[Mesa-dev] [PATCH 1/6] blorp: Turn anv_CmdCopyBuffer into a blorp_buffer_copy() helper.
Jason Ekstrand
jason at jlekstrand.net
Tue Aug 29 22:42:09 UTC 2017
On August 29, 2017 2:29:26 PM Kenneth Graunke <kenneth at whitecape.org> wrote:
> 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, ¶ms, &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,
I think I have a mild preference for making this take a pair of
blorp_address structs instead of void pointers and offsets. Of course, if
that's a pain for some reason, this is fine.
> + 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 at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
More information about the mesa-dev
mailing list