From bb273ea72817d96f66e1df3e0f8882e963cd8b30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolai=20H=C3=A4hnle?= Date: Wed, 6 Feb 2019 21:59:28 +0100 Subject: [PATCH] radeonsi: fix query buffer reset and allocation Re-prepare query buffers after a reset, and fix the logic for buffer full check on alloc. Fixes: e0f0d3675d4 ("radeonsi: factor si_query_buffer logic out of si_query_hw") Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=109561 --- src/gallium/drivers/radeonsi/si_query.c | 53 ++++++++++++++----------- src/gallium/drivers/radeonsi/si_query.h | 5 ++- 2 files changed, 33 insertions(+), 25 deletions(-) diff --git a/src/gallium/drivers/radeonsi/si_query.c b/src/gallium/drivers/radeonsi/si_query.c index 5b0fba0ed92..82e3a06ae3a 100644 --- a/src/gallium/drivers/radeonsi/si_query.c +++ b/src/gallium/drivers/radeonsi/si_query.c @@ -542,55 +542,62 @@ void si_query_buffer_reset(struct si_context *sctx, struct si_query_buffer *buff while (buffer->previous) { struct si_query_buffer *qbuf = buffer->previous; buffer->previous = qbuf->previous; r600_resource_reference(&buffer->buf, NULL); buffer->buf = qbuf->buf; /* move ownership */ FREE(qbuf); } buffer->results_end = 0; + if (!buffer->buf) + return; + /* Discard even the oldest buffer if it can't be mapped without a stall. */ - if (buffer->buf && - (si_rings_is_buffer_referenced(sctx, buffer->buf->buf, RADEON_USAGE_READWRITE) || - !sctx->ws->buffer_wait(buffer->buf->buf, 0, RADEON_USAGE_READWRITE))) { + if (si_rings_is_buffer_referenced(sctx, buffer->buf->buf, RADEON_USAGE_READWRITE) || + !sctx->ws->buffer_wait(buffer->buf->buf, 0, RADEON_USAGE_READWRITE)) { r600_resource_reference(&buffer->buf, NULL); + } else { + buffer->unprepared = true; } } bool si_query_buffer_alloc(struct si_context *sctx, struct si_query_buffer *buffer, bool (*prepare_buffer)(struct si_context *, struct si_query_buffer*), unsigned size) { - if (buffer->buf && buffer->results_end + size >= buffer->buf->b.b.width0) - return true; - - if (buffer->buf) { - struct si_query_buffer *qbuf = MALLOC_STRUCT(si_query_buffer); - memcpy(qbuf, buffer, sizeof(*qbuf)); - buffer->previous = qbuf; - } + bool unprepared = buffer->unprepared; + buffer->unprepared = false; + + if (!buffer->buf || buffer->results_end + size > buffer->buf->b.b.width0) { + if (buffer->buf) { + struct si_query_buffer *qbuf = MALLOC_STRUCT(si_query_buffer); + memcpy(qbuf, buffer, sizeof(*qbuf)); + buffer->previous = qbuf; + } + buffer->results_end = 0; - buffer->results_end = 0; + /* Queries are normally read by the CPU after + * being written by the gpu, hence staging is probably a good + * usage pattern. + */ + struct si_screen *screen = sctx->screen; + unsigned buf_size = MAX2(size, screen->info.min_alloc_size); + buffer->buf = r600_resource( + pipe_buffer_create(&screen->b, 0, PIPE_USAGE_STAGING, buf_size)); + if (unlikely(!buffer->buf)) + return false; - /* Queries are normally read by the CPU after - * being written by the gpu, hence staging is probably a good - * usage pattern. - */ - struct si_screen *screen = sctx->screen; - unsigned buf_size = MAX2(size, screen->info.min_alloc_size); - buffer->buf = r600_resource( - pipe_buffer_create(&screen->b, 0, PIPE_USAGE_STAGING, buf_size)); - if (unlikely(!buffer->buf)) - return false; + unprepared = true; + } - if (prepare_buffer) { + if (unprepared && prepare_buffer) { if (unlikely(!prepare_buffer(sctx, buffer))) { r600_resource_reference(&buffer->buf, NULL); return false; } } return true; } diff --git a/src/gallium/drivers/radeonsi/si_query.h b/src/gallium/drivers/radeonsi/si_query.h index 63af760a271..469714c616f 100644 --- a/src/gallium/drivers/radeonsi/si_query.h +++ b/src/gallium/drivers/radeonsi/si_query.h @@ -170,26 +170,27 @@ struct si_query_hw_ops { struct r600_resource *buffer, uint64_t va); void (*clear_result)(struct si_query_hw *, union pipe_query_result *); void (*add_result)(struct si_screen *screen, struct si_query_hw *, void *buffer, union pipe_query_result *result); }; struct si_query_buffer { /* The buffer where query results are stored. */ struct r600_resource *buf; - /* Offset of the next free result after current query data */ - unsigned results_end; /* If a query buffer is full, a new buffer is created and the old one * is put in here. When we calculate the result, we sum up the samples * from all buffers. */ struct si_query_buffer *previous; + /* Offset of the next free result after current query data */ + unsigned results_end; + bool unprepared; }; void si_query_buffer_destroy(struct si_screen *sctx, struct si_query_buffer *buffer); void si_query_buffer_reset(struct si_context *sctx, struct si_query_buffer *buffer); bool si_query_buffer_alloc(struct si_context *sctx, struct si_query_buffer *buffer, bool (*prepare_buffer)(struct si_context *, struct si_query_buffer*), unsigned size); struct si_query_hw { -- 2.19.1