From: Marek Olšák <marek.ol...@amd.com> --- src/gallium/drivers/radeon/r600_buffer_common.c | 23 +++++++++++++++++ src/gallium/drivers/radeon/r600_pipe_common.h | 11 +++++++- src/gallium/drivers/radeonsi/si_descriptors.c | 34 ++++++++++++++++--------- 3 files changed, 55 insertions(+), 13 deletions(-)
diff --git a/src/gallium/drivers/radeon/r600_buffer_common.c b/src/gallium/drivers/radeon/r600_buffer_common.c index 0c6fa66..58d2c4b 100644 --- a/src/gallium/drivers/radeon/r600_buffer_common.c +++ b/src/gallium/drivers/radeon/r600_buffer_common.c @@ -266,20 +266,43 @@ r600_invalidate_buffer(struct r600_common_context *rctx, if (r600_rings_is_buffer_referenced(rctx, rbuffer->buf, RADEON_USAGE_READWRITE) || !rctx->ws->buffer_wait(rbuffer->buf, 0, RADEON_USAGE_READWRITE)) { rctx->invalidate_buffer(&rctx->b, &rbuffer->b.b); } else { util_range_set_empty(&rbuffer->valid_buffer_range); } return true; } +/* Replace the storage of dst with src. */ +void r600_replace_buffer_storage(struct pipe_context *ctx, + struct pipe_resource *dst, + struct pipe_resource *src) +{ + struct r600_common_context *rctx = (struct r600_common_context *)ctx; + struct r600_resource *rdst = r600_resource(dst); + struct r600_resource *rsrc = r600_resource(src); + uint64_t old_gpu_address = rdst->gpu_address; + + pb_reference(&rdst->buf, rsrc->buf); + rdst->gpu_address = rsrc->gpu_address; + + assert(rdst->vram_usage == rsrc->vram_usage); + assert(rdst->gart_usage == rsrc->gart_usage); + assert(rdst->bo_size == rsrc->bo_size); + assert(rdst->bo_alignment == rsrc->bo_alignment); + assert(rdst->domains == rsrc->domains); + assert(rdst->flags == rsrc->flags); + + rctx->rebind_buffer(ctx, dst, old_gpu_address); +} + void r600_invalidate_resource(struct pipe_context *ctx, struct pipe_resource *resource) { struct r600_common_context *rctx = (struct r600_common_context*)ctx; struct r600_resource *rbuffer = r600_resource(resource); /* We currently only do anyting here for buffers */ if (resource->target == PIPE_BUFFER) (void)r600_invalidate_buffer(rctx, rbuffer); } diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h b/src/gallium/drivers/radeon/r600_pipe_common.h index a694b97..f9c9f11 100644 --- a/src/gallium/drivers/radeon/r600_pipe_common.h +++ b/src/gallium/drivers/radeon/r600_pipe_common.h @@ -659,38 +659,44 @@ struct r600_common_context { unsigned first_layer, unsigned last_layer, unsigned first_sample, unsigned last_sample); void (*decompress_dcc)(struct pipe_context *ctx, struct r600_texture *rtex); /* Reallocate the buffer and update all resource bindings where * the buffer is bound, including all resource descriptors. */ void (*invalidate_buffer)(struct pipe_context *ctx, struct pipe_resource *buf); + /* Update all resource bindings where the buffer is bound, including + * all resource descriptors. This is invalidate_buffer without + * the invalidation. */ + void (*rebind_buffer)(struct pipe_context *ctx, struct pipe_resource *buf, + uint64_t old_gpu_address); + /* Enable or disable occlusion queries. */ void (*set_occlusion_query_state)(struct pipe_context *ctx, bool enable); void (*save_qbo_state)(struct pipe_context *ctx, struct r600_qbo_state *st); /* This ensures there is enough space in the command stream. */ void (*need_gfx_cs_space)(struct pipe_context *ctx, unsigned num_dw, bool include_draw_vbo); void (*set_atom_dirty)(struct r600_common_context *ctx, struct r600_atom *atom, bool dirty); void (*check_vm_faults)(struct r600_common_context *ctx, struct radeon_saved_cs *saved, enum ring_type ring); }; -/* r600_buffer.c */ +/* r600_buffer_common.c */ bool r600_rings_is_buffer_referenced(struct r600_common_context *ctx, struct pb_buffer *buf, enum radeon_bo_usage usage); void *r600_buffer_map_sync_with_rings(struct r600_common_context *ctx, struct r600_resource *resource, unsigned usage); void r600_buffer_subdata(struct pipe_context *ctx, struct pipe_resource *buffer, unsigned usage, unsigned offset, unsigned size, const void *data); @@ -707,20 +713,23 @@ struct pipe_resource * r600_aligned_buffer_create(struct pipe_screen *screen, unsigned usage, unsigned size, unsigned alignment); struct pipe_resource * r600_buffer_from_user_memory(struct pipe_screen *screen, const struct pipe_resource *templ, void *user_memory); void r600_invalidate_resource(struct pipe_context *ctx, struct pipe_resource *resource); +void r600_replace_buffer_storage(struct pipe_context *ctx, + struct pipe_resource *dst, + struct pipe_resource *src); /* r600_common_pipe.c */ void r600_gfx_write_event_eop(struct r600_common_context *ctx, unsigned event, unsigned event_flags, unsigned data_sel, struct r600_resource *buf, uint64_t va, uint32_t old_fence, uint32_t new_fence); unsigned r600_gfx_write_fence_dwords(struct r600_common_screen *screen); void r600_gfx_wait_fence(struct r600_common_context *ctx, uint64_t va, uint32_t ref, uint32_t mask); diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c index 8d34541..c92a657 100644 --- a/src/gallium/drivers/radeonsi/si_descriptors.c +++ b/src/gallium/drivers/radeonsi/si_descriptors.c @@ -1619,39 +1619,29 @@ static void si_reset_buffer_resources(struct si_context *sctx, sctx->descriptors_dirty |= 1u << descriptors_idx; radeon_add_to_buffer_list_check_mem(&sctx->b, &sctx->b.gfx, (struct r600_resource *)buf, buffers->shader_usage, buffers->priority, true); } } } -/* Reallocate a buffer a update all resource bindings where the buffer is - * bound. - * - * This is used to avoid CPU-GPU synchronizations, because it makes the buffer - * idle by discarding its contents. Apps usually tell us when to do this using - * map_buffer flags, for example. - */ -static void si_invalidate_buffer(struct pipe_context *ctx, struct pipe_resource *buf) +static void si_rebind_buffer(struct pipe_context *ctx, struct pipe_resource *buf, + uint64_t old_va) { struct si_context *sctx = (struct si_context*)ctx; struct r600_resource *rbuffer = r600_resource(buf); unsigned i, shader; - uint64_t old_va = rbuffer->gpu_address; unsigned num_elems = sctx->vertex_elements ? sctx->vertex_elements->count : 0; - /* Reallocate the buffer in the same pipe_resource. */ - r600_alloc_resource(&sctx->screen->b, rbuffer); - /* We changed the buffer, now we need to bind it where the old one * was bound. This consists of 2 things: * 1) Updating the resource descriptor and dirtying it. * 2) Adding a relocation to the CS, so that it's usable. */ /* Vertex buffers. */ if (rbuffer->bind_history & PIPE_BIND_VERTEX_BUFFER) { for (i = 0; i < num_elems; i++) { int vb = sctx->vertex_elements->elements[i].vertex_buffer_index; @@ -1765,20 +1755,39 @@ static void si_invalidate_buffer(struct pipe_context *ctx, struct pipe_resource radeon_add_to_buffer_list_check_mem( &sctx->b, &sctx->b.gfx, rbuffer, RADEON_USAGE_READWRITE, RADEON_PRIO_SAMPLER_BUFFER, true); } } } } } +/* Reallocate a buffer a update all resource bindings where the buffer is + * bound. + * + * This is used to avoid CPU-GPU synchronizations, because it makes the buffer + * idle by discarding its contents. Apps usually tell us when to do this using + * map_buffer flags, for example. + */ +static void si_invalidate_buffer(struct pipe_context *ctx, struct pipe_resource *buf) +{ + struct si_context *sctx = (struct si_context*)ctx; + struct r600_resource *rbuffer = r600_resource(buf); + uint64_t old_va = rbuffer->gpu_address; + + /* Reallocate the buffer in the same pipe_resource. */ + r600_alloc_resource(&sctx->screen->b, rbuffer); + + si_rebind_buffer(ctx, buf, old_va); +} + /* Update mutable image descriptor fields of all bound textures. */ void si_update_all_texture_descriptors(struct si_context *sctx) { unsigned shader; for (shader = 0; shader < SI_NUM_SHADERS; shader++) { struct si_sampler_views *samplers = &sctx->samplers[shader].views; struct si_images_info *images = &sctx->images[shader]; unsigned mask; @@ -2060,20 +2069,21 @@ void si_init_all_descriptors(struct si_context *sctx) /* Set pipe_context functions. */ sctx->b.b.bind_sampler_states = si_bind_sampler_states; sctx->b.b.set_shader_images = si_set_shader_images; sctx->b.b.set_constant_buffer = si_pipe_set_constant_buffer; sctx->b.b.set_polygon_stipple = si_set_polygon_stipple; sctx->b.b.set_shader_buffers = si_set_shader_buffers; sctx->b.b.set_sampler_views = si_set_sampler_views; sctx->b.b.set_stream_output_targets = si_set_streamout_targets; sctx->b.invalidate_buffer = si_invalidate_buffer; + sctx->b.rebind_buffer = si_rebind_buffer; /* Shader user data. */ si_init_atom(sctx, &sctx->shader_userdata.atom, &sctx->atoms.s.shader_userdata, si_emit_graphics_shader_userdata); /* Set default and immutable mappings. */ si_set_user_data_base(sctx, PIPE_SHADER_VERTEX, R_00B130_SPI_SHADER_USER_DATA_VS_0); if (sctx->b.chip_class >= GFX9) { si_set_user_data_base(sctx, PIPE_SHADER_TESS_CTRL, -- 2.7.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev