anv/blit2d: Refactor in preparation for different src/dst types
authorJason Ekstrand <jason.ekstrand@intel.com>
Wed, 30 Mar 2016 22:03:34 +0000 (15:03 -0700)
committerJason Ekstrand <jason.ekstrand@intel.com>
Fri, 8 Apr 2016 22:57:52 +0000 (15:57 -0700)
Reviewed-by: Nanley Chery <nanley.g.chery@intel.com>
src/intel/vulkan/anv_meta_blit2d.c
src/intel/vulkan/anv_private.h

index 22b763aee2d267416b366d45ed0730998aa8e46d..8e63eee462df9706f97e1447af874c247166f783 100644 (file)
 #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:
index 7c140a33cb745a90dceb6494f22570d41f19c086..1a18dd15e659ce74feb26535cb155add970ad86c 100644 (file)
@@ -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 {