From 8b8a06f6c318e0ea45725527743aaac837762f59 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Thu, 26 Jun 2025 08:14:28 -0400 Subject: [PATCH] gallium: add pipe_context::image_copy_buffer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this is a more explicit version of the copying used in resource_copy_region which also provides stride info Reviewed-by: Marek Olšák Part-of: --- src/gallium/auxiliary/driver_ddebug/dd_draw.c | 54 +++++++++++++++ src/gallium/auxiliary/driver_ddebug/dd_pipe.h | 13 ++++ src/gallium/auxiliary/driver_noop/noop_pipe.c | 12 ++++ .../auxiliary/driver_trace/tr_context.c | 32 +++++++++ .../auxiliary/util/u_threaded_context.c | 65 +++++++++++++++++++ .../auxiliary/util/u_threaded_context_calls.h | 1 + src/gallium/include/pipe/p_context.h | 14 ++++ 7 files changed, 191 insertions(+) diff --git a/src/gallium/auxiliary/driver_ddebug/dd_draw.c b/src/gallium/auxiliary/driver_ddebug/dd_draw.c index 1f02c57b251..7386e3777a7 100644 --- a/src/gallium/auxiliary/driver_ddebug/dd_draw.c +++ b/src/gallium/auxiliary/driver_ddebug/dd_draw.c @@ -465,6 +465,21 @@ dd_dump_resource_copy_region(struct dd_draw_state *dstate, DUMP_M_ADDR(box, info, src_box); } +static void +dd_dump_image_copy_buffer(struct dd_draw_state *dstate, + struct call_image_copy_buffer *info, + FILE *f) +{ + fprintf(f, "%s:\n", __func__+8); + DUMP_M(resource, info, dst); + DUMP_M(resource, info, src); + DUMP_M(uint, info, buffer_offset); + DUMP_M(uint, info, buffer_stride); + DUMP_M(uint, info, buffer_layer_stride); + DUMP_M(uint, info, level); + DUMP_M_ADDR(box, info, box); +} + static void dd_dump_blit(struct dd_draw_state *dstate, struct pipe_blit_info *info, FILE *f) { @@ -652,6 +667,10 @@ dd_dump_call(FILE *f, struct dd_draw_state *state, struct dd_call *call) dd_dump_resource_copy_region(state, &call->info.resource_copy_region, f); break; + case CALL_IMAGE_COPY_BUFFER: + dd_dump_image_copy_buffer(state, + &call->info.image_copy_buffer, f); + break; case CALL_BLIT: dd_dump_blit(state, &call->info.blit, f); break; @@ -732,6 +751,10 @@ dd_unreference_copy_of_call(struct dd_call *dst) pipe_resource_reference(&dst->info.resource_copy_region.dst, NULL); pipe_resource_reference(&dst->info.resource_copy_region.src, NULL); break; + case CALL_IMAGE_COPY_BUFFER: + pipe_resource_reference(&dst->info.image_copy_buffer.dst, NULL); + pipe_resource_reference(&dst->info.image_copy_buffer.src, NULL); + break; case CALL_BLIT: pipe_resource_reference(&dst->info.blit.dst.resource, NULL); pipe_resource_reference(&dst->info.blit.src.resource, NULL); @@ -1427,6 +1450,36 @@ dd_context_resource_copy_region(struct pipe_context *_pipe, dd_after_draw(dctx, record); } +static void +dd_context_image_copy_buffer(struct pipe_context *_pipe, + struct pipe_resource *dst, + struct pipe_resource *src, + unsigned buffer_offset, + unsigned buffer_stride, + unsigned buffer_layer_stride, + unsigned level, + const struct pipe_box *box) +{ + struct dd_context *dctx = dd_context(_pipe); + struct pipe_context *pipe = dctx->pipe; + struct dd_draw_record *record = dd_create_record(dctx); + + record->call.type = CALL_IMAGE_COPY_BUFFER; + record->call.info.image_copy_buffer.dst = NULL; + pipe_resource_reference(&record->call.info.image_copy_buffer.dst, dst); + pipe_resource_reference(&record->call.info.image_copy_buffer.src, src); + record->call.info.image_copy_buffer.buffer_offset = buffer_offset; + record->call.info.image_copy_buffer.buffer_stride = buffer_stride; + record->call.info.image_copy_buffer.buffer_layer_stride = buffer_layer_stride; + record->call.info.image_copy_buffer.level = level; + record->call.info.image_copy_buffer.box = *box; + + dd_before_draw(dctx, record); + pipe->image_copy_buffer(pipe, + dst, src, buffer_offset, buffer_stride, buffer_layer_stride, level, box); + dd_after_draw(dctx, record); +} + static void dd_context_blit(struct pipe_context *_pipe, const struct pipe_blit_info *info) { @@ -1843,6 +1896,7 @@ dd_init_draw_functions(struct dd_context *dctx) CTX_INIT(draw_vbo); CTX_INIT(launch_grid); CTX_INIT(resource_copy_region); + CTX_INIT(image_copy_buffer); CTX_INIT(blit); CTX_INIT(clear); CTX_INIT(clear_render_target); diff --git a/src/gallium/auxiliary/driver_ddebug/dd_pipe.h b/src/gallium/auxiliary/driver_ddebug/dd_pipe.h index 26a17e60969..574e48096ad 100644 --- a/src/gallium/auxiliary/driver_ddebug/dd_pipe.h +++ b/src/gallium/auxiliary/driver_ddebug/dd_pipe.h @@ -64,6 +64,7 @@ enum call_type CALL_DRAW_VBO, CALL_LAUNCH_GRID, CALL_RESOURCE_COPY_REGION, + CALL_IMAGE_COPY_BUFFER, CALL_BLIT, CALL_FLUSH_RESOURCE, CALL_CLEAR, @@ -90,6 +91,17 @@ struct call_resource_copy_region struct pipe_box src_box; }; +struct call_image_copy_buffer +{ + struct pipe_resource *dst; + struct pipe_resource *src; + unsigned buffer_offset; + unsigned buffer_stride; + unsigned buffer_layer_stride; + unsigned level; + struct pipe_box box; +}; + struct call_clear { unsigned buffers; @@ -182,6 +194,7 @@ struct dd_call struct call_draw_info draw_vbo; struct pipe_grid_info launch_grid; struct call_resource_copy_region resource_copy_region; + struct call_image_copy_buffer image_copy_buffer; struct pipe_blit_info blit; struct pipe_resource *flush_resource; struct call_clear clear; diff --git a/src/gallium/auxiliary/driver_noop/noop_pipe.c b/src/gallium/auxiliary/driver_noop/noop_pipe.c index 16150e38a67..d6098b16390 100644 --- a/src/gallium/auxiliary/driver_noop/noop_pipe.c +++ b/src/gallium/auxiliary/driver_noop/noop_pipe.c @@ -312,6 +312,17 @@ static void noop_resource_copy_region(struct pipe_context *ctx, { } +static void noop_image_copy_buffer(struct pipe_context *pipe, + struct pipe_resource *dst, + struct pipe_resource *src, + unsigned buffer_offset, + unsigned buffer_stride, + unsigned buffer_layer_stride, + unsigned level, + const struct pipe_box *box) +{ +} + static void noop_blit(struct pipe_context *ctx, const struct pipe_blit_info *info) @@ -427,6 +438,7 @@ static struct pipe_context *noop_create_context(struct pipe_screen *screen, ctx->clear_render_target = noop_clear_render_target; ctx->clear_depth_stencil = noop_clear_depth_stencil; ctx->resource_copy_region = noop_resource_copy_region; + ctx->image_copy_buffer = noop_image_copy_buffer; ctx->generate_mipmap = noop_generate_mipmap; ctx->blit = noop_blit; ctx->flush_resource = noop_flush_resource; diff --git a/src/gallium/auxiliary/driver_trace/tr_context.c b/src/gallium/auxiliary/driver_trace/tr_context.c index c6925221ced..aabf9963403 100644 --- a/src/gallium/auxiliary/driver_trace/tr_context.c +++ b/src/gallium/auxiliary/driver_trace/tr_context.c @@ -1341,6 +1341,37 @@ trace_context_resource_copy_region(struct pipe_context *_pipe, } +static void +trace_context_image_copy_buffer(struct pipe_context *_pipe, + struct pipe_resource *dst, + struct pipe_resource *src, + unsigned buffer_offset, + unsigned buffer_stride, + unsigned buffer_layer_stride, + unsigned level, + const struct pipe_box *box) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "image_copy_buffer"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, dst); + trace_dump_arg(ptr, src); + trace_dump_arg(uint, buffer_offset); + trace_dump_arg(uint, buffer_stride); + trace_dump_arg(uint, buffer_layer_stride); + trace_dump_arg(uint, level); + trace_dump_arg(box, box); + + pipe->image_copy_buffer(pipe, + dst, src, buffer_offset, buffer_stride, buffer_layer_stride, level, box); + + trace_dump_call_end(); +} + + static void trace_context_blit(struct pipe_context *_pipe, const struct pipe_blit_info *_info) @@ -2532,6 +2563,7 @@ trace_context_create(struct trace_screen *tr_scr, /* this is lavapipe-only and can't be traced */ tr_ctx->base.stream_output_target_offset = pipe->stream_output_target_offset; TR_CTX_INIT(resource_copy_region); + TR_CTX_INIT(image_copy_buffer); TR_CTX_INIT(blit); TR_CTX_INIT(flush_resource); TR_CTX_INIT(clear); diff --git a/src/gallium/auxiliary/util/u_threaded_context.c b/src/gallium/auxiliary/util/u_threaded_context.c index f42ec1535b3..a8e6c16faa4 100644 --- a/src/gallium/auxiliary/util/u_threaded_context.c +++ b/src/gallium/auxiliary/util/u_threaded_context.c @@ -4443,6 +4443,70 @@ tc_launch_grid(struct pipe_context *_pipe, tc_add_all_compute_bindings_to_buffer_list(tc); } +struct tc_image_copy_buffer { + struct tc_call_base base; + unsigned buffer_stride; + unsigned buffer_layer_stride; + unsigned level; + unsigned buffer_offset; + struct pipe_box box; + struct pipe_resource *dst; + struct pipe_resource *src; +}; + +static uint16_t ALWAYS_INLINE +tc_call_image_copy_buffer(struct pipe_context *pipe, void *call) +{ + struct tc_image_copy_buffer *p = to_call(call, tc_image_copy_buffer); + + pipe->image_copy_buffer(pipe, p->dst, p->src, p->buffer_offset, p->buffer_stride, + p->buffer_layer_stride, p->level, &p->box); + tc_drop_resource_reference(p->dst); + tc_drop_resource_reference(p->src); + return call_size(tc_image_copy_buffer); +} + +static void +tc_image_copy_buffer(struct pipe_context *_pipe, + struct pipe_resource *dst, + struct pipe_resource *src, + unsigned buffer_offset, + unsigned buffer_stride, + unsigned buffer_layer_stride, + unsigned level, + const struct pipe_box *box) +{ + struct threaded_context *tc = threaded_context(_pipe); + struct threaded_resource *tbuf = dst->target == PIPE_BUFFER ? threaded_resource(dst) : threaded_resource(src); + struct threaded_resource *timg = dst->target == PIPE_BUFFER ? threaded_resource(src) : threaded_resource(dst); + struct tc_image_copy_buffer *p = + tc_add_call(tc, TC_CALL_image_copy_buffer, + tc_image_copy_buffer); + + if (dst->target == PIPE_BUFFER) + tc_buffer_disable_cpu_storage(&tbuf->b); + if (tc->options.parse_renderpass_info && tc->in_renderpass) + tc_check_fb_access(tc, NULL, &timg->b); + + tc_set_resource_batch_usage(tc, dst); + tc_set_resource_reference(&p->dst, dst); + p->buffer_offset = buffer_offset; + p->buffer_stride = buffer_stride; + p->buffer_layer_stride = buffer_layer_stride; + p->level = level; + p->box = *box; + tc_set_resource_batch_usage(tc, src); + tc_set_resource_reference(&p->src, src); + + struct tc_buffer_list *next = &tc->buffer_lists[tc->next_buf_list]; + + tc_add_to_buffer_list(next, &tbuf->b); + + if (dst->target == PIPE_BUFFER) + util_range_add(&tbuf->b, &tbuf->valid_buffer_range, + buffer_offset, buffer_offset + box->width); +} + static uint16_t ALWAYS_INLINE tc_call_resource_copy_region(struct pipe_context *pipe, void *call) { @@ -5456,6 +5520,7 @@ threaded_context_create(struct pipe_context *pipe, CTX_INIT(draw_vertex_state); CTX_INIT(launch_grid); CTX_INIT(resource_copy_region); + CTX_INIT(image_copy_buffer); CTX_INIT(blit); CTX_INIT(clear); CTX_INIT(clear_render_target); diff --git a/src/gallium/auxiliary/util/u_threaded_context_calls.h b/src/gallium/auxiliary/util/u_threaded_context_calls.h index 317f16c85d0..8d48dc50f8d 100644 --- a/src/gallium/auxiliary/util/u_threaded_context_calls.h +++ b/src/gallium/auxiliary/util/u_threaded_context_calls.h @@ -101,3 +101,4 @@ CALL(delete_tes_state) CALL(begin_intel_perf_query) CALL(end_intel_perf_query) +CALL(image_copy_buffer) diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h index 379619044b0..8ce19dcafe6 100644 --- a/src/gallium/include/pipe/p_context.h +++ b/src/gallium/include/pipe/p_context.h @@ -693,6 +693,20 @@ struct pipe_context { unsigned src_level, const struct pipe_box *src_box); + /** + * Perform a copy between an image and a buffer in either direction. + * buffer_stride=0 or buffer_layer_stride=0 means tightly packed on that axis + * Resources with nr_samples > 1 are not allowed. + */ + void (*image_copy_buffer)(struct pipe_context *pipe, + struct pipe_resource *dst, + struct pipe_resource *src, + unsigned buffer_offset, + unsigned buffer_stride, + unsigned buffer_layer_stride, + unsigned level, + const struct pipe_box *box); + /* Optimal hardware path for blitting pixels. * Scaling, format conversion, up- and downsampling (resolve) are allowed. */