From: Jason Ekstrand Date: Sun, 25 Sep 2016 15:44:40 +0000 (-0700) Subject: anv: Use blorp for VkCmdFillBuffer X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f027609a64dffbe09fdf4b24fed4bcdc8e0cafb2;p=mesa.git anv: Use blorp for VkCmdFillBuffer Signed-off-by: Jason Ekstrand Reviewed-by: Nanley Chery --- diff --git a/src/intel/vulkan/anv_blorp.c b/src/intel/vulkan/anv_blorp.c index cb610708ab3..f149f849426 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 fd0797f31d7..5579454188f 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); -}