summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Olšák <marek.olsak@amd.com>2014-03-08 23:34:36 +0100
committerMarek Olšák <marek.olsak@amd.com>2014-03-11 19:18:02 +0100
commite1a9a54464c31f7b3b69d686d82f425dffb65f40 (patch)
tree3b3376288ce8d98b8e3e7a79688a21e721830efd
parent74d95adea08b3f94ed7d8f7f9cee693a6cd49a44 (diff)
r600g,radeonsi: attempt to fix racy multi-context apps calling BufferData
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=75061 v2: minimize the window where cs_buf != new_buf
-rw-r--r--src/gallium/drivers/r600/r600_state_common.c5
-rw-r--r--src/gallium/drivers/radeon/r600_buffer_common.c22
-rw-r--r--src/gallium/drivers/radeonsi/si_descriptors.c5
3 files changed, 18 insertions, 14 deletions
diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c
index 96c18808ea8..7dbb0b777ed 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 d56a6441eae..77e1b35862a 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;
}
- res->cs_buf = rscreen->ws->buffer_get_cs_handle(res->buf);
+ /* 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->cs_buf = rscreen->ws->buffer_get_cs_handle(new_buf); /* should be atomic */
+ res->buf = new_buf; /* should be atomic */
+ 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) {
@@ -363,6 +372,7 @@ struct pipe_resource *r600_buffer_create(struct pipe_screen *screen,
pipe_reference_init(&rbuffer->b.b.reference, 1);
rbuffer->b.b.screen = screen;
rbuffer->b.vtbl = &r600_buffer_vtbl;
+ rbuffer->buf = NULL;
util_range_init(&rbuffer->valid_buffer_range);
if (!r600_init_resource(rscreen, rbuffer, templ->width0, alignment, TRUE)) {
diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c
index bf2206dc1bc..0c58d5fd045 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);