Mesa (master): anv: Use blorp for VkCmdFillBuffer

Jason Ekstrand jekstrand at kemper.freedesktop.org
Wed Oct 5 16:33:56 UTC 2016


Module: Mesa
Branch: master
Commit: f027609a64dffbe09fdf4b24fed4bcdc8e0cafb2
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=f027609a64dffbe09fdf4b24fed4bcdc8e0cafb2

Author: Jason Ekstrand <jason.ekstrand at intel.com>
Date:   Sun Sep 25 08:44:40 2016 -0700

anv: Use blorp for VkCmdFillBuffer

Signed-off-by: Jason Ekstrand <jason at jlekstrand.net>
Reviewed-by: Nanley Chery <nanley.g.chery at intel.com>

---

 src/intel/vulkan/anv_blorp.c      | 106 +++++++++++++++++++++++++++++----
 src/intel/vulkan/anv_meta_clear.c | 120 --------------------------------------
 2 files changed, 96 insertions(+), 130 deletions(-)

diff --git a/src/intel/vulkan/anv_blorp.c b/src/intel/vulkan/anv_blorp.c
index cb61070..f149f84 100644
--- a/src/intel/vulkan/anv_blorp.c
+++ b/src/intel/vulkan/anv_blorp.c
@@ -480,6 +480,20 @@ void anv_CmdBlitImage(
    blorp_batch_finish(&batch);
 }
 
+static enum isl_format
+isl_format_for_size(unsigned size_B)
+{
+   switch (size_B) {
+   case 1:  return ISL_FORMAT_R8_UINT;
+   case 2:  return ISL_FORMAT_R8G8_UINT;
+   case 4:  return ISL_FORMAT_R8G8B8A8_UINT;
+   case 8:  return ISL_FORMAT_R16G16B16A16_UINT;
+   case 16: return ISL_FORMAT_R32G32B32A32_UINT;
+   default:
+      unreachable("Not a power-of-two format size");
+   }
+}
+
 static void
 do_buffer_copy(struct blorp_batch *batch,
                struct anv_bo *src, uint64_t src_offset,
@@ -491,16 +505,7 @@ do_buffer_copy(struct blorp_batch *batch,
    /* The actual format we pick doesn't matter as blorp will throw it away.
     * The only thing that actually matters is the size.
     */
-   enum isl_format format;
-   switch (block_size) {
-   case 1:  format = ISL_FORMAT_R8_UINT;              break;
-   case 2:  format = ISL_FORMAT_R8G8_UINT;            break;
-   case 4:  format = ISL_FORMAT_R8G8B8A8_UNORM;       break;
-   case 8:  format = ISL_FORMAT_R16G16B16A16_UNORM;   break;
-   case 16: format = ISL_FORMAT_R32G32B32A32_UINT;    break;
-   default:
-      unreachable("Not a power-of-two format size");
-   }
+   enum isl_format format = isl_format_for_size(block_size);
 
    struct isl_surf surf;
    isl_surf_init(&device->isl_dev, &surf,
@@ -667,6 +672,87 @@ void anv_CmdUpdateBuffer(
    blorp_batch_finish(&batch);
 }
 
+void anv_CmdFillBuffer(
+    VkCommandBuffer                             commandBuffer,
+    VkBuffer                                    dstBuffer,
+    VkDeviceSize                                dstOffset,
+    VkDeviceSize                                fillSize,
+    uint32_t                                    data)
+{
+   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
+   ANV_FROM_HANDLE(anv_buffer, dst_buffer, dstBuffer);
+   struct blorp_surf surf;
+   struct isl_surf isl_surf;
+
+   struct blorp_batch batch;
+   blorp_batch_init(&cmd_buffer->device->blorp, &batch, cmd_buffer);
+
+   if (fillSize == VK_WHOLE_SIZE) {
+      fillSize = dst_buffer->size - dstOffset;
+      /* Make sure fillSize is a multiple of 4 */
+      fillSize &= ~3ull;
+   }
+
+   /* First, we compute the biggest format that can be used with the
+    * given offsets and size.
+    */
+   int bs = 16;
+   bs = gcd_pow2_u64(bs, dstOffset);
+   bs = gcd_pow2_u64(bs, fillSize);
+   enum isl_format isl_format = isl_format_for_size(bs);
+
+   union isl_color_value color = {
+      .u32 = { data, data, data, data },
+   };
+
+   const uint64_t max_fill_size = MAX_SURFACE_DIM * MAX_SURFACE_DIM * bs;
+   while (fillSize >= max_fill_size) {
+      get_blorp_surf_for_anv_buffer(cmd_buffer->device,
+                                    dst_buffer, dstOffset,
+                                    MAX_SURFACE_DIM, MAX_SURFACE_DIM,
+                                    MAX_SURFACE_DIM * bs, isl_format,
+                                    &surf, &isl_surf);
+
+      blorp_clear(&batch, &surf, isl_format, ISL_SWIZZLE_IDENTITY,
+                  0, 0, 1, 0, 0, MAX_SURFACE_DIM, MAX_SURFACE_DIM,
+                  color, NULL);
+      fillSize -= max_fill_size;
+      dstOffset += max_fill_size;
+   }
+
+   uint64_t height = fillSize / (MAX_SURFACE_DIM * bs);
+   assert(height < MAX_SURFACE_DIM);
+   if (height != 0) {
+      const uint64_t rect_fill_size = height * MAX_SURFACE_DIM * bs;
+      get_blorp_surf_for_anv_buffer(cmd_buffer->device,
+                                    dst_buffer, dstOffset,
+                                    MAX_SURFACE_DIM, height,
+                                    MAX_SURFACE_DIM * bs, isl_format,
+                                    &surf, &isl_surf);
+
+      blorp_clear(&batch, &surf, isl_format, ISL_SWIZZLE_IDENTITY,
+                  0, 0, 1, 0, 0, MAX_SURFACE_DIM, height,
+                  color, NULL);
+      fillSize -= rect_fill_size;
+      dstOffset += rect_fill_size;
+   }
+
+   if (fillSize != 0) {
+      const uint32_t width = fillSize / bs;
+      get_blorp_surf_for_anv_buffer(cmd_buffer->device,
+                                    dst_buffer, dstOffset,
+                                    width, 1,
+                                    width * bs, isl_format,
+                                    &surf, &isl_surf);
+
+      blorp_clear(&batch, &surf, isl_format, ISL_SWIZZLE_IDENTITY,
+                  0, 0, 1, 0, 0, width, 1,
+                  color, NULL);
+   }
+
+   blorp_batch_finish(&batch);
+}
+
 void anv_CmdClearColorImage(
     VkCommandBuffer                             commandBuffer,
     VkImage                                     _image,
diff --git a/src/intel/vulkan/anv_meta_clear.c b/src/intel/vulkan/anv_meta_clear.c
index fd0797f..5579454 100644
--- a/src/intel/vulkan/anv_meta_clear.c
+++ b/src/intel/vulkan/anv_meta_clear.c
@@ -944,123 +944,3 @@ void anv_CmdClearAttachments(
 
    meta_clear_end(&saved_state, cmd_buffer);
 }
-
-static void
-do_buffer_fill(struct anv_cmd_buffer *cmd_buffer,
-               struct anv_bo *dest, uint64_t dest_offset,
-               int width, int height, VkFormat fill_format, uint32_t data)
-{
-   VkDevice vk_device = anv_device_to_handle(cmd_buffer->device);
-
-   VkImageCreateInfo image_info = {
-      .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
-      .imageType = VK_IMAGE_TYPE_2D,
-      .format = fill_format,
-      .extent = {
-         .width = width,
-         .height = height,
-         .depth = 1,
-      },
-      .mipLevels = 1,
-      .arrayLayers = 1,
-      .samples = 1,
-      .tiling = VK_IMAGE_TILING_LINEAR,
-      .usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
-      .flags = 0,
-   };
-
-   VkImage dest_image;
-   image_info.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
-   anv_CreateImage(vk_device, &image_info,
-                   &cmd_buffer->pool->alloc, &dest_image);
-
-   /* We could use a vk call to bind memory, but that would require
-    * creating a dummy memory object etc. so there's really no point.
-    */
-   anv_image_from_handle(dest_image)->bo = dest;
-   anv_image_from_handle(dest_image)->offset = dest_offset;
-
-   const VkClearValue clear_value = {
-      .color = {
-         .uint32 = { data, data, data, data }
-      }
-   };
-
-   const VkImageSubresourceRange range = {
-      .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
-      .baseMipLevel = 0,
-      .levelCount = 1,
-      .baseArrayLayer = 0,
-      .layerCount = 1,
-   };
-
-   anv_cmd_clear_image(cmd_buffer, anv_image_from_handle(dest_image),
-                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
-                       clear_value, 1, &range);
-}
-
-void anv_CmdFillBuffer(
-    VkCommandBuffer                             commandBuffer,
-    VkBuffer                                    dstBuffer,
-    VkDeviceSize                                dstOffset,
-    VkDeviceSize                                fillSize,
-    uint32_t                                    data)
-{
-   ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
-   ANV_FROM_HANDLE(anv_buffer, dst_buffer, dstBuffer);
-   struct anv_meta_saved_state saved_state;
-
-   meta_clear_begin(&saved_state, cmd_buffer);
-
-   if (fillSize == VK_WHOLE_SIZE) {
-      fillSize = dst_buffer->size - dstOffset;
-      /* Make sure fillSize is a multiple of 4 */
-      fillSize -= fillSize & 3;
-   }
-
-   VkFormat format;
-   int bs;
-   if ((fillSize & 15) == 0 && (dstOffset & 15) == 0) {
-      format = VK_FORMAT_R32G32B32A32_UINT;
-      bs = 16;
-   } else if ((fillSize & 7) == 0 && (dstOffset & 15) == 0) {
-      format = VK_FORMAT_R32G32_UINT;
-      bs = 8;
-   } else {
-      assert((fillSize & 3) == 0 && (dstOffset & 3) == 0);
-      format = VK_FORMAT_R32_UINT;
-      bs = 4;
-   }
-
-   /* This is maximum possible width/height our HW can handle */
-   const uint64_t max_surface_dim = 1 << 14;
-
-   /* First, we make a bunch of max-sized copies */
-   const uint64_t max_fill_size = max_surface_dim * max_surface_dim * bs;
-   while (fillSize > max_fill_size) {
-      do_buffer_fill(cmd_buffer, dst_buffer->bo,
-                     dst_buffer->offset + dstOffset,
-                     max_surface_dim, max_surface_dim, format, data);
-      fillSize -= max_fill_size;
-      dstOffset += max_fill_size;
-   }
-
-   uint64_t height = fillSize / (max_surface_dim * bs);
-   assert(height < max_surface_dim);
-   if (height != 0) {
-      const uint64_t rect_fill_size = height * max_surface_dim * bs;
-      do_buffer_fill(cmd_buffer, dst_buffer->bo,
-                     dst_buffer->offset + dstOffset,
-                     max_surface_dim, height, format, data);
-      fillSize -= rect_fill_size;
-      dstOffset += rect_fill_size;
-   }
-
-   if (fillSize != 0) {
-      do_buffer_fill(cmd_buffer, dst_buffer->bo,
-                     dst_buffer->offset + dstOffset,
-                     fillSize / bs, 1, format, data);
-   }
-
-   meta_clear_end(&saved_state, cmd_buffer);
-}




More information about the mesa-commit mailing list