anv/gpu_memcpy: Add a lighter-weight GPU memcpy function
authorNanley Chery <nanley.g.chery@intel.com>
Wed, 25 Jan 2017 22:54:39 +0000 (14:54 -0800)
committerJason Ekstrand <jason.ekstrand@intel.com>
Sun, 23 Jul 2017 03:12:09 +0000 (20:12 -0700)
We'll be performing a GPU memcpy in more places to copy small amounts of
data. Add an alternate function that thrashes less state.

v2:
- Make a new function (Jason Ekstrand).
- Move the #define into the function.
v3:
- Update the function name (Jason).
- Update comments.
v4: Use an indirect drawing register as TEMP_REG (Jason Ekstrand).

Signed-off-by: Nanley Chery <nanley.g.chery@intel.com>
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
src/intel/vulkan/anv_genX.h
src/intel/vulkan/genX_gpu_memcpy.c

index 8da5e075dc3b3cf2de914715a8255c9206e5be46..0b7322e281257273a3a0b84a21c2c385460b36d7 100644 (file)
@@ -69,5 +69,10 @@ void genX(cmd_buffer_so_memcpy)(struct anv_cmd_buffer *cmd_buffer,
                                 struct anv_bo *src, uint32_t src_offset,
                                 uint32_t size);
 
+void genX(cmd_buffer_mi_memcpy)(struct anv_cmd_buffer *cmd_buffer,
+                                struct anv_bo *dst, uint32_t dst_offset,
+                                struct anv_bo *src, uint32_t src_offset,
+                                uint32_t size);
+
 void genX(blorp_exec)(struct blorp_batch *batch,
                       const struct blorp_params *params);
index 5ef35e628337fe0a0ad82fe61a03eeebeb0c7ce8..db723d4a528316729b51ab0aa6b3b0dd35e0bf2e 100644 (file)
@@ -51,6 +51,46 @@ gcd_pow2_u64(uint64_t a, uint64_t b)
    return 1 << MIN2(a_log2, b_log2);
 }
 
+void
+genX(cmd_buffer_mi_memcpy)(struct anv_cmd_buffer *cmd_buffer,
+                           struct anv_bo *dst, uint32_t dst_offset,
+                           struct anv_bo *src, uint32_t src_offset,
+                           uint32_t size)
+{
+   /* This memcpy operates in units of dwords. */
+   assert(size % 4 == 0);
+   assert(dst_offset % 4 == 0);
+   assert(src_offset % 4 == 0);
+
+   for (uint32_t i = 0; i < size; i += 4) {
+      const struct anv_address src_addr =
+         (struct anv_address) { src, src_offset + i};
+      const struct anv_address dst_addr =
+         (struct anv_address) { dst, dst_offset + i};
+#if GEN_GEN >= 8
+      anv_batch_emit(&cmd_buffer->batch, GENX(MI_COPY_MEM_MEM), cp) {
+         cp.DestinationMemoryAddress = dst_addr;
+         cp.SourceMemoryAddress = src_addr;
+      }
+#else
+      /* IVB does not have a general purpose register for command streamer
+       * commands. Therefore, we use an alternate temporary register.
+       */
+#define TEMP_REG 0x2440 /* GEN7_3DPRIM_BASE_VERTEX */
+      anv_batch_emit(&cmd_buffer->batch, GENX(MI_LOAD_REGISTER_MEM), load) {
+         load.RegisterAddress = TEMP_REG;
+         load.MemoryAddress = src_addr;
+      }
+      anv_batch_emit(&cmd_buffer->batch, GENX(MI_STORE_REGISTER_MEM), store) {
+         store.RegisterAddress = TEMP_REG;
+         store.MemoryAddress = dst_addr;
+      }
+#undef TEMP_REG
+#endif
+   }
+   return;
+}
+
 void
 genX(cmd_buffer_so_memcpy)(struct anv_cmd_buffer *cmd_buffer,
                            struct anv_bo *dst, uint32_t dst_offset,