[Mesa-dev] [PATCH 01/13] anv: Use blorp for VkCmdFillBuffer
Jason Ekstrand
jason at jlekstrand.net
Sun Sep 25 16:59:00 UTC 2016
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) {
+ 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);
-}
--
2.5.0.400.gff86faf
More information about the mesa-dev
mailing list