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
