From 63d010115c7972d854e0583f8f74e8d0c3407fcd Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 17 Aug 2010 16:07:23 +1000 Subject: [PATCH] r600g: add occlusion query support Signed-off-by: Dave Airlie Signed-off-by: Jerome Glisse --- src/gallium/drivers/r600/r600_blit.c | 34 ++-- src/gallium/drivers/r600/r600_context.c | 13 +- src/gallium/drivers/r600/r600_context.h | 37 +++- src/gallium/drivers/r600/r600_query.c | 208 +++++++++++++++++++++- src/gallium/drivers/r600/r600_state.c | 1 - src/gallium/drivers/r600/radeon.h | 30 ++-- src/gallium/winsys/r600/drm/r600_state.c | 36 ++++ src/gallium/winsys/r600/drm/r600_states.h | 25 ++- src/gallium/winsys/r600/drm/r600d.h | 1 + src/gallium/winsys/r600/drm/radeon_ctx.c | 36 +++- 10 files changed, 379 insertions(+), 42 deletions(-) diff --git a/src/gallium/drivers/r600/r600_blit.c b/src/gallium/drivers/r600/r600_blit.c index db7aef7ebd2..aef4fbd9af9 100644 --- a/src/gallium/drivers/r600/r600_blit.c +++ b/src/gallium/drivers/r600/r600_blit.c @@ -32,8 +32,10 @@ #include "r600_screen.h" #include "r600_context.h" -static void r600_blitter_save_states(struct r600_context *rctx) +static void r600_blitter_save_states(struct pipe_context *ctx) { + struct r600_context *rctx = r600_context(ctx); + util_blitter_save_blend(rctx->blitter, rctx->blend); util_blitter_save_depth_stencil_alpha(rctx->blitter, rctx->dsa); if (rctx->stencil_ref) { @@ -47,8 +49,9 @@ static void r600_blitter_save_states(struct r600_context *rctx) if (rctx->viewport) { util_blitter_save_viewport(rctx->blitter, &rctx->viewport->state.viewport); } - if (rctx->clip) - util_blitter_save_clip(rctx->blitter, &rctx->clip->state.clip); + if (rctx->clip) { + util_blitter_save_clip(rctx->blitter, &rctx->clip->state.clip); + } util_blitter_save_vertex_buffers(rctx->blitter, rctx->nvertex_buffer, rctx->vertex_buffer); @@ -60,37 +63,44 @@ static void r600_blitter_save_states(struct r600_context *rctx) rctx->rasterizer = NULL; rctx->dsa = NULL; rctx->vertex_elements = NULL; + + /* suspend queries */ + r600_queries_suspend(ctx); } static void r600_clear(struct pipe_context *ctx, unsigned buffers, - const float *rgba, double depth, unsigned stencil) + const float *rgba, double depth, unsigned stencil) { struct r600_context *rctx = r600_context(ctx); struct pipe_framebuffer_state *fb = &rctx->framebuffer->state.framebuffer; - r600_blitter_save_states(rctx); + r600_blitter_save_states(ctx); util_blitter_clear(rctx->blitter, fb->width, fb->height, fb->nr_cbufs, buffers, rgba, depth, stencil); + /* resume queries */ + r600_queries_resume(ctx); } -static void r600_clear_render_target(struct pipe_context *pipe, +static void r600_clear_render_target(struct pipe_context *ctx, struct pipe_surface *dst, const float *rgba, unsigned dstx, unsigned dsty, unsigned width, unsigned height) { - struct r600_context *rctx = r600_context(pipe); + struct r600_context *rctx = r600_context(ctx); struct pipe_framebuffer_state *fb = &rctx->framebuffer->state.framebuffer; - r600_blitter_save_states(rctx); + r600_blitter_save_states(ctx); util_blitter_save_framebuffer(rctx->blitter, fb); util_blitter_clear_render_target(rctx->blitter, dst, rgba, dstx, dsty, width, height); + /* resume queries */ + r600_queries_resume(ctx); } -static void r600_clear_depth_stencil(struct pipe_context *pipe, +static void r600_clear_depth_stencil(struct pipe_context *ctx, struct pipe_surface *dst, unsigned clear_flags, double depth, @@ -98,14 +108,16 @@ static void r600_clear_depth_stencil(struct pipe_context *pipe, unsigned dstx, unsigned dsty, unsigned width, unsigned height) { - struct r600_context *rctx = r600_context(pipe); + struct r600_context *rctx = r600_context(ctx); struct pipe_framebuffer_state *fb = &rctx->framebuffer->state.framebuffer; - r600_blitter_save_states(rctx); + r600_blitter_save_states(ctx); util_blitter_save_framebuffer(rctx->blitter, fb); util_blitter_clear_depth_stencil(rctx->blitter, dst, clear_flags, depth, stencil, dstx, dsty, width, height); + /* resume queries */ + r600_queries_resume(ctx); } static void r600_resource_copy_region(struct pipe_context *pipe, diff --git a/src/gallium/drivers/r600/r600_context.c b/src/gallium/drivers/r600/r600_context.c index edde80c660a..2f59a550f56 100644 --- a/src/gallium/drivers/r600/r600_context.c +++ b/src/gallium/drivers/r600/r600_context.c @@ -34,6 +34,7 @@ #include "r600_resource.h" #include "r600d.h" + static void r600_destroy_context(struct pipe_context *context) { struct r600_context *rctx = r600_context(context); @@ -46,26 +47,34 @@ void r600_flush(struct pipe_context *ctx, unsigned flags, { struct r600_context *rctx = r600_context(ctx); struct r600_screen *rscreen = rctx->screen; + struct r600_query *rquery; static int dc = 0; char dname[256]; + /* suspend queries */ + r600_queries_suspend(rctx); if (radeon_ctx_pm4(rctx->ctx)) - return; + goto out; /* FIXME dumping should be removed once shader support instructions * without throwing bad code */ if (!rctx->ctx->cpm4) goto out; sprintf(dname, "gallium-%08d.bof", dc); - if (dc < 1) + if (dc < 10) radeon_ctx_dump_bof(rctx->ctx, dname); #if 1 radeon_ctx_submit(rctx->ctx); #endif + LIST_FOR_EACH_ENTRY(rquery, &rctx->query_list, list) { + rquery->flushed = true; + } dc++; out: rctx->ctx = radeon_ctx_decref(rctx->ctx); rctx->ctx = radeon_ctx(rscreen->rw); + /* resume queries */ + r600_queries_resume(rctx); } static void r600_init_config(struct r600_context *rctx) diff --git a/src/gallium/drivers/r600/r600_context.h b/src/gallium/drivers/r600/r600_context.h index 2ce29720d9c..900aa9fd0c2 100644 --- a/src/gallium/drivers/r600/r600_context.h +++ b/src/gallium/drivers/r600/r600_context.h @@ -30,9 +30,32 @@ #include #include #include +#include #include "radeon.h" #include "r600_shader.h" +#define R600_QUERY_STATE_STARTED (1 << 0) +#define R600_QUERY_STATE_ENDED (1 << 1) +#define R600_QUERY_STATE_SUSPENDED (1 << 2) + +struct r600_query { + u64 result; + /* The kind of query. Currently only OQ is supported. */ + unsigned type; + /* How many results have been written, in dwords. It's incremented + * after end_query and flush. */ + unsigned num_results; + /* if we've flushed the query */ + boolean flushed; + unsigned state; + /* The buffer where query results are stored. */ + struct radeon_bo *buffer; + unsigned buffer_size; + /* linked list of queries */ + struct list_head list; + struct radeon_state *rstate; +}; + /* XXX move this to a more appropriate place */ union pipe_states { struct pipe_rasterizer_state rasterizer; @@ -142,7 +165,8 @@ struct r600_context { struct r600_vertex_element *vertex_elements; struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; struct pipe_index_buffer index_buffer; - struct pipe_blend_color blend_color; + struct pipe_blend_color blend_color; + struct list_head query_list; }; /* Convenience cast wrapper. */ @@ -151,6 +175,11 @@ static INLINE struct r600_context *r600_context(struct pipe_context *pipe) return (struct r600_context*)pipe; } +static INLINE struct r600_query* r600_query(struct pipe_query* q) +{ + return (struct r600_query*)q; +} + struct r600_context_state *r600_context_state(struct r600_context *rctx, unsigned type, const void *state); struct r600_context_state *r600_context_state_incref(struct r600_context_state *rstate); struct r600_context_state *r600_context_state_decref(struct r600_context_state *rstate); @@ -179,4 +208,10 @@ extern int r600_pipe_shader_update(struct pipe_context *ctx, uint32_t r600_translate_texformat(enum pipe_format format, const unsigned char *swizzle_view, uint32_t *word4_p, uint32_t *yuv_format_p); + +/* query */ +extern void r600_queries_resume(struct pipe_context *ctx); +extern void r600_queries_suspend(struct pipe_context *ctx); + + #endif diff --git a/src/gallium/drivers/r600/r600_query.c b/src/gallium/drivers/r600/r600_query.c index 9b02ae680e7..5929606cd28 100644 --- a/src/gallium/drivers/r600/r600_query.c +++ b/src/gallium/drivers/r600/r600_query.c @@ -24,39 +24,233 @@ * Jerome Glisse * Corbin Simpson */ +#include #include #include #include #include "r600_screen.h" #include "r600_context.h" -static struct pipe_query *r600_create_query(struct pipe_context *pipe, unsigned query_type) +static struct radeon_state *r600_query_begin(struct r600_context *rctx, struct r600_query *rquery) { - return NULL; + struct r600_screen *rscreen = rctx->screen; + struct radeon_state *rstate; + + rstate = radeon_state(rscreen->rw, R600_QUERY_BEGIN_TYPE, R600_QUERY_BEGIN); + if (rstate == NULL) + return NULL; + rstate->states[R600_QUERY__OFFSET] = rquery->num_results; + rstate->bo[0] = radeon_bo_incref(rscreen->rw, rquery->buffer); + rstate->nbo = 1; + rstate->placement[0] = RADEON_GEM_DOMAIN_GTT; + if (radeon_state_pm4(rstate)) { + radeon_state_decref(rstate); + return NULL; + } + return rstate; } -static void r600_destroy_query(struct pipe_context *pipe, struct pipe_query *query) +static struct radeon_state *r600_query_end(struct r600_context *rctx, struct r600_query *rquery) { + struct r600_screen *rscreen = rctx->screen; + struct radeon_state *rstate; + + rstate = radeon_state(rscreen->rw, R600_QUERY_END_TYPE, R600_QUERY_END); + if (rstate == NULL) + return NULL; + rstate->states[R600_QUERY__OFFSET] = rquery->num_results + 8; + rstate->bo[0] = radeon_bo_incref(rscreen->rw, rquery->buffer); + rstate->nbo = 1; + rstate->placement[0] = RADEON_GEM_DOMAIN_GTT; + if (radeon_state_pm4(rstate)) { + radeon_state_decref(rstate); + return NULL; + } + return rstate; +} + +static struct pipe_query *r600_create_query(struct pipe_context *ctx, unsigned query_type) +{ + struct r600_screen *rscreen = r600_screen(ctx->screen); + struct r600_context *rctx = r600_context(ctx); + struct r600_query *q; + + if (query_type != PIPE_QUERY_OCCLUSION_COUNTER) + return NULL; + + q = CALLOC_STRUCT(r600_query); + if (!q) + return NULL; + + q->type = query_type; + LIST_ADDTAIL(&q->list, &rctx->query_list); + q->buffer_size = 4096; + + q->buffer = radeon_bo(rscreen->rw, 0, q->buffer_size, 1, NULL); + if (!q->buffer) { + FREE(q); + return NULL; + } + return (struct pipe_query *)q; +} + +static void r600_destroy_query(struct pipe_context *ctx, + struct pipe_query *query) +{ + struct r600_screen *rscreen = r600_screen(ctx->screen); + struct r600_query *q = r600_query(query); + + radeon_bo_decref(rscreen->rw, q->buffer); + LIST_DEL(&q->list); FREE(query); } -static void r600_begin_query(struct pipe_context *pipe, struct pipe_query *query) +static void r600_query_result(struct pipe_context *ctx, struct r600_query *rquery) { + struct r600_screen *rscreen = r600_screen(ctx->screen); + u64 start, end; + u32 *results; + int i; + + radeon_bo_wait(rscreen->rw, rquery->buffer); + radeon_bo_map(rscreen->rw, rquery->buffer); + results = rquery->buffer->data; + for (i = 0; i < rquery->num_results; i += 4) { + start = (u64)results[i] | (u64)results[i + 1] << 32; + end = (u64)results[i + 2] | (u64)results[i + 3] << 32; + if ((start & 0x8000000000000000UL) && (end & 0x8000000000000000UL)) { + rquery->result += end - start; + } + } + radeon_bo_unmap(rscreen->rw, rquery->buffer); + rquery->num_results = 0; } -static void r600_end_query(struct pipe_context *pipe, struct pipe_query *query) +static void r600_query_resume(struct pipe_context *ctx, struct r600_query *rquery) { + struct r600_context *rctx = r600_context(ctx); + + if (rquery->num_results >= ((rquery->buffer_size >> 2) - 2)) { + /* running out of space */ + if (!rquery->flushed) { + ctx->flush(ctx, 0, NULL); + } + r600_query_result(ctx, rquery); + } + rquery->rstate = radeon_state_decref(rquery->rstate); + rquery->rstate = r600_query_begin(rctx, rquery); + rquery->flushed = false; } -static boolean r600_get_query_result(struct pipe_context *pipe, +static void r600_query_suspend(struct pipe_context *ctx, struct r600_query *rquery) +{ + struct r600_context *rctx = r600_context(ctx); + + rquery->rstate = radeon_state_decref(rquery->rstate); + rquery->rstate = r600_query_end(rctx, rquery); + rquery->num_results += 16; +} + +static void r600_begin_query(struct pipe_context *ctx, struct pipe_query *query) +{ + struct r600_context *rctx = r600_context(ctx); + struct r600_query *rquery = r600_query(query); + int r; + + rquery->state = R600_QUERY_STATE_STARTED; + rquery->num_results = 0; + rquery->flushed = false; + r600_query_resume(ctx, rquery); + r = radeon_ctx_set_query_state(rctx->ctx, rquery->rstate); + if (r == -EBUSY) { + /* this shouldn't happen */ + R600_ERR("had to flush while emitting end query\n"); + ctx->flush(ctx, 0, NULL); + r = radeon_ctx_set_query_state(rctx->ctx, rquery->rstate); + } +} + +static void r600_end_query(struct pipe_context *ctx, struct pipe_query *query) +{ + struct r600_context *rctx = r600_context(ctx); + struct r600_query *rquery = r600_query(query); + int r; + + rquery->state &= ~R600_QUERY_STATE_STARTED; + rquery->state |= R600_QUERY_STATE_ENDED; + r600_query_suspend(ctx, rquery); + r = radeon_ctx_set_query_state(rctx->ctx, rquery->rstate); + if (r == -EBUSY) { + /* this shouldn't happen */ + R600_ERR("had to flush while emitting end query\n"); + ctx->flush(ctx, 0, NULL); + r = radeon_ctx_set_query_state(rctx->ctx, rquery->rstate); + } +} + +void r600_queries_suspend(struct pipe_context *ctx) +{ + struct r600_context *rctx = r600_context(ctx); + struct r600_query *rquery; + int r; + + LIST_FOR_EACH_ENTRY(rquery, &rctx->query_list, list) { + if (rquery->state & R600_QUERY_STATE_STARTED) { + r600_query_suspend(ctx, rquery); + r = radeon_ctx_set_query_state(rctx->ctx, rquery->rstate); + if (r == -EBUSY) { + /* this shouldn't happen */ + R600_ERR("had to flush while emitting end query\n"); + ctx->flush(ctx, 0, NULL); + r = radeon_ctx_set_query_state(rctx->ctx, rquery->rstate); + } + } + rquery->state |= R600_QUERY_STATE_SUSPENDED; + } +} + +void r600_queries_resume(struct pipe_context *ctx) +{ + struct r600_context *rctx = r600_context(ctx); + struct r600_query *rquery; + int r; + + LIST_FOR_EACH_ENTRY(rquery, &rctx->query_list, list) { + if (rquery->state & R600_QUERY_STATE_STARTED) { + r600_query_resume(ctx, rquery); + r = radeon_ctx_set_query_state(rctx->ctx, rquery->rstate); + if (r == -EBUSY) { + /* this shouldn't happen */ + R600_ERR("had to flush while emitting end query\n"); + ctx->flush(ctx, 0, NULL); + r = radeon_ctx_set_query_state(rctx->ctx, rquery->rstate); + } + } + rquery->state &= ~R600_QUERY_STATE_SUSPENDED; + } +} + +static boolean r600_get_query_result(struct pipe_context *ctx, struct pipe_query *query, - boolean wait, void *result) + boolean wait, void *vresult) { + struct r600_query *rquery = r600_query(query); + uint64_t *result = (uint64_t*)vresult; + + if (!rquery->flushed) { + ctx->flush(ctx, 0, NULL); + rquery->flushed = true; + } + r600_query_result(ctx, rquery); + *result = rquery->result; + rquery->result = 0; return TRUE; } void r600_init_query_functions(struct r600_context* rctx) { + LIST_INITHEAD(&rctx->query_list); + rctx->context.create_query = r600_create_query; rctx->context.destroy_query = r600_destroy_query; rctx->context.begin_query = r600_begin_query; diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c index 7d2b61f9b01..3943ebacb36 100644 --- a/src/gallium/drivers/r600/r600_state.c +++ b/src/gallium/drivers/r600/r600_state.c @@ -268,7 +268,6 @@ static void r600_set_blend_color(struct pipe_context *ctx, static void r600_set_clip_state(struct pipe_context *ctx, const struct pipe_clip_state *state) { - struct r600_screen *rscreen = r600_screen(ctx->screen); struct r600_context *rctx = r600_context(ctx); struct r600_context_state *rstate; diff --git a/src/gallium/drivers/r600/radeon.h b/src/gallium/drivers/r600/radeon.h index d36c89d6a72..b2cc74f6967 100644 --- a/src/gallium/drivers/r600/radeon.h +++ b/src/gallium/drivers/r600/radeon.h @@ -151,6 +151,7 @@ struct radeon_ctx *radeon_ctx(struct radeon *radeon); struct radeon_ctx *radeon_ctx_decref(struct radeon_ctx *ctx); struct radeon_ctx *radeon_ctx_incref(struct radeon_ctx *ctx); int radeon_ctx_set_draw(struct radeon_ctx *ctx, struct radeon_draw *draw); +int radeon_ctx_set_query_state(struct radeon_ctx *ctx, struct radeon_state *state); int radeon_ctx_set_draw_new(struct radeon_ctx *ctx, struct radeon_draw *draw); int radeon_ctx_pm4(struct radeon_ctx *ctx); int radeon_ctx_submit(struct radeon_ctx *ctx); @@ -191,8 +192,8 @@ struct radeon_ctx { * R600/R700 */ -#define R600_NSTATE 1286 -#define R600_NTYPE 33 +#define R600_NSTATE 1288 +#define R600_NTYPE 35 #define R600_CONFIG 0 #define R600_CONFIG_TYPE 0 @@ -252,14 +253,18 @@ struct radeon_ctx { #define R600_CB6_TYPE 27 #define R600_CB7 1276 #define R600_CB7_TYPE 28 -#define R600_DB 1277 -#define R600_DB_TYPE 29 -#define R600_CLIP 1278 -#define R600_CLIP_TYPE 30 -#define R600_VGT 1284 -#define R600_VGT_TYPE 31 -#define R600_DRAW 1285 -#define R600_DRAW_TYPE 32 +#define R600_QUERY_BEGIN 1277 +#define R600_QUERY_BEGIN_TYPE 29 +#define R600_QUERY_END 1278 +#define R600_QUERY_END_TYPE 30 +#define R600_DB 1279 +#define R600_DB_TYPE 31 +#define R600_CLIP 1280 +#define R600_CLIP_TYPE 32 +#define R600_VGT 1286 +#define R600_VGT_TYPE 33 +#define R600_DRAW 1287 +#define R600_DRAW_TYPE 34 /* R600_CONFIG */ #define R600_CONFIG__SQ_CONFIG 0 @@ -653,4 +658,9 @@ struct radeon_ctx { #define R600_CLIP__PA_CL_UCP_W_0 3 #define R600_CLIP_SIZE 4 #define R600_CLIP_PM4 128 +/* R600 QUERY BEGIN/END */ +#define R600_QUERY__OFFSET 0 +#define R600_QUERY_SIZE 1 +#define R600_QUERY_PM4 128 + #endif diff --git a/src/gallium/winsys/r600/drm/r600_state.c b/src/gallium/winsys/r600/drm/r600_state.c index 2facec75dec..9b7c11bdc06 100644 --- a/src/gallium/winsys/r600/drm/r600_state.c +++ b/src/gallium/winsys/r600/drm/r600_state.c @@ -38,6 +38,8 @@ static int r600_state_pm4_shader(struct radeon_state *state); static int r600_state_pm4_draw(struct radeon_state *state); static int r600_state_pm4_config(struct radeon_state *state); static int r600_state_pm4_generic(struct radeon_state *state); +static int r600_state_pm4_query_begin(struct radeon_state *state); +static int r600_state_pm4_query_end(struct radeon_state *state); static int r700_state_pm4_config(struct radeon_state *state); static int r700_state_pm4_cb0(struct radeon_state *state); static int r700_state_pm4_db(struct radeon_state *state); @@ -240,6 +242,40 @@ static int r600_state_pm4_config(struct radeon_state *state) return r600_state_pm4_generic(state); } +static int r600_state_pm4_query_begin(struct radeon_state *state) +{ + int r; + + state->cpm4 = 0; + state->pm4[state->cpm4++] = PKT3(PKT3_EVENT_WRITE, 2); + state->pm4[state->cpm4++] = EVENT_TYPE_ZPASS_DONE; + state->pm4[state->cpm4++] = state->states[0]; + state->pm4[state->cpm4++] = 0x0; + state->pm4[state->cpm4++] = PKT3(PKT3_NOP, 0); + r = radeon_state_reloc(state, state->cpm4, 0); + if (r) + return r; + state->pm4[state->cpm4++] = state->bo[0]->handle; + return 0; +} + +static int r600_state_pm4_query_end(struct radeon_state *state) +{ + int r; + + state->cpm4 = 0; + state->pm4[state->cpm4++] = PKT3(PKT3_EVENT_WRITE, 2); + state->pm4[state->cpm4++] = EVENT_TYPE_ZPASS_DONE; + state->pm4[state->cpm4++] = state->states[0]; + state->pm4[state->cpm4++] = 0x0; + state->pm4[state->cpm4++] = PKT3(PKT3_NOP, 0); + r = radeon_state_reloc(state, state->cpm4, 0); + if (r) + return r; + state->pm4[state->cpm4++] = state->bo[0]->handle; + return 0; +} + static int r700_state_pm4_config(struct radeon_state *state) { state->pm4[state->cpm4++] = PKT3(PKT3_CONTEXT_CONTROL, 1); diff --git a/src/gallium/winsys/r600/drm/r600_states.h b/src/gallium/winsys/r600/drm/r600_states.h index 2d7a1d31c8c..b5365e4275a 100644 --- a/src/gallium/winsys/r600/drm/r600_states.h +++ b/src/gallium/winsys/r600/drm/r600_states.h @@ -479,6 +479,10 @@ static const struct radeon_register R600_DRAW_names[] = { {0x000287F0, 0, 0, "VGT_DRAW_INITIATOR"}, }; +static const struct radeon_register R600_VGT_EVENT_names[] = { + {0x00028A90, 1, 0, "VGT_EVENT_INITIATOR"}, +}; + static struct radeon_type R600_types[] = { { 128, 0, 0x00000000, 0x00000000, 0x0000, 0, "R600_CONFIG", 41, r600_state_pm4_config, R600_CONFIG_names}, { 128, 1, 0x00000000, 0x00000000, 0x0000, 0, "R600_CB_CNTL", 18, r600_state_pm4_generic, R600_CB_CNTL_names}, @@ -509,11 +513,12 @@ static struct radeon_type R600_types[] = { { 128, 1274, 0x00000000, 0x00000000, 0x0000, 0, "R600_CB5", 7, r600_state_pm4_cb0, R600_CB5_names}, { 128, 1275, 0x00000000, 0x00000000, 0x0000, 0, "R600_CB6", 7, r600_state_pm4_cb0, R600_CB6_names}, { 128, 1276, 0x00000000, 0x00000000, 0x0000, 0, "R600_CB7", 7, r600_state_pm4_cb0, R600_CB7_names}, - { 128, 1277, 0x00000000, 0x00000000, 0x0000, 0, "R600_DB", 6, r600_state_pm4_db, R600_DB_names}, - { 128, 1278, 0x00028e20, 0x00028e70, 0x0010, 0, "R600_UCP", 4, r600_state_pm4_generic, R600_UCP_names}, - { 128, 1284, 0x00000000, 0x00000000, 0x0000, 0, "R600_VGT", 11, r600_state_pm4_vgt, R600_VGT_names}, - { 128, 1285, 0x00000000, 0x00000000, 0x0000, 0, "R600_DRAW", 4, r600_state_pm4_draw, R600_DRAW_names}, - + { 128, 1277, 0x00000000, 0x00000000, 0x0000, 0, "R600_QUERY_BEGIN", 1, r600_state_pm4_query_begin, R600_VGT_EVENT_names}, + { 128, 1278, 0x00000000, 0x00000000, 0x0000, 0, "R600_QUERY_END", 1, r600_state_pm4_query_end, R600_VGT_EVENT_names}, + { 128, 1279, 0x00000000, 0x00000000, 0x0000, 0, "R600_DB", 6, r600_state_pm4_db, R600_DB_names}, + { 128, 1280, 0x00028e20, 0x00028e70, 0x0010, 0, "R600_UCP", 4, r600_state_pm4_generic, R600_UCP_names}, + { 128, 1286, 0x00000000, 0x00000000, 0x0000, 0, "R600_VGT", 11, r600_state_pm4_vgt, R600_VGT_names}, + { 128, 1287, 0x00000000, 0x00000000, 0x0000, 0, "R600_DRAW", 4, r600_state_pm4_draw, R600_DRAW_names}, }; static struct radeon_type R700_types[] = { @@ -546,10 +551,12 @@ static struct radeon_type R700_types[] = { { 128, 1274, 0x00000000, 0x00000000, 0x0000, 0, "R600_CB5", 7, r600_state_pm4_cb0, R600_CB5_names}, { 128, 1275, 0x00000000, 0x00000000, 0x0000, 0, "R600_CB6", 7, r600_state_pm4_cb0, R600_CB6_names}, { 128, 1276, 0x00000000, 0x00000000, 0x0000, 0, "R600_CB7", 7, r600_state_pm4_cb0, R600_CB7_names}, - { 128, 1277, 0x00000000, 0x00000000, 0x0000, 0, "R600_DB", 6, r700_state_pm4_db, R600_DB_names}, - { 128, 1278, 0x00028e20, 0x00028e70, 0x0010, 0, "R600_UCP", 4, r600_state_pm4_generic, R600_UCP_names}, - { 128, 1284, 0x00000000, 0x00000000, 0x0000, 0, "R600_VGT", 11, r600_state_pm4_vgt, R600_VGT_names}, - { 128, 1285, 0x00000000, 0x00000000, 0x0000, 0, "R600_DRAW", 4, r600_state_pm4_draw, R600_DRAW_names}, + { 128, 1277, 0x00000000, 0x00000000, 0x0000, 0, "R600_QUERY_BEGIN", 1, r600_state_pm4_query_begin, R600_VGT_EVENT_names}, + { 128, 1278, 0x00000000, 0x00000000, 0x0000, 0, "R600_QUERY_END", 1, r600_state_pm4_query_end, R600_VGT_EVENT_names}, + { 128, 1279, 0x00000000, 0x00000000, 0x0000, 0, "R600_DB", 6, r700_state_pm4_db, R600_DB_names}, + { 128, 1280, 0x00028e20, 0x00028e70, 0x0010, 0, "R600_UCP", 4, r600_state_pm4_generic, R600_UCP_names}, + { 128, 1286, 0x00000000, 0x00000000, 0x0000, 0, "R600_VGT", 11, r600_state_pm4_vgt, R600_VGT_names}, + { 128, 1287, 0x00000000, 0x00000000, 0x0000, 0, "R600_DRAW", 4, r600_state_pm4_draw, R600_DRAW_names}, }; #endif diff --git a/src/gallium/winsys/r600/drm/r600d.h b/src/gallium/winsys/r600/drm/r600d.h index 235b2b3d976..e8c2dc0651c 100644 --- a/src/gallium/winsys/r600/drm/r600d.h +++ b/src/gallium/winsys/r600/drm/r600d.h @@ -82,6 +82,7 @@ #define PKT3_SET_CTL_CONST 0x6F #define PKT3_SURFACE_BASE_UPDATE 0x73 +#define EVENT_TYPE_ZPASS_DONE 0x15 #define EVENT_TYPE_CACHE_FLUSH_AND_INV_EVENT 0x16 #define PKT_TYPE_S(x) (((x) & 0x3) << 30) diff --git a/src/gallium/winsys/r600/drm/radeon_ctx.c b/src/gallium/winsys/r600/drm/radeon_ctx.c index 45b706bb0f9..bd050c4cf90 100644 --- a/src/gallium/winsys/r600/drm/radeon_ctx.c +++ b/src/gallium/winsys/r600/drm/radeon_ctx.c @@ -224,6 +224,41 @@ static int radeon_ctx_state_schedule(struct radeon_ctx *ctx, struct radeon_state return 0; } +int radeon_ctx_set_query_state(struct radeon_ctx *ctx, struct radeon_state *state) +{ + void *tmp; + int r = 0; + + /* !!! ONLY ACCEPT QUERY STATE HERE !!! */ + if (state->type != R600_QUERY_BEGIN_TYPE && state->type != R600_QUERY_END_TYPE) { + return -EINVAL; + } + r = radeon_state_pm4(state); + if (r) + return r; + if ((ctx->draw_cpm4 + state->cpm4) > RADEON_CTX_MAX_PM4) { + /* need to flush */ + return -EBUSY; + } + if (state->cpm4 >= RADEON_CTX_MAX_PM4) { + fprintf(stderr, "%s single state too big %d, max %d\n", + __func__, state->cpm4, RADEON_CTX_MAX_PM4); + return -EINVAL; + } + tmp = realloc(ctx->state, (ctx->nstate + 1) * sizeof(void*)); + if (tmp == NULL) + return -ENOMEM; + ctx->state = tmp; + ctx->state[ctx->nstate++] = radeon_state_incref(state); + /* BEGIN/END query are balanced in the same cs so account for END + * END query when scheduling BEGIN query + */ + if (state->type == R600_QUERY_BEGIN_TYPE) { + ctx->draw_cpm4 += state->cpm4 * 2; + } + return 0; +} + int radeon_ctx_set_draw_new(struct radeon_ctx *ctx, struct radeon_draw *draw) { struct radeon_draw *pdraw = NULL; @@ -366,7 +401,6 @@ printf("%d pm4\n", ctx->cpm4); if (bo == NULL) goto out_err; size = bof_int32(ctx->bo[i]->size); -printf("[%d] %d bo\n", i, size); if (size == NULL) goto out_err; if (bof_object_set(bo, "size", size))