From 7feb0b6233690af9c1bff7f6748a9e91359d2c44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Sat, 8 Mar 2014 23:34:36 +0100 Subject: [PATCH] r600g,radeonsi: attempt to fix racy multi-context apps calling BufferData --- src/gallium/drivers/r600/r600_state_common.c | 5 +---- src/gallium/drivers/radeon/r600_buffer_common.c | 19 ++++++++++++++----- src/gallium/drivers/radeonsi/si_descriptors.c | 5 +---- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c index 96c1880..7dbb0b7 100644 --- a/src/gallium/drivers/r600/r600_state_common.c +++ b/src/gallium/drivers/r600/r600_state_common.c @@ -2292,10 +2292,7 @@ static void r600_invalidate_buffer(struct pipe_context *ctx, struct pipe_resourc struct r600_resource *rbuffer = r600_resource(buf); unsigned i, shader, mask, alignment = rbuffer->buf->alignment; - /* Discard the buffer. */ - pb_reference(&rbuffer->buf, NULL); - - /* Create a new one in the same pipe_resource. */ + /* Reallocate the buffer in the same pipe_resource. */ r600_init_resource(&rctx->screen->b, rbuffer, rbuffer->b.b.width0, alignment, TRUE); diff --git a/src/gallium/drivers/radeon/r600_buffer_common.c b/src/gallium/drivers/radeon/r600_buffer_common.c index a7ecfb3..589296c 100644 --- a/src/gallium/drivers/radeon/r600_buffer_common.c +++ b/src/gallium/drivers/radeon/r600_buffer_common.c @@ -106,6 +106,7 @@ bool r600_init_resource(struct r600_common_screen *rscreen, bool use_reusable_pool) { struct r600_texture *rtex = (struct r600_texture*)res; + struct pb_buffer *old_buf, *new_buf; switch (res->b.b.usage) { case PIPE_USAGE_STAGING: @@ -136,15 +137,23 @@ bool r600_init_resource(struct r600_common_screen *rscreen, res->domains = RADEON_DOMAIN_VRAM; } - /* Allocate the resource. */ - res->buf = rscreen->ws->buffer_create(rscreen->ws, size, alignment, - use_reusable_pool, - res->domains); - if (!res->buf) { + /* Allocate a new resource. */ + new_buf = rscreen->ws->buffer_create(rscreen->ws, size, alignment, + use_reusable_pool, + res->domains); + if (!new_buf) { return false; } + /* Replace the pointer such that if res->buf wasn't NULL, it won't be + * NULL. This should prevent crashes with multiple contexts using + * the same buffer where one of the contexts invalidates it while + * the others are using it. */ + old_buf = res->buf; + res->buf = new_buf; /* this should be atomic */ res->cs_buf = rscreen->ws->buffer_get_cs_handle(res->buf); + pb_reference(&old_buf, NULL); + util_range_set_empty(&res->valid_buffer_range); if (rscreen->debug_flags & DBG_VM && res->b.b.target == PIPE_BUFFER) { diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c index 12e5b61..85d17d0 100644 --- a/src/gallium/drivers/radeonsi/si_descriptors.c +++ b/src/gallium/drivers/radeonsi/si_descriptors.c @@ -723,10 +723,7 @@ static void si_invalidate_buffer(struct pipe_context *ctx, struct pipe_resource unsigned i, shader, alignment = rbuffer->buf->alignment; uint64_t old_va = r600_resource_va(ctx->screen, buf); - /* Discard the buffer. */ - pb_reference(&rbuffer->buf, NULL); - - /* Create a new one in the same pipe_resource. */ + /* Reallocate the buffer in the same pipe_resource. */ r600_init_resource(&sctx->screen->b, rbuffer, rbuffer->b.b.width0, alignment, TRUE); -- 1.8.3.2