From 4ee80e8816091869943d98cbe261c49406bb8039 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Wed, 30 Mar 2016 15:03:34 -0700 Subject: [PATCH] anv/blit2d: Refactor in preparation for different src/dst types Reviewed-by: Nanley Chery --- src/intel/vulkan/anv_meta_blit2d.c | 349 +++++++++++++++++++---------- src/intel/vulkan/anv_private.h | 9 +- 2 files changed, 238 insertions(+), 120 deletions(-) diff --git a/src/intel/vulkan/anv_meta_blit2d.c b/src/intel/vulkan/anv_meta_blit2d.c index 22b763aee2d..8e63eee462d 100644 --- a/src/intel/vulkan/anv_meta_blit2d.c +++ b/src/intel/vulkan/anv_meta_blit2d.c @@ -24,6 +24,44 @@ #include "anv_meta.h" #include "nir/nir_builder.h" +enum blit2d_src_type { + /* We can make a "normal" image view of this source and just texture + * from it like you would in any other shader. + */ + BLIT2D_SRC_TYPE_NORMAL, + + /* The source is W-tiled and we need to detile manually in the shader. + * This will work on any platform but is needed for all W-tiled sources + * prior to Broadwell. + */ + BLIT2D_SRC_TYPE_W_DETILE, + + BLIT2D_NUM_SRC_TYPES, +}; + +enum blit2d_dst_type { + /* We can bind this destination as a "normal" render target and render + * to it just like you would anywhere else. + */ + BLIT2D_DST_TYPE_NORMAL, + + /* The destination is W-tiled and we need to do the tiling manually in + * the shader. This is required for all W-tiled destinations. + * + * Sky Lake adds a feature for providing explicit stencil values in the + * shader but mesa doesn't support that yet so neither do we. + */ + BLIT2D_DST_TYPE_W_TILE, + + /* The destination has a 3-channel RGB format. Since we can't render to + * non-power-of-two textures, we have to bind it as a red texture and + * select the correct component for the given red pixel in the shader. + */ + BLIT2D_DST_TYPE_RGB, + + BLIT2D_NUM_DST_TYPES, +}; + static VkFormat vk_format_for_size(int bs) { @@ -139,6 +177,7 @@ struct blit2d_src_temps { static void blit2d_bind_src(struct anv_cmd_buffer *cmd_buffer, struct anv_meta_blit2d_surf *src, + enum blit2d_src_type src_type, struct anv_meta_blit2d_rect *rect, struct blit2d_src_temps *tmp) { @@ -199,6 +238,7 @@ blit2d_bind_src(struct anv_cmd_buffer *cmd_buffer, static void blit2d_unbind_src(struct anv_cmd_buffer *cmd_buffer, + enum blit2d_src_type src_type, struct blit2d_src_temps *tmp) { anv_DestroyDescriptorPool(anv_device_to_handle(cmd_buffer->device), @@ -222,12 +262,27 @@ anv_meta_begin_blit2d(struct anv_cmd_buffer *cmd_buffer, (1 << VK_DYNAMIC_STATE_VIEWPORT)); } -void -anv_meta_blit2d(struct anv_cmd_buffer *cmd_buffer, - struct anv_meta_blit2d_surf *src, - struct anv_meta_blit2d_surf *dst, - unsigned num_rects, - struct anv_meta_blit2d_rect *rects) +static void +bind_pipeline(struct anv_cmd_buffer *cmd_buffer, + enum blit2d_src_type src_type, + enum blit2d_dst_type dst_type) +{ + VkPipeline pipeline = + cmd_buffer->device->meta_state.blit2d.pipelines[src_type][dst_type]; + + if (cmd_buffer->state.pipeline != anv_pipeline_from_handle(pipeline)) { + anv_CmdBindPipeline(anv_cmd_buffer_to_handle(cmd_buffer), + VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); + } +} + +static void +anv_meta_blit2d_normal_dst(struct anv_cmd_buffer *cmd_buffer, + struct anv_meta_blit2d_surf *src, + enum blit2d_src_type src_type, + struct anv_meta_blit2d_surf *dst, + unsigned num_rects, + struct anv_meta_blit2d_rect *rects) { struct anv_device *device = cmd_buffer->device; VkDevice vk_device = anv_device_to_handle(cmd_buffer->device); @@ -235,7 +290,7 @@ anv_meta_blit2d(struct anv_cmd_buffer *cmd_buffer, for (unsigned r = 0; r < num_rects; ++r) { struct blit2d_src_temps src_temps; - blit2d_bind_src(cmd_buffer, src, &rects[r], &src_temps); + blit2d_bind_src(cmd_buffer, src, src_type, &rects[r], &src_temps); VkImage dst_img; struct anv_image_view dst_iview; @@ -334,12 +389,7 @@ anv_meta_blit2d(struct anv_cmd_buffer *cmd_buffer, .pClearValues = NULL, }, VK_SUBPASS_CONTENTS_INLINE); - VkPipeline pipeline = device->meta_state.blit2d.pipeline_2d_src; - - if (cmd_buffer->state.pipeline != anv_pipeline_from_handle(pipeline)) { - anv_CmdBindPipeline(anv_cmd_buffer_to_handle(cmd_buffer), - VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); - } + bind_pipeline(cmd_buffer, src_type, BLIT2D_DST_TYPE_NORMAL); anv_CmdSetViewport(anv_cmd_buffer_to_handle(cmd_buffer), 0, 1, &(VkViewport) { @@ -358,12 +408,39 @@ anv_meta_blit2d(struct anv_cmd_buffer *cmd_buffer, /* At the point where we emit the draw call, all data from the * descriptor sets, etc. has been used. We are free to delete it. */ - blit2d_unbind_src(cmd_buffer, &src_temps); + blit2d_unbind_src(cmd_buffer, src_type, &src_temps); anv_DestroyFramebuffer(vk_device, fb, &cmd_buffer->pool->alloc); anv_DestroyImage(vk_device, dst_img, &cmd_buffer->pool->alloc); } } +void +anv_meta_blit2d(struct anv_cmd_buffer *cmd_buffer, + struct anv_meta_blit2d_surf *src, + struct anv_meta_blit2d_surf *dst, + unsigned num_rects, + struct anv_meta_blit2d_rect *rects) +{ + enum blit2d_src_type src_type; + if (src->tiling == ISL_TILING_W && cmd_buffer->device->info.gen < 8) { + src_type = BLIT2D_SRC_TYPE_W_DETILE; + } else { + src_type = BLIT2D_SRC_TYPE_NORMAL; + } + + if (dst->tiling == ISL_TILING_W) { + assert(dst->bs == 1); + anv_finishme("Blitting to w-tiled destinations not yet supported"); + return; + } else if (dst->bs % 3 == 0) { + anv_finishme("Blitting to RGB destinations not yet supported"); + return; + } else { + assert(util_is_power_of_two(dst->bs)); + anv_meta_blit2d_normal_dst(cmd_buffer, src, src_type, dst, + num_rects, rects); + } +} static nir_shader * build_nir_vertex_shader(void) @@ -467,12 +544,6 @@ anv_device_finish_meta_blit2d_state(struct anv_device *device) &device->meta_state.alloc); } - if (device->meta_state.blit2d.pipeline_2d_src) { - anv_DestroyPipeline(anv_device_to_handle(device), - device->meta_state.blit2d.pipeline_2d_src, - &device->meta_state.alloc); - } - if (device->meta_state.blit2d.img_p_layout) { anv_DestroyPipelineLayout(anv_device_to_handle(device), device->meta_state.blit2d.img_p_layout, @@ -496,101 +567,47 @@ anv_device_finish_meta_blit2d_state(struct anv_device *device) device->meta_state.blit2d.buf_ds_layout, &device->meta_state.alloc); } + + for (unsigned src = 0; src < BLIT2D_NUM_SRC_TYPES; src++) { + for (unsigned dst = 0; dst < BLIT2D_NUM_DST_TYPES; dst++) { + if (device->meta_state.blit2d.pipelines[src][dst]) { + anv_DestroyPipeline(anv_device_to_handle(device), + device->meta_state.blit2d.pipelines[src][dst], + &device->meta_state.alloc); + } + } + } } -VkResult -anv_device_init_meta_blit2d_state(struct anv_device *device) +static VkResult +blit2d_init_pipeline(struct anv_device *device, + enum blit2d_src_type src_type, + enum blit2d_dst_type dst_type) { VkResult result; - zero(device->meta_state.blit2d); - - result = anv_CreateRenderPass(anv_device_to_handle(device), - &(VkRenderPassCreateInfo) { - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, - .attachmentCount = 1, - .pAttachments = &(VkAttachmentDescription) { - .format = VK_FORMAT_UNDEFINED, /* Our shaders don't care */ - .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD, - .storeOp = VK_ATTACHMENT_STORE_OP_STORE, - .initialLayout = VK_IMAGE_LAYOUT_GENERAL, - .finalLayout = VK_IMAGE_LAYOUT_GENERAL, - }, - .subpassCount = 1, - .pSubpasses = &(VkSubpassDescription) { - .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, - .inputAttachmentCount = 0, - .colorAttachmentCount = 1, - .pColorAttachments = &(VkAttachmentReference) { - .attachment = 0, - .layout = VK_IMAGE_LAYOUT_GENERAL, - }, - .pResolveAttachments = NULL, - .pDepthStencilAttachment = &(VkAttachmentReference) { - .attachment = VK_ATTACHMENT_UNUSED, - .layout = VK_IMAGE_LAYOUT_GENERAL, - }, - .preserveAttachmentCount = 1, - .pPreserveAttachments = (uint32_t[]) { 0 }, - }, - .dependencyCount = 0, - }, &device->meta_state.alloc, &device->meta_state.blit2d.render_pass); - if (result != VK_SUCCESS) - goto fail; - - result = anv_CreateDescriptorSetLayout(anv_device_to_handle(device), - &(VkDescriptorSetLayoutCreateInfo) { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, - .bindingCount = 1, - .pBindings = (VkDescriptorSetLayoutBinding[]) { - { - .binding = 0, - .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, - .descriptorCount = 1, - .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, - .pImmutableSamplers = NULL - }, - } - }, &device->meta_state.alloc, &device->meta_state.blit2d.img_ds_layout); - if (result != VK_SUCCESS) - goto fail; - - result = anv_CreatePipelineLayout(anv_device_to_handle(device), - &(VkPipelineLayoutCreateInfo) { - .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, - .setLayoutCount = 1, - .pSetLayouts = &device->meta_state.blit2d.img_ds_layout, - }, - &device->meta_state.alloc, &device->meta_state.blit2d.img_p_layout); - if (result != VK_SUCCESS) - goto fail; - - result = anv_CreateDescriptorSetLayout(anv_device_to_handle(device), - &(VkDescriptorSetLayoutCreateInfo) { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, - .bindingCount = 1, - .pBindings = (VkDescriptorSetLayoutBinding[]) { - { - .binding = 0, - .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, - .descriptorCount = 1, - .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, - .pImmutableSamplers = NULL - }, - } - }, &device->meta_state.alloc, &device->meta_state.blit2d.buf_ds_layout); - if (result != VK_SUCCESS) - goto fail; + texel_fetch_build_func src_func; + switch (src_type) { + case BLIT2D_SRC_TYPE_NORMAL: + src_func = build_nir_texel_fetch; + break; + case BLIT2D_SRC_TYPE_W_DETILE: + /* Not yet supported */ + default: + return VK_SUCCESS; + } - result = anv_CreatePipelineLayout(anv_device_to_handle(device), - &(VkPipelineLayoutCreateInfo) { - .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, - .setLayoutCount = 1, - .pSetLayouts = &device->meta_state.blit2d.buf_ds_layout, - }, - &device->meta_state.alloc, &device->meta_state.blit2d.buf_p_layout); - if (result != VK_SUCCESS) - goto fail; + struct anv_shader_module fs = { .nir = NULL }; + switch (dst_type) { + case BLIT2D_DST_TYPE_NORMAL: + fs.nir = build_nir_copy_fragment_shader(device, src_func); + break; + case BLIT2D_DST_TYPE_W_TILE: + case BLIT2D_DST_TYPE_RGB: + /* Not yet supported */ + default: + return VK_SUCCESS; + } /* We don't use a vertex shader for blitting, but instead build and pass * the VUEs directly to the rasterization backend. However, we do need @@ -601,10 +618,6 @@ anv_device_init_meta_blit2d_state(struct anv_device *device) .nir = build_nir_vertex_shader(), }; - struct anv_shader_module fs_2d = { - .nir = build_nir_copy_fragment_shader(device, build_nir_texel_fetch), - }; - VkPipelineVertexInputStateCreateInfo vi_create_info = { .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, .vertexBindingDescriptionCount = 2, @@ -656,7 +669,7 @@ anv_device_init_meta_blit2d_state(struct anv_device *device) }, { .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, .stage = VK_SHADER_STAGE_FRAGMENT_BIT, - .module = VK_NULL_HANDLE, /* TEMPLATE VALUE! FILL ME IN! */ + .module = anv_shader_module_to_handle(&fs), .pName = "main", .pSpecializationInfo = NULL }, @@ -731,18 +744,120 @@ anv_device_init_meta_blit2d_state(struct anv_device *device) .use_rectlist = true }; - pipeline_shader_stages[1].module = anv_shader_module_to_handle(&fs_2d); result = anv_graphics_pipeline_create(anv_device_to_handle(device), VK_NULL_HANDLE, &vk_pipeline_info, &anv_pipeline_info, - &device->meta_state.alloc, &device->meta_state.blit2d.pipeline_2d_src); + &device->meta_state.alloc, + &device->meta_state.blit2d.pipelines[src_type][dst_type]); ralloc_free(vs.nir); - ralloc_free(fs_2d.nir); + ralloc_free(fs.nir); + + return result; +} + +VkResult +anv_device_init_meta_blit2d_state(struct anv_device *device) +{ + VkResult result; + zero(device->meta_state.blit2d); + + result = anv_CreateRenderPass(anv_device_to_handle(device), + &(VkRenderPassCreateInfo) { + .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, + .attachmentCount = 1, + .pAttachments = &(VkAttachmentDescription) { + .format = VK_FORMAT_UNDEFINED, /* Our shaders don't care */ + .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD, + .storeOp = VK_ATTACHMENT_STORE_OP_STORE, + .initialLayout = VK_IMAGE_LAYOUT_GENERAL, + .finalLayout = VK_IMAGE_LAYOUT_GENERAL, + }, + .subpassCount = 1, + .pSubpasses = &(VkSubpassDescription) { + .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, + .inputAttachmentCount = 0, + .colorAttachmentCount = 1, + .pColorAttachments = &(VkAttachmentReference) { + .attachment = 0, + .layout = VK_IMAGE_LAYOUT_GENERAL, + }, + .pResolveAttachments = NULL, + .pDepthStencilAttachment = &(VkAttachmentReference) { + .attachment = VK_ATTACHMENT_UNUSED, + .layout = VK_IMAGE_LAYOUT_GENERAL, + }, + .preserveAttachmentCount = 1, + .pPreserveAttachments = (uint32_t[]) { 0 }, + }, + .dependencyCount = 0, + }, &device->meta_state.alloc, &device->meta_state.blit2d.render_pass); + if (result != VK_SUCCESS) + goto fail; + + result = anv_CreateDescriptorSetLayout(anv_device_to_handle(device), + &(VkDescriptorSetLayoutCreateInfo) { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + .bindingCount = 1, + .pBindings = (VkDescriptorSetLayoutBinding[]) { + { + .binding = 0, + .descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, + .descriptorCount = 1, + .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, + .pImmutableSamplers = NULL + }, + } + }, &device->meta_state.alloc, &device->meta_state.blit2d.img_ds_layout); if (result != VK_SUCCESS) goto fail; + result = anv_CreatePipelineLayout(anv_device_to_handle(device), + &(VkPipelineLayoutCreateInfo) { + .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + .setLayoutCount = 1, + .pSetLayouts = &device->meta_state.blit2d.img_ds_layout, + }, + &device->meta_state.alloc, &device->meta_state.blit2d.img_p_layout); + if (result != VK_SUCCESS) + goto fail; + + result = anv_CreateDescriptorSetLayout(anv_device_to_handle(device), + &(VkDescriptorSetLayoutCreateInfo) { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + .bindingCount = 1, + .pBindings = (VkDescriptorSetLayoutBinding[]) { + { + .binding = 0, + .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, + .descriptorCount = 1, + .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, + .pImmutableSamplers = NULL + }, + } + }, &device->meta_state.alloc, &device->meta_state.blit2d.buf_ds_layout); + if (result != VK_SUCCESS) + goto fail; + + result = anv_CreatePipelineLayout(anv_device_to_handle(device), + &(VkPipelineLayoutCreateInfo) { + .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + .setLayoutCount = 1, + .pSetLayouts = &device->meta_state.blit2d.buf_ds_layout, + }, + &device->meta_state.alloc, &device->meta_state.blit2d.buf_p_layout); + if (result != VK_SUCCESS) + goto fail; + + for (unsigned src = 0; src < BLIT2D_NUM_SRC_TYPES; src++) { + for (unsigned dst = 0; dst < BLIT2D_NUM_DST_TYPES; dst++) { + result = blit2d_init_pipeline(device, src, dst); + if (result != VK_SUCCESS) + goto fail; + } + } + return VK_SUCCESS; fail: diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index 7c140a33cb7..1a18dd15e65 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -609,13 +609,16 @@ struct anv_meta_state { struct { VkRenderPass render_pass; - /** Pipeline that copies from a 2D image. */ - VkPipeline pipeline_2d_src; - VkPipelineLayout img_p_layout; VkDescriptorSetLayout img_ds_layout; VkPipelineLayout buf_p_layout; VkDescriptorSetLayout buf_ds_layout; + + /* Pipelines indexed by source and destination type. See the + * blit2d_src_type and blit2d_dst_type enums in anv_meta_blit2d.c to + * see what these mean. + */ + VkPipeline pipelines[2][3]; } blit2d; struct { -- 2.30.2