From 79f28cdb983b7faf9d3008fae541a30e34ccce5a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Mon, 11 Aug 2014 13:32:40 +0200 Subject: [PATCH] r600g: implement invalidation of texture buffer objects This fixes piglit spec/ARB_texture_buffer_object/data-sync. Reviewed-by: Alex Deucher --- 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 602c1877bf3..e6e9f49e537 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 6422e3ee70e..d04fef80df1 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 207f07ec9c9..64a027797d1 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, @@ -2314,6 +2318,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, @@ -2358,7 +2363,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 95abfb82f41..5ceadb4d3e5 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 59d0b3e21c4..ab348ae02cc 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, -- 2.30.2