[Mesa-dev] [PATCH 01/13] anv: Use blorp for VkCmdFillBuffer
Jason Ekstrand
jason at jlekstrand.net
Mon Sep 26 19:12:32 UTC 2016
On Sep 26, 2016 11:16 AM, "Nanley Chery" <nanleychery at gmail.com> wrote:
>
> 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 '>='.
Sure. Both work but >= is a bit clearer. Fixed locally.
> > + 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.
Sure. I mostly did it that way to match the other two callers of
get_blorp_surf_for_anv_buffer.
> -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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20160926/2b866b98/attachment-0001.html>
More information about the mesa-dev
mailing list