[Mesa-dev] [PATCH 01/13] anv: Use blorp for VkCmdFillBuffer

Nanley Chery nanleychery at gmail.com
Mon Sep 26 18:16:47 UTC 2016


On Sun, Sep 25, 2016 at 09:59:00AM -0700, Jason Ekstrand wrote:
> Signed-off-by: Jason Ekstrand <jason at jlekstrand.net>
> ---
>  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..f5a6c40 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) {
                      ^
                      This should be '>='.

> +      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,
                                       ^
				       fillSize could be used instead.

-Nanley

> +                                    &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);
> -}
> -- 
> 2.5.0.400.gff86faf
> 
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list