Use backend_map kernel query if supported, otherwise analyze ZPASS_DONE
results to get the mask.

Signed-off-by: Vadim Girlin <[email protected]>
---

I'm not sure about backend_map to mask conversion, it works for me but needs
to be verified.

 src/gallium/drivers/r600/r600.h                    |    4 +
 src/gallium/winsys/r600/drm/evergreen_hw_context.c |    2 +
 src/gallium/winsys/r600/drm/r600_drm.c             |   57 ++++++++++++
 src/gallium/winsys/r600/drm/r600_hw_context.c      |   92 ++++++++++++++++++-
 src/gallium/winsys/r600/drm/r600_priv.h            |    2 +
 5 files changed, 152 insertions(+), 5 deletions(-)

diff --git a/src/gallium/drivers/r600/r600.h b/src/gallium/drivers/r600/r600.h
index 2af4d31..b4dc879 100644
--- a/src/gallium/drivers/r600/r600.h
+++ b/src/gallium/drivers/r600/r600.h
@@ -94,6 +94,8 @@ struct r600_tiling_info *r600_get_tiling_info(struct radeon 
*radeon);
 unsigned r600_get_clock_crystal_freq(struct radeon *radeon);
 unsigned r600_get_minor_version(struct radeon *radeon);
 unsigned r600_get_num_backends(struct radeon *radeon);
+unsigned r600_get_num_tile_pipes(struct radeon *radeon);
+unsigned r600_get_backend_map(struct radeon *radeon);
 
 /* r600_bo.c */
 struct r600_bo;
@@ -254,6 +256,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 +278,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_drm.c 
b/src/gallium/winsys/r600/drm/r600_drm.c
index b5a4d92..b33a0e2 100644
--- a/src/gallium/winsys/r600/drm/r600_drm.c
+++ b/src/gallium/winsys/r600/drm/r600_drm.c
@@ -50,6 +50,14 @@
 #define RADEON_INFO_NUM_BACKENDS 0xa
 #endif
 
+#ifndef RADEON_INFO_NUM_TILE_PIPES
+#define RADEON_INFO_NUM_TILE_PIPES 0xb
+#endif
+
+#ifndef RADEON_INFO_BACKEND_MAP
+#define RADEON_INFO_BACKEND_MAP 0xd
+#endif
+
 enum radeon_family r600_get_family(struct radeon *r600)
 {
        return r600->family;
@@ -75,6 +83,16 @@ unsigned r600_get_num_backends(struct radeon *radeon)
        return radeon->num_backends;
 }
 
+unsigned r600_get_num_tile_pipes(struct radeon *radeon)
+{
+       return radeon->num_tile_pipes;
+}
+
+unsigned r600_get_backend_map(struct radeon *radeon)
+{
+       return radeon->backend_map;
+}
+
 unsigned r600_get_minor_version(struct radeon *radeon)
 {
        return radeon->minor_version;
@@ -241,6 +259,40 @@ static int radeon_get_num_backends(struct radeon *radeon)
        return 0;
 }
 
+static int radeon_get_num_tile_pipes(struct radeon *radeon)
+{
+       struct drm_radeon_info info;
+       uint32_t num_tile_pipes;
+       int r;
+
+       info.request = RADEON_INFO_NUM_TILE_PIPES;
+       info.value = (uintptr_t)&num_tile_pipes;
+       r = drmCommandWriteRead(radeon->fd, DRM_RADEON_INFO, &info,
+                       sizeof(struct drm_radeon_info));
+       if (r)
+               return r;
+
+       radeon->num_tile_pipes = num_tile_pipes;
+       return 0;
+}
+
+static int radeon_get_backend_map(struct radeon *radeon)
+{
+       struct drm_radeon_info info;
+       uint32_t backend_map;
+       int r;
+
+       info.request = RADEON_INFO_BACKEND_MAP;
+       info.value = (uintptr_t)&backend_map;
+       r = drmCommandWriteRead(radeon->fd, DRM_RADEON_INFO, &info,
+                       sizeof(struct drm_radeon_info));
+       if (r)
+               return r;
+
+       radeon->backend_map = backend_map;
+       return 0;
+}
+
 
 static int radeon_init_fence(struct radeon *radeon)
 {
@@ -362,6 +414,11 @@ static struct radeon *radeon_new(int fd, unsigned device)
        if (radeon->minor_version >= 9)
                radeon_get_num_backends(radeon);
 
+       if (radeon->minor_version >= 11) {
+               radeon_get_num_tile_pipes(radeon);
+               radeon_get_backend_map(radeon);
+       }
+
        radeon->bomgr = r600_bomgr_create(radeon, 1000000);
        if (radeon->bomgr == NULL) {
                return NULL;
diff --git a/src/gallium/winsys/r600/drm/r600_hw_context.c 
b/src/gallium/winsys/r600/drm/r600_hw_context.c
index a2f13ff..cccefea 100644
--- a/src/gallium/winsys/r600/drm/r600_hw_context.c
+++ b/src/gallium/winsys/r600/drm/r600_hw_context.c
@@ -40,6 +40,85 @@
 
 #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;
+       unsigned backend_map, num_tile_pipes, num_backends;
+
+       num_backends = r600_get_num_backends(ctx->radeon);
+       num_tile_pipes = r600_get_num_tile_pipes(ctx->radeon);
+       backend_map = r600_get_backend_map(ctx->radeon);
+
+       /* if backend_map query is supported by the kernel */
+       if (backend_map!=0) {
+               while(num_tile_pipes--) {
+                       i = backend_map & 0xF;
+                       if (i < num_backends)
+                               mask |= (1<<i);
+                       backend_map >>= 4;
+               }
+               if (mask != 0) {
+                       ctx->zpass_backends_mask = mask;
+                       return;
+               }
+       }
+
+       /* otherwise backup path for older kernels */
+
+       /* 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-num_backends);
+       return;
+}
+
 static inline void r600_context_ps_partial_flush(struct r600_context *ctx)
 {
        if (!(ctx->flags & R600_CONTEXT_DRAW_PENDING))
@@ -899,6 +978,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);
@@ -1726,7 +1807,6 @@ static boolean r600_query_result(struct r600_context 
*ctx, struct r600_query *qu
 void r600_query_begin(struct r600_context *ctx, struct r600_query *query)
 {
        unsigned required_space, required_buffer;
-       int num_backends = r600_get_num_backends(ctx->radeon);
 
        /* query request needs 6/8 dwords for begin + 6/8 dwords for end */
        if (query->type == PIPE_QUERY_TIME_ELAPSED)
@@ -1750,7 +1830,7 @@ void r600_query_begin(struct r600_context *ctx, struct 
r600_query *query)
        }
 
        if (query->type == PIPE_QUERY_OCCLUSION_COUNTER &&
-           num_backends > 0) {
+           ctx->zpass_backends_mask != 0) {
                /* as per info on ZPASS the driver must set the unusued DB top 
bits */
                u32 *results;
                int i;
@@ -1759,9 +1839,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);
                }
diff --git a/src/gallium/winsys/r600/drm/r600_priv.h 
b/src/gallium/winsys/r600/drm/r600_priv.h
index 69f7251..cf3be09 100644
--- a/src/gallium/winsys/r600/drm/r600_priv.h
+++ b/src/gallium/winsys/r600/drm/r600_priv.h
@@ -55,6 +55,8 @@ struct radeon {
        struct r600_bo                  *fence_bo;
        unsigned                        clock_crystal_freq;
        unsigned                        num_backends;
+       unsigned                        num_tile_pipes;
+       unsigned                        backend_map;
        unsigned                        minor_version;
 
         /* List of buffer handles and its mutex. */
-- 
1.7.6

_______________________________________________
mesa-dev mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to