Anvil already had code to copy between two buffer objects in the most
efficient way possible, using large bpp copies, then smaller bpp copies.

This patch moves that logic into BLORP as blorp_buffer_copy(), so we
can reuse it in i965 as well.
---
 src/intel/blorp/blorp.h      |   6 ++
 src/intel/blorp/blorp_blit.c | 128 +++++++++++++++++++++++++++++++++++++++++++
 src/intel/vulkan/anv_blorp.c | 104 +++--------------------------------
 3 files changed, 141 insertions(+), 97 deletions(-)

diff --git a/src/intel/blorp/blorp.h b/src/intel/blorp/blorp.h
index 4d9a44b0926..951a97f5daa 100644
--- a/src/intel/blorp/blorp.h
+++ b/src/intel/blorp/blorp.h
@@ -132,6 +132,12 @@ blorp_copy(struct blorp_batch *batch,
            uint32_t dst_x, uint32_t dst_y,
            uint32_t src_width, uint32_t src_height);
 
+void
+blorp_buffer_copy(struct blorp_batch *batch,
+                  void *src_bo, uint64_t src_offset,
+                  void *dst_bo, uint64_t dst_offset,
+                  uint64_t size);
+
 void
 blorp_fast_clear(struct blorp_batch *batch,
                  const struct blorp_surf *surf, enum isl_format format,
diff --git a/src/intel/blorp/blorp_blit.c b/src/intel/blorp/blorp_blit.c
index 35008cbbb0a..998fd9b6d39 100644
--- a/src/intel/blorp/blorp_blit.c
+++ b/src/intel/blorp/blorp_blit.c
@@ -2513,3 +2513,131 @@ blorp_copy(struct blorp_batch *batch,
 
    do_blorp_blit(batch, &params, &wm_prog_key, &coords);
 }
+
+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");
+   }
+}
+
+/**
+ * Returns the greatest common divisor of a and b that is a power of two.
+ */
+static uint64_t
+gcd_pow2_u64(uint64_t a, uint64_t b)
+{
+   assert(a > 0 || b > 0);
+
+   unsigned a_log2 = ffsll(a) - 1;
+   unsigned b_log2 = ffsll(b) - 1;
+
+   /* If either a or b is 0, then a_log2 or b_log2 till be UINT_MAX in which
+    * case, the MIN2() will take the other one.  If both are 0 then we will
+    * hit the assert above.
+    */
+   return 1 << MIN2(a_log2, b_log2);
+}
+
+static void
+do_buffer_copy(struct blorp_batch *batch,
+               void *src_bo, uint64_t src_offset,
+               void *dst_bo, uint64_t dst_offset,
+               int width, int height, int block_size)
+{
+   /* 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 = isl_format_for_size(block_size);
+
+   UNUSED bool ok;
+   struct isl_surf surf;
+   ok = isl_surf_init(batch->blorp->isl_dev, &surf,
+                      .dim = ISL_SURF_DIM_2D,
+                      .format = format,
+                      .width = width,
+                      .height = height,
+                      .depth = 1,
+                      .levels = 1,
+                      .array_len = 1,
+                      .samples = 1,
+                      .row_pitch = width * block_size,
+                      .usage = ISL_SURF_USAGE_TEXTURE_BIT |
+                               ISL_SURF_USAGE_RENDER_TARGET_BIT,
+                      .tiling_flags = ISL_TILING_LINEAR_BIT);
+   assert(ok);
+
+   struct blorp_surf src_blorp_surf = {
+      .surf = &surf,
+      .addr = {
+         .buffer = src_bo,
+         .offset = src_offset,
+      },
+   };
+
+   struct blorp_surf dst_blorp_surf = {
+      .surf = &surf,
+      .addr = {
+         .buffer = dst_bo,
+         .offset = dst_offset,
+      },
+   };
+
+   blorp_copy(batch, &src_blorp_surf, 0, 0, &dst_blorp_surf, 0, 0,
+              0, 0, 0, 0, width, height);
+}
+
+/* This is maximum possible width/height our HW can handle */
+#define MAX_SURFACE_DIM (1ull << 14)
+
+void
+blorp_buffer_copy(struct blorp_batch *batch,
+                  void *src_bo, uint64_t src_offset,
+                  void *dst_bo, uint64_t dst_offset,
+                  uint64_t size)
+{
+   uint64_t copy_size = size;
+
+   /* First, we compute the biggest format that can be used with the
+    * given offsets and size.
+    */
+   int bs = 16;
+   bs = gcd_pow2_u64(bs, src_offset);
+   bs = gcd_pow2_u64(bs, dst_offset);
+   bs = gcd_pow2_u64(bs, size);
+
+   /* First, we make a bunch of max-sized copies */
+   uint64_t max_copy_size = MAX_SURFACE_DIM * MAX_SURFACE_DIM * bs;
+   while (copy_size >= max_copy_size) {
+      do_buffer_copy(batch, src_bo, src_offset, dst_bo, dst_offset,
+                     MAX_SURFACE_DIM, MAX_SURFACE_DIM, bs);
+      copy_size -= max_copy_size;
+      src_offset += max_copy_size;
+      dst_offset += max_copy_size;
+   }
+
+   /* Now make a max-width copy */
+   uint64_t height = copy_size / (MAX_SURFACE_DIM * bs);
+   assert(height < MAX_SURFACE_DIM);
+   if (height != 0) {
+      uint64_t rect_copy_size = height * MAX_SURFACE_DIM * bs;
+      do_buffer_copy(batch, src_bo, src_offset, dst_bo, dst_offset,
+                     MAX_SURFACE_DIM, height, bs);
+      copy_size -= rect_copy_size;
+      src_offset += rect_copy_size;
+      dst_offset += rect_copy_size;
+   }
+
+   /* Finally, make a small copy to finish it off */
+   if (copy_size != 0) {
+      do_buffer_copy(batch, src_bo, src_offset, dst_bo, dst_offset,
+                     copy_size / bs, 1, bs);
+   }
+}
diff --git a/src/intel/vulkan/anv_blorp.c b/src/intel/vulkan/anv_blorp.c
index 860e50ac487..780cda84641 100644
--- a/src/intel/vulkan/anv_blorp.c
+++ b/src/intel/vulkan/anv_blorp.c
@@ -541,56 +541,6 @@ isl_format_for_size(unsigned size_B)
    }
 }
 
-static void
-do_buffer_copy(struct blorp_batch *batch,
-               struct anv_bo *src, uint64_t src_offset,
-               struct anv_bo *dst, uint64_t dst_offset,
-               int width, int height, int block_size)
-{
-   struct anv_device *device = batch->blorp->driver_ctx;
-
-   /* 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 = isl_format_for_size(block_size);
-
-   UNUSED bool ok;
-   struct isl_surf surf;
-   ok = isl_surf_init(&device->isl_dev, &surf,
-                      .dim = ISL_SURF_DIM_2D,
-                      .format = format,
-                      .width = width,
-                      .height = height,
-                      .depth = 1,
-                      .levels = 1,
-                      .array_len = 1,
-                      .samples = 1,
-                      .row_pitch = width * block_size,
-                      .usage = ISL_SURF_USAGE_TEXTURE_BIT |
-                               ISL_SURF_USAGE_RENDER_TARGET_BIT,
-                      .tiling_flags = ISL_TILING_LINEAR_BIT);
-   assert(ok);
-
-   struct blorp_surf src_blorp_surf = {
-      .surf = &surf,
-      .addr = {
-         .buffer = src,
-         .offset = src_offset,
-      },
-   };
-
-   struct blorp_surf dst_blorp_surf = {
-      .surf = &surf,
-      .addr = {
-         .buffer = dst,
-         .offset = dst_offset,
-      },
-   };
-
-   blorp_copy(batch, &src_blorp_surf, 0, 0, &dst_blorp_surf, 0, 0,
-              0, 0, 0, 0, width, height);
-}
-
 /**
  * Returns the greatest common divisor of a and b that is a power of two.
  */
@@ -631,44 +581,8 @@ void anv_CmdCopyBuffer(
       uint64_t dst_offset = dst_buffer->offset + pRegions[r].dstOffset;
       uint64_t copy_size = pRegions[r].size;
 
-      /* First, we compute the biggest format that can be used with the
-       * given offsets and size.
-       */
-      int bs = 16;
-      bs = gcd_pow2_u64(bs, src_offset);
-      bs = gcd_pow2_u64(bs, dst_offset);
-      bs = gcd_pow2_u64(bs, pRegions[r].size);
-
-      /* First, we make a bunch of max-sized copies */
-      uint64_t max_copy_size = MAX_SURFACE_DIM * MAX_SURFACE_DIM * bs;
-      while (copy_size >= max_copy_size) {
-         do_buffer_copy(&batch, src_buffer->bo, src_offset,
-                        dst_buffer->bo, dst_offset,
-                        MAX_SURFACE_DIM, MAX_SURFACE_DIM, bs);
-         copy_size -= max_copy_size;
-         src_offset += max_copy_size;
-         dst_offset += max_copy_size;
-      }
-
-      /* Now make a max-width copy */
-      uint64_t height = copy_size / (MAX_SURFACE_DIM * bs);
-      assert(height < MAX_SURFACE_DIM);
-      if (height != 0) {
-         uint64_t rect_copy_size = height * MAX_SURFACE_DIM * bs;
-         do_buffer_copy(&batch, src_buffer->bo, src_offset,
-                        dst_buffer->bo, dst_offset,
-                        MAX_SURFACE_DIM, height, bs);
-         copy_size -= rect_copy_size;
-         src_offset += rect_copy_size;
-         dst_offset += rect_copy_size;
-      }
-
-      /* Finally, make a small copy to finish it off */
-      if (copy_size != 0) {
-         do_buffer_copy(&batch, src_buffer->bo, src_offset,
-                        dst_buffer->bo, dst_offset,
-                        copy_size / bs, 1, bs);
-      }
+      blorp_buffer_copy(&batch, src_buffer->bo, src_offset,
+                        dst_buffer->bo, dst_offset, copy_size);
    }
 
    blorp_batch_finish(&batch);
@@ -710,15 +624,11 @@ void anv_CmdUpdateBuffer(
 
       anv_state_flush(cmd_buffer->device, tmp_data);
 
-      int bs = 16;
-      bs = gcd_pow2_u64(bs, dstOffset);
-      bs = gcd_pow2_u64(bs, copy_size);
-
-      do_buffer_copy(&batch,
-                     &cmd_buffer->device->dynamic_state_pool.block_pool.bo,
-                     tmp_data.offset,
-                     dst_buffer->bo, dst_buffer->offset + dstOffset,
-                     copy_size / bs, 1, bs);
+      blorp_buffer_copy(&batch,
+                        &cmd_buffer->device->dynamic_state_pool.block_pool.bo,
+                        tmp_data.offset,
+                        dst_buffer->bo, dst_buffer->offset + dstOffset,
+                        copy_size);
 
       dataSize -= copy_size;
       dstOffset += copy_size;
-- 
2.14.1

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to