From d40e372fe9774c3fb93c14a7f3e588daef88ce86 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Wed, 7 Oct 2020 15:55:16 -0400 Subject: [PATCH] zink: move buffer<->image copying to pipe_context::resource_copy_region hook that's a todo item off the list Reviewed-by: Dave Airlie Part-of: --- src/gallium/drivers/zink/zink_context.c | 81 +++++++++++++++++++++- src/gallium/drivers/zink/zink_context.h | 5 ++ src/gallium/drivers/zink/zink_resource.c | 85 ++++-------------------- 3 files changed, 98 insertions(+), 73 deletions(-) diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c index d2d38f24408..fb234d1c837 100644 --- a/src/gallium/drivers/zink/zink_context.c +++ b/src/gallium/drivers/zink/zink_context.c @@ -1841,6 +1841,84 @@ zink_copy_buffer(struct zink_context *ctx, struct zink_batch *batch, struct zink vkCmdCopyBuffer(batch->cmdbuf, src->buffer, dst->buffer, 1, ®ion); } +void +zink_copy_image_buffer(struct zink_context *ctx, struct zink_batch *batch, struct zink_resource *dst, struct zink_resource *src, + unsigned dst_level, unsigned dstx, unsigned dsty, unsigned dstz, + unsigned src_level, const struct pipe_box *src_box, enum pipe_map_flags map_flags) +{ + struct zink_resource *img = dst->base.target == PIPE_BUFFER ? src : dst; + struct zink_resource *buf = dst->base.target == PIPE_BUFFER ? dst : src; + + if (!batch) + batch = zink_batch_no_rp(ctx); + + bool buf2img = buf == src; + + if (buf2img) { + zink_resource_image_barrier(ctx, batch, img, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, 0); + zink_resource_buffer_barrier(ctx, batch, buf, VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); + } else { + zink_resource_image_barrier(ctx, batch, img, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 0, 0); + zink_resource_buffer_barrier(ctx, batch, buf, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); + util_range_add(&dst->base, &dst->valid_buffer_range, dstx, dstx + src_box->width); + } + + VkBufferImageCopy region = {}; + region.bufferOffset = buf2img ? src_box->x : dstx; + region.bufferRowLength = 0; + region.bufferImageHeight = 0; + region.imageSubresource.mipLevel = buf2img ? dst_level : src_level; + region.imageSubresource.layerCount = 1; + if (img->base.array_size > 1) { + region.imageSubresource.baseArrayLayer = buf2img ? dstz : src_box->z; + region.imageSubresource.layerCount = src_box->depth; + region.imageExtent.depth = 1; + } else { + region.imageOffset.z = buf2img ? dstz : src_box->z; + region.imageExtent.depth = src_box->depth; + } + region.imageOffset.x = buf2img ? dstx : src_box->x; + region.imageOffset.y = buf2img ? dsty : src_box->y; + + region.imageExtent.width = src_box->width; + region.imageExtent.height = src_box->height; + + zink_batch_reference_resource_rw(batch, img, buf2img); + zink_batch_reference_resource_rw(batch, buf, !buf2img); + + /* we're using u_transfer_helper_deinterleave, which means we'll be getting PIPE_MAP_* usage + * to indicate whether to copy either the depth or stencil aspects + */ + unsigned aspects = 0; + if (map_flags) { + assert((map_flags & (PIPE_MAP_DEPTH_ONLY | PIPE_MAP_STENCIL_ONLY)) != + (PIPE_MAP_DEPTH_ONLY | PIPE_MAP_STENCIL_ONLY)); + if (map_flags & PIPE_MAP_DEPTH_ONLY) + aspects = VK_IMAGE_ASPECT_DEPTH_BIT; + else if (map_flags & PIPE_MAP_STENCIL_ONLY) + aspects = VK_IMAGE_ASPECT_STENCIL_BIT; + } + if (!aspects) + aspects = img->aspect; + while (aspects) { + int aspect = 1 << u_bit_scan(&aspects); + region.imageSubresource.aspectMask = aspect; + + /* this may or may not work with multisampled depth/stencil buffers depending on the driver implementation: + * + * srcImage must have a sample count equal to VK_SAMPLE_COUNT_1_BIT + * - vkCmdCopyImageToBuffer spec + * + * dstImage must have a sample count equal to VK_SAMPLE_COUNT_1_BIT + * - vkCmdCopyBufferToImage spec + */ + if (buf2img) + vkCmdCopyBufferToImage(batch->cmdbuf, buf->buffer, img->image, img->layout, 1, ®ion); + else + vkCmdCopyImageToBuffer(batch->cmdbuf, img->image, img->layout, buf->buffer, 1, ®ion); + } +} + static void zink_resource_copy_region(struct pipe_context *pctx, struct pipe_resource *pdst, @@ -1911,8 +1989,7 @@ zink_resource_copy_region(struct pipe_context *pctx, src->base.target == PIPE_BUFFER) { zink_copy_buffer(ctx, NULL, dst, src, dstx, src_box->x, src_box->width); } else - debug_printf("zink: TODO resource copy\n"); - //util_range_add(dst, &dst->valid_buffer_range, dstx, dstx + src_box->width); + zink_copy_image_buffer(ctx, NULL, dst, src, dst_level, dstx, dsty, dstz, src_level, src_box, 0); } static struct pipe_stream_output_target * diff --git a/src/gallium/drivers/zink/zink_context.h b/src/gallium/drivers/zink/zink_context.h index 47c29614c54..5db1b421f5c 100644 --- a/src/gallium/drivers/zink/zink_context.h +++ b/src/gallium/drivers/zink/zink_context.h @@ -328,6 +328,11 @@ void zink_copy_buffer(struct zink_context *ctx, struct zink_batch *batch, struct zink_resource *dst, struct zink_resource *src, unsigned dst_offset, unsigned src_offset, unsigned size); +void +zink_copy_image_buffer(struct zink_context *ctx, struct zink_batch *batch, struct zink_resource *dst, struct zink_resource *src, + unsigned dst_level, unsigned dstx, unsigned dsty, unsigned dstz, + unsigned src_level, const struct pipe_box *src_box, enum pipe_map_flags map_flags); + void zink_context_update_descriptor_states(struct zink_context *ctx, bool is_compute); diff --git a/src/gallium/drivers/zink/zink_resource.c b/src/gallium/drivers/zink/zink_resource.c index 1b5f71338b2..0949c835dbd 100644 --- a/src/gallium/drivers/zink/zink_resource.c +++ b/src/gallium/drivers/zink/zink_resource.c @@ -522,76 +522,24 @@ zink_resource_from_handle(struct pipe_screen *pscreen, #endif } -static bool +static void zink_transfer_copy_bufimage(struct zink_context *ctx, - struct zink_resource *res, - struct zink_resource *staging_res, - struct zink_transfer *trans, - bool buf2img) + struct zink_resource *dst, + struct zink_resource *src, + struct zink_transfer *trans) { - struct zink_batch *batch = zink_batch_no_rp(ctx); - - if (buf2img) { - zink_resource_image_barrier(ctx, batch, res, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, 0); - } else { - zink_resource_image_barrier(ctx, batch, res, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 0, 0); - } - - VkBufferImageCopy copyRegion = {}; - copyRegion.bufferOffset = staging_res->offset; - copyRegion.bufferRowLength = 0; - copyRegion.bufferImageHeight = 0; - copyRegion.imageSubresource.mipLevel = trans->base.level; - copyRegion.imageSubresource.layerCount = 1; - if (res->base.array_size > 1) { - copyRegion.imageSubresource.baseArrayLayer = trans->base.box.z; - copyRegion.imageSubresource.layerCount = trans->base.box.depth; - copyRegion.imageExtent.depth = 1; - } else { - copyRegion.imageOffset.z = trans->base.box.z; - copyRegion.imageExtent.depth = trans->base.box.depth; - } - copyRegion.imageOffset.x = trans->base.box.x; - copyRegion.imageOffset.y = trans->base.box.y; - - copyRegion.imageExtent.width = trans->base.box.width; - copyRegion.imageExtent.height = trans->base.box.height; - - zink_batch_reference_resource_rw(batch, res, buf2img); - zink_batch_reference_resource_rw(batch, staging_res, !buf2img); - - /* we're using u_transfer_helper_deinterleave, which means we'll be getting PIPE_MAP_* usage - * to indicate whether to copy either the depth or stencil aspects - */ - unsigned aspects = 0; assert((trans->base.usage & (PIPE_MAP_DEPTH_ONLY | PIPE_MAP_STENCIL_ONLY)) != (PIPE_MAP_DEPTH_ONLY | PIPE_MAP_STENCIL_ONLY)); - if (trans->base.usage & PIPE_MAP_DEPTH_ONLY) - aspects = VK_IMAGE_ASPECT_DEPTH_BIT; - else if (trans->base.usage & PIPE_MAP_STENCIL_ONLY) - aspects = VK_IMAGE_ASPECT_STENCIL_BIT; - else { - aspects = aspect_from_format(res->base.format); - } - while (aspects) { - int aspect = 1 << u_bit_scan(&aspects); - copyRegion.imageSubresource.aspectMask = aspect; - /* this may or may not work with multisampled depth/stencil buffers depending on the driver implementation: - * - * srcImage must have a sample count equal to VK_SAMPLE_COUNT_1_BIT - * - vkCmdCopyImageToBuffer spec - * - * dstImage must have a sample count equal to VK_SAMPLE_COUNT_1_BIT - * - vkCmdCopyBufferToImage spec - */ - if (buf2img) - vkCmdCopyBufferToImage(batch->cmdbuf, staging_res->buffer, res->image, res->layout, 1, ©Region); - else - vkCmdCopyImageToBuffer(batch->cmdbuf, res->image, res->layout, staging_res->buffer, 1, ©Region); - } + bool buf2img = src->base.target == PIPE_BUFFER; - return true; + struct pipe_box box = trans->base.box; + int x = box.x; + if (buf2img) + box.x = src->offset; + + zink_copy_image_buffer(ctx, NULL, dst, src, trans->base.level, buf2img ? x : dst->offset, + box.y, box.z, trans->base.level, &box, trans->base.usage); } uint32_t @@ -722,12 +670,7 @@ zink_transfer_map(struct pipe_context *pctx, /* don't actually have to stall here, only ensure batch is submitted */ zink_flush_compute(ctx); struct zink_context *ctx = zink_context(pctx); - bool ret = zink_transfer_copy_bufimage(ctx, res, - staging_res, trans, - false); - if (ret == false) - return NULL; - + zink_transfer_copy_bufimage(ctx, staging_res, res, trans); /* need to wait for rendering to finish */ zink_fence_wait(pctx); } @@ -800,7 +743,7 @@ zink_transfer_flush_region(struct pipe_context *pctx, if (ptrans->resource->target == PIPE_BUFFER) zink_copy_buffer(ctx, NULL, res, staging_res, box->x, box->x, box->width); else - zink_transfer_copy_bufimage(ctx, res, staging_res, trans, true); + zink_transfer_copy_bufimage(ctx, res, staging_res, trans); if (batch_uses) pctx->flush(pctx, NULL, 0); }