From: Marek Olšák <marek.ol...@amd.com>

This fixes piglit spec/ARB_texture_buffer_object/data-sync.
---
 src/gallium/drivers/r600/evergreen_state.c    |  9 +++++--
 src/gallium/drivers/r600/r600_pipe.h          |  1 +
 src/gallium/drivers/r600/r600_state_common.c  | 39 ++++++++++++++++++++++++---
 src/gallium/drivers/radeon/r600_pipe_common.c |  2 ++
 src/gallium/drivers/radeon/r600_pipe_common.h |  5 ++++
 5 files changed, 51 insertions(+), 5 deletions(-)

diff --git a/src/gallium/drivers/r600/evergreen_state.c 
b/src/gallium/drivers/r600/evergreen_state.c
index 67f505d..841ad0c 100644
--- a/src/gallium/drivers/r600/evergreen_state.c
+++ b/src/gallium/drivers/r600/evergreen_state.c
@@ -596,7 +596,8 @@ static void *evergreen_create_sampler_state(struct 
pipe_context *ctx,
 }
 
 static struct pipe_sampler_view *
-texture_buffer_sampler_view(struct r600_pipe_sampler_view *view,
+texture_buffer_sampler_view(struct r600_context *rctx,
+                           struct r600_pipe_sampler_view *view,
                            unsigned width0, unsigned height0)
                            
 {
@@ -644,6 +645,9 @@ texture_buffer_sampler_view(struct r600_pipe_sampler_view 
*view,
        view->tex_resource_words[4] = 0;
        view->tex_resource_words[5] = view->tex_resource_words[6] = 0;
        view->tex_resource_words[7] = 
S_03001C_TYPE(V_03001C_SQ_TEX_VTX_VALID_BUFFER);
+
+       if (tmp->resource.gpu_address)
+               LIST_ADDTAIL(&view->list, &rctx->b.texture_buffers);
        return &view->base;
 }
 
@@ -654,6 +658,7 @@ evergreen_create_sampler_view_custom(struct pipe_context 
*ctx,
                                     unsigned width0, unsigned height0,
                                     unsigned force_level)
 {
+       struct r600_context *rctx = (struct r600_context*)ctx;
        struct r600_screen *rscreen = (struct r600_screen*)ctx->screen;
        struct r600_pipe_sampler_view *view = 
CALLOC_STRUCT(r600_pipe_sampler_view);
        struct r600_texture *tmp = (struct r600_texture*)texture;
@@ -679,7 +684,7 @@ evergreen_create_sampler_view_custom(struct pipe_context 
*ctx,
        view->base.context = ctx;
 
        if (texture->target == PIPE_BUFFER)
-               return texture_buffer_sampler_view(view, width0, height0);
+               return texture_buffer_sampler_view(rctx, view, width0, height0);
 
        swizzle[0] = state->swizzle_r;
        swizzle[1] = state->swizzle_g;
diff --git a/src/gallium/drivers/r600/r600_pipe.h 
b/src/gallium/drivers/r600/r600_pipe.h
index 9c407a2..1236e5e 100644
--- a/src/gallium/drivers/r600/r600_pipe.h
+++ b/src/gallium/drivers/r600/r600_pipe.h
@@ -222,6 +222,7 @@ struct r600_screen {
 
 struct r600_pipe_sampler_view {
        struct pipe_sampler_view        base;
+       struct list_head                list;
        struct r600_resource            *tex_resource;
        uint32_t                        tex_resource_words[8];
        bool                            skip_mip_address_reloc;
diff --git a/src/gallium/drivers/r600/r600_state_common.c 
b/src/gallium/drivers/r600/r600_state_common.c
index e0c2a32..23b5512 100644
--- a/src/gallium/drivers/r600/r600_state_common.c
+++ b/src/gallium/drivers/r600/r600_state_common.c
@@ -354,10 +354,14 @@ static void r600_delete_rs_state(struct pipe_context 
*ctx, void *state)
 static void r600_sampler_view_destroy(struct pipe_context *ctx,
                                      struct pipe_sampler_view *state)
 {
-       struct r600_pipe_sampler_view *resource = (struct 
r600_pipe_sampler_view *)state;
+       struct r600_pipe_sampler_view *view = (struct r600_pipe_sampler_view 
*)state;
+
+       if (view->tex_resource->gpu_address &&
+           view->tex_resource->b.b.target == PIPE_BUFFER)
+               LIST_DELINIT(&view->list);
 
        pipe_resource_reference(&state->texture, NULL);
-       FREE(resource);
+       FREE(view);
 }
 
 void r600_sampler_states_dirty(struct r600_context *rctx,
@@ -2335,6 +2339,7 @@ static void r600_invalidate_buffer(struct pipe_context 
*ctx, struct pipe_resourc
        struct r600_context *rctx = (struct r600_context*)ctx;
        struct r600_resource *rbuffer = r600_resource(buf);
        unsigned i, shader, mask, alignment = rbuffer->buf->alignment;
+       struct r600_pipe_sampler_view *view;
 
        /* Reallocate the buffer in the same pipe_resource. */
        r600_init_resource(&rctx->screen->b, rbuffer, rbuffer->b.b.width0,
@@ -2379,7 +2384,35 @@ static void r600_invalidate_buffer(struct pipe_context 
*ctx, struct pipe_resourc
                }
        }
 
-       /* XXX TODO: texture buffer objects */
+       /* Texture buffer objects - update the virtual addresses in 
descriptors. */
+       LIST_FOR_EACH_ENTRY(view, &rctx->b.texture_buffers, list) {
+               if (view->base.texture == &rbuffer->b.b) {
+                       unsigned stride = 
util_format_get_blocksize(view->base.format);
+                       uint64_t offset = 
(uint64_t)view->base.u.buf.first_element * stride;
+                       uint64_t va = rbuffer->gpu_address + offset;
+
+                       view->tex_resource_words[0] = va;
+                       view->tex_resource_words[2] &= C_038008_BASE_ADDRESS_HI;
+                       view->tex_resource_words[2] |= 
S_038008_BASE_ADDRESS_HI(va >> 32);
+               }
+       }
+       /* Texture buffer objects - make bindings dirty if needed. */
+       for (shader = 0; shader < PIPE_SHADER_TYPES; shader++) {
+               struct r600_samplerview_state *state = 
&rctx->samplers[shader].views;
+               bool found = false;
+               uint32_t mask = state->enabled_mask;
+
+               while (mask) {
+                       unsigned i = u_bit_scan(&mask);
+                       if (state->views[i]->base.texture == &rbuffer->b.b) {
+                               found = true;
+                               state->dirty_mask |= 1 << i;
+                       }
+               }
+               if (found) {
+                       r600_sampler_views_dirty(rctx, state);
+               }
+       }
 }
 
 static void r600_set_occlusion_query_state(struct pipe_context *ctx, bool 
enable)
diff --git a/src/gallium/drivers/radeon/r600_pipe_common.c 
b/src/gallium/drivers/radeon/r600_pipe_common.c
index eb44d72..2c7cf04 100644
--- a/src/gallium/drivers/radeon/r600_pipe_common.c
+++ b/src/gallium/drivers/radeon/r600_pipe_common.c
@@ -157,6 +157,8 @@ bool r600_common_context_init(struct r600_common_context 
*rctx,
         rctx->b.memory_barrier = r600_memory_barrier;
        rctx->b.flush = r600_flush_from_st;
 
+       LIST_INITHEAD(&rctx->texture_buffers);
+
        r600_init_context_texture_functions(rctx);
        r600_streamout_init(rctx);
        r600_query_init(rctx);
diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h 
b/src/gallium/drivers/radeon/r600_pipe_common.h
index 59d0b3e..ab348ae 100644
--- a/src/gallium/drivers/radeon/r600_pipe_common.h
+++ b/src/gallium/drivers/radeon/r600_pipe_common.h
@@ -375,6 +375,11 @@ struct r600_common_context {
        float                           sample_locations_8x[8][2];
        float                           sample_locations_16x[16][2];
 
+       /* The list of all texture buffer objects in this context.
+        * This list is walked when a buffer is invalidated/reallocated and
+        * the GPU addresses are updated. */
+       struct list_head                texture_buffers;
+
        /* Copy one resource to another using async DMA. */
        void (*dma_copy)(struct pipe_context *ctx,
                         struct pipe_resource *dst,
-- 
1.9.1

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to