radeonsi: fix query buffer allocation
authorTimothy Arceri <tarceri@itsqueeze.com>
Sun, 24 Feb 2019 23:55:57 +0000 (10:55 +1100)
committerTimothy Arceri <tarceri@itsqueeze.com>
Mon, 25 Feb 2019 22:55:41 +0000 (09:55 +1100)
Fix the logic for buffer full check on alloc.

This patch just takes the fix Nicolai attached to the bug report
and updates it to work on master.

Fixes: e0f0d3675d4 ("radeonsi: factor si_query_buffer logic out of si_query_hw")

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=109561

src/gallium/drivers/radeonsi/si_query.c
src/gallium/drivers/radeonsi/si_query.h

index 266b9d3..280eee3 100644 (file)
@@ -549,11 +549,15 @@ void si_query_buffer_reset(struct si_context *sctx, struct si_query_buffer *buff
        }
        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)) {
                si_resource_reference(&buffer->buf, NULL);
+       } else {
+               buffer->unprepared = true;
        }
 }
 
@@ -561,29 +565,31 @@ bool si_query_buffer_alloc(struct si_context *sctx, struct si_query_buffer *buff
                           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;
+       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;
 
-       if (buffer->buf) {
-               struct si_query_buffer *qbuf = MALLOC_STRUCT(si_query_buffer);
-               memcpy(qbuf, buffer, sizeof(*qbuf));
-               buffer->previous = qbuf;
+               /* 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 = si_resource(
+                       pipe_buffer_create(&screen->b, 0, PIPE_USAGE_STAGING, buf_size));
+               if (unlikely(!buffer->buf))
+                       return false;
+               unprepared = true;
        }
 
-       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 = si_resource(
-               pipe_buffer_create(&screen->b, 0, PIPE_USAGE_STAGING, buf_size));
-       if (unlikely(!buffer->buf))
-               return false;
-
-       if (prepare_buffer) {
+       if (unprepared && prepare_buffer) {
                if (unlikely(!prepare_buffer(sctx, buffer))) {
                        si_resource_reference(&buffer->buf, NULL);
                        return false;
index aaf0bd0..c61af51 100644 (file)
@@ -177,12 +177,13 @@ struct si_query_hw_ops {
 struct si_query_buffer {
        /* The buffer where query results are stored. */
        struct si_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);