From d69e557f2a2c39888d83c7b52244412ee2a5594e Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Sat, 7 Nov 2015 23:20:31 -0500 Subject: [PATCH] freedreno: add support for conditional rendering, required for GL3.0 A smarter implementation would make it possible to attach this to emit state for the BY_REGION versions to avoid breaking the tiling. But this is a start. Signed-off-by: Ilia Mirkin Signed-off-by: Rob Clark --- docs/relnotes/11.1.0.html | 1 + .../drivers/freedreno/freedreno_context.h | 4 +++ .../drivers/freedreno/freedreno_draw.c | 8 +++++ .../drivers/freedreno/freedreno_query.c | 11 +++++++ .../drivers/freedreno/freedreno_resource.c | 33 ++++++++++++++++--- .../drivers/freedreno/freedreno_resource.h | 2 ++ .../drivers/freedreno/freedreno_screen.c | 4 +-- 7 files changed, 57 insertions(+), 6 deletions(-) diff --git a/docs/relnotes/11.1.0.html b/docs/relnotes/11.1.0.html index 28fec7e89c4..00d517706b5 100644 --- a/docs/relnotes/11.1.0.html +++ b/docs/relnotes/11.1.0.html @@ -61,6 +61,7 @@ Note: some of the new features are only available with certain drivers.
  • GL_EXT_buffer_storage implemented for when ES 3.1 support is gained
  • GL_EXT_draw_elements_base_vertex on all drivers
  • GL_EXT_texture_compression_rgtc / latc on freedreno (a3xx)
  • +
  • GL_NV_conditional_render on freedreno
  • GL_OES_draw_elements_base_vertex on all drivers
  • EGL_KHR_create_context on softpipe, llvmpipe
  • EGL_KHR_gl_colorspace on softpipe, llvmpipe
  • diff --git a/src/gallium/drivers/freedreno/freedreno_context.h b/src/gallium/drivers/freedreno/freedreno_context.h index 61c4c6d6e24..571c8142bf7 100644 --- a/src/gallium/drivers/freedreno/freedreno_context.h +++ b/src/gallium/drivers/freedreno/freedreno_context.h @@ -359,6 +359,10 @@ struct fd_context { struct fd_streamout_stateobj streamout; struct pipe_clip_state ucp; + struct pipe_query *cond_query; + bool cond_cond; /* inverted rendering condition */ + uint cond_mode; + /* GMEM/tile handling fxns: */ void (*emit_tile_init)(struct fd_context *ctx); void (*emit_tile_prep)(struct fd_context *ctx, struct fd_tile *tile); diff --git a/src/gallium/drivers/freedreno/freedreno_draw.c b/src/gallium/drivers/freedreno/freedreno_draw.c index 7bf3343f43a..bf803cc77bc 100644 --- a/src/gallium/drivers/freedreno/freedreno_draw.c +++ b/src/gallium/drivers/freedreno/freedreno_draw.c @@ -88,6 +88,10 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) return; } + /* TODO: push down the region versions into the tiles */ + if (!fd_render_condition_check(pctx)) + return; + /* emulate unsupported primitives: */ if (!fd_supported_prim(ctx, info->mode)) { if (ctx->streamout.num_targets > 0) @@ -220,6 +224,10 @@ fd_clear(struct pipe_context *pctx, unsigned buffers, unsigned cleared_buffers; int i; + /* TODO: push down the region versions into the tiles */ + if (!fd_render_condition_check(pctx)) + return; + /* for bookkeeping about which buffers have been cleared (and thus * can fully or partially skip mem2gmem) we need to ignore buffers * that have already had a draw, in case apps do silly things like diff --git a/src/gallium/drivers/freedreno/freedreno_query.c b/src/gallium/drivers/freedreno/freedreno_query.c index db2683c9b6f..b87e8250719 100644 --- a/src/gallium/drivers/freedreno/freedreno_query.c +++ b/src/gallium/drivers/freedreno/freedreno_query.c @@ -81,6 +81,16 @@ fd_get_query_result(struct pipe_context *pctx, struct pipe_query *pq, return q->funcs->get_query_result(fd_context(pctx), q, wait, result); } +static void +fd_render_condition(struct pipe_context *pctx, struct pipe_query *pq, + boolean condition, uint mode) +{ + struct fd_context *ctx = fd_context(pctx); + ctx->cond_query = pq; + ctx->cond_cond = condition; + ctx->cond_mode = mode; +} + static int fd_get_driver_query_info(struct pipe_screen *pscreen, unsigned index, struct pipe_driver_query_info *info) @@ -118,4 +128,5 @@ fd_query_context_init(struct pipe_context *pctx) pctx->begin_query = fd_begin_query; pctx->end_query = fd_end_query; pctx->get_query_result = fd_get_query_result; + pctx->render_condition = fd_render_condition; } diff --git a/src/gallium/drivers/freedreno/freedreno_resource.c b/src/gallium/drivers/freedreno/freedreno_resource.c index 6e22e39f52e..5b1cee8d18d 100644 --- a/src/gallium/drivers/freedreno/freedreno_resource.c +++ b/src/gallium/drivers/freedreno/freedreno_resource.c @@ -671,7 +671,7 @@ fail: return NULL; } -static void fd_blitter_pipe_begin(struct fd_context *ctx); +static void fd_blitter_pipe_begin(struct fd_context *ctx, bool render_cond); static void fd_blitter_pipe_end(struct fd_context *ctx); /** @@ -693,7 +693,7 @@ fd_blitter_pipe_copy_region(struct fd_context *ctx, if (!util_blitter_is_copy_supported(ctx->blitter, dst, src)) return false; - fd_blitter_pipe_begin(ctx); + fd_blitter_pipe_begin(ctx, false); util_blitter_copy_texture(ctx->blitter, dst, dst_level, dstx, dsty, dstz, src, src_level, src_box); @@ -735,6 +735,25 @@ fd_resource_copy_region(struct pipe_context *pctx, src, src_level, src_box); } +bool +fd_render_condition_check(struct pipe_context *pctx) +{ + struct fd_context *ctx = fd_context(pctx); + + if (!ctx->cond_query) + return true; + + union pipe_query_result res = { 0 }; + bool wait = + ctx->cond_mode != PIPE_RENDER_COND_NO_WAIT && + ctx->cond_mode != PIPE_RENDER_COND_BY_REGION_NO_WAIT; + + if (pctx->get_query_result(pctx, ctx->cond_query, wait, &res)) + return (bool)res.u64 != ctx->cond_cond; + + return true; +} + /** * Optimal hardware path for blitting pixels. * Scaling, format conversion, up- and downsampling (resolve) are allowed. @@ -753,6 +772,9 @@ fd_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info) return; } + if (info.render_condition_enable && !fd_render_condition_check(pctx)) + return; + if (util_try_blit_via_copy_region(pctx, &info)) { return; /* done */ } @@ -769,13 +791,13 @@ fd_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info) return; } - fd_blitter_pipe_begin(ctx); + fd_blitter_pipe_begin(ctx, info.render_condition_enable); util_blitter_blit(ctx->blitter, &info); fd_blitter_pipe_end(ctx); } static void -fd_blitter_pipe_begin(struct fd_context *ctx) +fd_blitter_pipe_begin(struct fd_context *ctx, bool render_cond) { util_blitter_save_vertex_buffer_slot(ctx->blitter, ctx->vtx.vertexbuf.vb); util_blitter_save_vertex_elements(ctx->blitter, ctx->vtx.vtx); @@ -796,6 +818,9 @@ fd_blitter_pipe_begin(struct fd_context *ctx) (void **)ctx->fragtex.samplers); util_blitter_save_fragment_sampler_views(ctx->blitter, ctx->fragtex.num_textures, ctx->fragtex.textures); + if (!render_cond) + util_blitter_save_render_condition(ctx->blitter, + ctx->cond_query, ctx->cond_cond, ctx->cond_mode); fd_hw_query_set_stage(ctx, ctx->ring, FD_STAGE_BLIT); } diff --git a/src/gallium/drivers/freedreno/freedreno_resource.h b/src/gallium/drivers/freedreno/freedreno_resource.h index 7549becaa1f..10f5242da57 100644 --- a/src/gallium/drivers/freedreno/freedreno_resource.h +++ b/src/gallium/drivers/freedreno/freedreno_resource.h @@ -135,4 +135,6 @@ fd_resource_offset(struct fd_resource *rsc, unsigned level, unsigned layer) void fd_resource_screen_init(struct pipe_screen *pscreen); void fd_resource_context_init(struct pipe_context *pctx); +bool fd_render_condition_check(struct pipe_context *pctx); + #endif /* FREEDRENO_RESOURCE_H_ */ diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c index 56d1834ef9c..1e124592a80 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.c +++ b/src/gallium/drivers/freedreno/freedreno_screen.c @@ -160,7 +160,6 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_SHADER_STENCIL_EXPORT: case PIPE_CAP_TGSI_TEXCOORD: case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER: - case PIPE_CAP_CONDITIONAL_RENDER: case PIPE_CAP_TEXTURE_MULTISAMPLE: case PIPE_CAP_TEXTURE_BARRIER: case PIPE_CAP_TEXTURE_MIRROR_CLAMP: @@ -176,6 +175,8 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_INDEP_BLEND_FUNC: case PIPE_CAP_TEXTURE_BUFFER_OBJECTS: case PIPE_CAP_TEXTURE_HALF_FLOAT_LINEAR: + case PIPE_CAP_CONDITIONAL_RENDER: + case PIPE_CAP_CONDITIONAL_RENDER_INVERTED: return is_a3xx(screen) || is_a4xx(screen); case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT: @@ -227,7 +228,6 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION: case PIPE_CAP_DRAW_INDIRECT: case PIPE_CAP_TGSI_FS_FINE_DERIVATIVE: - case PIPE_CAP_CONDITIONAL_RENDER_INVERTED: case PIPE_CAP_SAMPLER_VIEW_TARGET: case PIPE_CAP_POLYGON_OFFSET_CLAMP: case PIPE_CAP_MULTISAMPLE_Z_RESOLVE: -- 2.30.2