This patch uses ZPASS_DONE counters to get the mask on context creation,
then uses it for query buffer initialization. 

Signed-off-by: Vadim Girlin <vadimgir...@gmail.com>
---

Probably it's not the best way, but i hope it should be more reliable than
the current implementation. I've tested it with the juniper card which uses
backends 0 & 2 only (don't know if it is normal, maybe the card is broken,
or it's hw configuration bug, but it works fine). This patch fixes lockups with
conditional rendering. Current implementation doesn't set highest bits for
backends 1 & 3 and then conditional rendering causes gpu lockups.

 src/gallium/drivers/r600/r600.h                    |    2 +
 src/gallium/winsys/r600/drm/evergreen_hw_context.c |    2 +
 src/gallium/winsys/r600/drm/r600_hw_context.c      |   68 +++++++++++++++++++-
 3 files changed, 69 insertions(+), 3 deletions(-)

diff --git a/src/gallium/drivers/r600/r600.h b/src/gallium/drivers/r600/r600.h
index 2af4d31..b9689df 100644
--- a/src/gallium/drivers/r600/r600.h
+++ b/src/gallium/drivers/r600/r600.h
@@ -254,6 +254,7 @@ struct r600_context {
        u32                     *pm4;
        struct list_head        query_list;
        unsigned                num_query_running;
+       unsigned                zpass_backends_mask;
        struct list_head        fenced_bo;
        unsigned                max_db; /* for OQ */
        unsigned                num_dest_buffers;
@@ -275,6 +276,7 @@ struct r600_draw {
        struct r600_bo          *indices;
 };
 
+void r600_get_zpass_backends_mask(struct r600_context *ctx);
 int r600_context_init(struct r600_context *ctx, struct radeon *radeon);
 void r600_context_fini(struct r600_context *ctx);
 void r600_context_pipe_state_set(struct r600_context *ctx, struct 
r600_pipe_state *state);
diff --git a/src/gallium/winsys/r600/drm/evergreen_hw_context.c 
b/src/gallium/winsys/r600/drm/evergreen_hw_context.c
index 4d9dd50..87445ab 100644
--- a/src/gallium/winsys/r600/drm/evergreen_hw_context.c
+++ b/src/gallium/winsys/r600/drm/evergreen_hw_context.c
@@ -1018,6 +1018,8 @@ int evergreen_context_init(struct r600_context *ctx, 
struct radeon *radeon)
 
        LIST_INITHEAD(&ctx->fenced_bo);
 
+       r600_get_zpass_backends_mask(ctx);
+
        return 0;
 out_err:
        r600_context_fini(ctx);
diff --git a/src/gallium/winsys/r600/drm/r600_hw_context.c 
b/src/gallium/winsys/r600/drm/r600_hw_context.c
index a2f13ff..2fafe35 100644
--- a/src/gallium/winsys/r600/drm/r600_hw_context.c
+++ b/src/gallium/winsys/r600/drm/r600_hw_context.c
@@ -40,6 +40,64 @@
 
 #define GROUP_FORCE_NEW_BLOCK  0
 
+/* Get backends mask for ZPASS_DONE event */
+void r600_get_zpass_backends_mask(struct r600_context *ctx)
+{
+       struct r600_bo * buffer;
+       u32 * results;
+       unsigned i, mask = 0;
+
+       /* create buffer for event data */
+       buffer = r600_bo(ctx->radeon, ctx->max_db*16, 1, 0,
+                               PIPE_USAGE_STAGING);
+       if (!buffer)
+               goto err;
+
+       /* initialize buffer with zeroes */
+       results = r600_bo_map(ctx->radeon, buffer, PB_USAGE_CPU_WRITE, NULL);
+       if (results) {
+               memset(results, 0, ctx->max_db * 4 * 4);
+               r600_bo_unmap(ctx->radeon, buffer);
+
+               /* emit EVENT_WRITE for ZPASS_DONE */
+               ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE, 2, 0);
+               ctx->pm4[ctx->pm4_cdwords++] = 
EVENT_TYPE(EVENT_TYPE_ZPASS_DONE) | EVENT_INDEX(1);
+               ctx->pm4[ctx->pm4_cdwords++] = r600_bo_offset(buffer);
+               ctx->pm4[ctx->pm4_cdwords++] = 0;
+
+               ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_NOP, 0, 0);
+               ctx->pm4[ctx->pm4_cdwords++] = 0;
+               r600_context_bo_reloc(ctx, &ctx->pm4[ctx->pm4_cdwords - 1], 
buffer);
+
+               /* execute */
+               r600_context_flush(ctx);
+
+               /* analyze results */
+               results = r600_bo_map(ctx->radeon, buffer, PB_USAGE_CPU_READ, 
NULL);
+               if (results) {
+                       for(i = 0; i < ctx->max_db; i++) {
+                               /* if highest bit is set then backend is used */
+                               if (results[i*4 + 1] & 0x80000000) {
+                                       mask |= (1<<i);
+                               }
+                       }
+                       r600_bo_unmap(ctx->radeon, buffer);
+               }
+       }
+
+       r600_bo_reference(ctx->radeon, &buffer, NULL);
+
+       if (mask != 0) {
+               ctx->zpass_backends_mask = mask;
+               return;
+       }
+
+err:
+       /* fallback to old method - set num_backends lower bits to 1 */
+       ctx->zpass_backends_mask = 
(~((u32)0))>>(32-r600_get_num_backends(ctx->radeon));
+       return;
+}
+
 static inline void r600_context_ps_partial_flush(struct r600_context *ctx)
 {
        if (!(ctx->flags & R600_CONTEXT_DRAW_PENDING))
@@ -899,6 +957,8 @@ int r600_context_init(struct r600_context *ctx, struct 
radeon *radeon)
 
        ctx->max_db = 4;
 
+       r600_get_zpass_backends_mask(ctx);
+
        return 0;
 out_err:
        r600_context_fini(ctx);
@@ -1759,9 +1819,11 @@ void r600_query_begin(struct r600_context *ctx, struct 
r600_query *query)
                if (results) {
                        memset(results + query->num_results, 0, ctx->max_db * 4 
* 4);
 
-                       for (i = num_backends; i < ctx->max_db; i++) {
-                               results[(i * 4)+1] = 0x80000000;
-                               results[(i * 4)+3] = 0x80000000;
+                       for (i = 0; i < ctx->max_db; i++) {
+                               if (!(ctx->zpass_backends_mask & (1<<i))) {
+                                       results[(i * 4)+1] = 0x80000000;
+                                       results[(i * 4)+3] = 0x80000000;
+                               }
                        }
                        r600_bo_unmap(ctx->radeon, query->buffer);
                }
-- 
1.7.6

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to