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

Reply via email to