diff --git a/docs/features.txt b/docs/features.txt index 49139661f8e6b..32495bd0284dc 100644 --- a/docs/features.txt +++ b/docs/features.txt @@ -39,7 +39,7 @@ Feature Status GL 3.0, GLSL 1.30 --- all DONE: freedreno, i965, nv50, nvc0, r600, radeonsi, llvmpipe, softpipe, virgl, zink, d3d12, panfrost, asahi glBindFragDataLocation, glGetFragDataLocation DONE - GL_NV_conditional_render (Conditional rendering) DONE (v3d) + GL_NV_conditional_render (Conditional rendering) DONE (v3d, etnaviv/HALTI0) GL_ARB_map_buffer_range (Map buffer subranges) DONE (v3d, vc4, lima) GL_ARB_color_buffer_float (Clamping controls) DONE (v3d, vc4, lima) GL_ARB_texture_float (Float textures, renderbuffers) DONE (v3d) diff --git a/src/gallium/drivers/etnaviv/etnaviv_blt.c b/src/gallium/drivers/etnaviv/etnaviv_blt.c index e00aeb2258438..b9a5fa366040e 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_blt.c +++ b/src/gallium/drivers/etnaviv/etnaviv_blt.c @@ -360,6 +360,9 @@ etna_clear_blt(struct pipe_context *pctx, unsigned buffers, const struct pipe_sc { struct etna_context *ctx = etna_context(pctx); + if (!etna_render_condition_check(pctx)) + return; + etna_set_state(ctx->stream, VIVS_GL_FLUSH_CACHE, 0x00000c23); etna_set_state(ctx->stream, VIVS_TS_FLUSH_CACHE, VIVS_TS_FLUSH_CACHE_FLUSH); diff --git a/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c b/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c index 4233a1221b0f7..b7b8ebab2c3bd 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c +++ b/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c @@ -47,7 +47,7 @@ /* Save current state for blitter operation */ void -etna_blit_save_state(struct etna_context *ctx) +etna_blit_save_state(struct etna_context *ctx, bool render_cond) { util_blitter_save_fragment_constant_buffer_slot(ctx->blitter, ctx->constant_buffer[PIPE_SHADER_FRAGMENT].cb); @@ -68,6 +68,10 @@ etna_blit_save_state(struct etna_context *ctx) util_blitter_save_fragment_sampler_views(ctx->blitter, ctx->num_fragment_sampler_views, ctx->sampler_view); + if (!render_cond) + util_blitter_save_render_condition(ctx->blitter, + ctx->cond_query, ctx->cond_cond, ctx->cond_mode); + if (DBG_ENABLED(ETNA_DBG_DEQP)) util_blitter_save_so_targets(ctx->blitter, 0, NULL); } @@ -100,6 +104,8 @@ etna_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info) struct etna_context *ctx = etna_context(pctx); struct pipe_blit_info info = *blit_info; + if (info.render_condition_enable && !etna_render_condition_check(pctx)) + return; if (ctx->blit(pctx, &info)) goto success; @@ -119,7 +125,7 @@ etna_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info) return; } - etna_blit_save_state(ctx); + etna_blit_save_state(ctx, info.render_condition_enable); util_blitter_blit(ctx->blitter, &info); success: @@ -137,7 +143,7 @@ etna_clear_render_target(struct pipe_context *pctx, struct pipe_surface *dst, /* XXX could fall back to RS when target area is full screen / resolveable * and no TS. */ - etna_blit_save_state(ctx); + etna_blit_save_state(ctx, false); util_blitter_clear_render_target(ctx->blitter, dst, color, dstx, dsty, width, height); } @@ -151,7 +157,7 @@ etna_clear_depth_stencil(struct pipe_context *pctx, struct pipe_surface *dst, /* XXX could fall back to RS when target area is full screen / resolveable * and no TS. */ - etna_blit_save_state(ctx); + etna_blit_save_state(ctx, false); util_blitter_clear_depth_stencil(ctx->blitter, dst, clear_flags, depth, stencil, dstx, dsty, width, height); } @@ -166,7 +172,7 @@ etna_resource_copy_region(struct pipe_context *pctx, struct pipe_resource *dst, if (src->target != PIPE_BUFFER && dst->target != PIPE_BUFFER && util_blitter_is_copy_supported(ctx->blitter, dst, src)) { - etna_blit_save_state(ctx); + etna_blit_save_state(ctx, false); util_blitter_copy_texture(ctx->blitter, dst, dst_level, dstx, dsty, dstz, src, src_level, src_box); } else { diff --git a/src/gallium/drivers/etnaviv/etnaviv_clear_blit.h b/src/gallium/drivers/etnaviv/etnaviv_clear_blit.h index 2249a5b12e07d..2348f207abc91 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_clear_blit.h +++ b/src/gallium/drivers/etnaviv/etnaviv_clear_blit.h @@ -48,7 +48,7 @@ etna_copy_resource_box(struct pipe_context *pctx, struct pipe_resource *dst, struct pipe_box *box); void -etna_blit_save_state(struct etna_context *ctx); +etna_blit_save_state(struct etna_context *ctx, bool render_cond); uint64_t etna_clear_blit_pack_rgba(enum pipe_format format, const union pipe_color_union *color); diff --git a/src/gallium/drivers/etnaviv/etnaviv_context.c b/src/gallium/drivers/etnaviv/etnaviv_context.c index 9797bf3a0a83e..3c2d9b5f7ee03 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_context.c +++ b/src/gallium/drivers/etnaviv/etnaviv_context.c @@ -248,6 +248,9 @@ etna_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info, u_decomposed_prim(info->mode) == MESA_PRIM_TRIANGLES)) return; + if (!etna_render_condition_check(pctx)) + return; + int prims = u_decomposed_prims_for_vertices(info->mode, draws[0].count); if (unlikely(prims <= 0)) { DBG("Invalid draw primitive mode=%i or no primitives to be drawn", info->mode); @@ -664,3 +667,22 @@ fail: return NULL; } + +bool +etna_render_condition_check(struct pipe_context *pctx) +{ + struct etna_context *ctx = etna_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; +} diff --git a/src/gallium/drivers/etnaviv/etnaviv_context.h b/src/gallium/drivers/etnaviv/etnaviv_context.h index 2b61369d743fc..50af6b95501e3 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_context.h +++ b/src/gallium/drivers/etnaviv/etnaviv_context.h @@ -199,6 +199,11 @@ struct etna_context { struct set *flush_resources; bool is_noop; + + /* conditional rendering */ + struct pipe_query *cond_query; + bool cond_cond; /* inverted rendering condition */ + uint cond_mode; }; static inline struct etna_context * @@ -224,4 +229,7 @@ void etna_flush(struct pipe_context *pctx, struct pipe_fence_handle **fence, enum pipe_flush_flags flags, bool internal); +bool +etna_render_condition_check(struct pipe_context *pctx); + #endif diff --git a/src/gallium/drivers/etnaviv/etnaviv_query.c b/src/gallium/drivers/etnaviv/etnaviv_query.c index 01ec3bebc8e5d..6d869db89e90d 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_query.c +++ b/src/gallium/drivers/etnaviv/etnaviv_query.c @@ -119,6 +119,17 @@ etna_get_driver_query_group_info(struct pipe_screen *pscreen, unsigned index, return etna_pm_get_driver_query_group_info(pscreen, index, info); } +static void +etna_render_condition(struct pipe_context *pctx, struct pipe_query *pq, + bool condition, enum pipe_render_cond_flag mode) +{ + struct etna_context *ctx = etna_context(pctx); + + ctx->cond_query = pq; + ctx->cond_cond = condition; + ctx->cond_mode = mode; +} + static void etna_set_active_query_state(struct pipe_context *pctx, bool enable) { @@ -149,4 +160,5 @@ etna_query_context_init(struct pipe_context *pctx) pctx->end_query = etna_end_query; pctx->get_query_result = etna_get_query_result; pctx->set_active_query_state = etna_set_active_query_state; + pctx->render_condition = etna_render_condition; } diff --git a/src/gallium/drivers/etnaviv/etnaviv_rs.c b/src/gallium/drivers/etnaviv/etnaviv_rs.c index 0dd58a9ed1479..13fb43cf54eb4 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_rs.c +++ b/src/gallium/drivers/etnaviv/etnaviv_rs.c @@ -431,6 +431,9 @@ etna_clear_rs(struct pipe_context *pctx, unsigned buffers, const struct pipe_sci { struct etna_context *ctx = etna_context(pctx); + if (!etna_render_condition_check(pctx)) + return; + /* Flush color and depth cache before clearing anything. * This is especially important when coming from another surface, as * otherwise it may clear part of the old surface instead. */ diff --git a/src/gallium/drivers/etnaviv/etnaviv_screen.c b/src/gallium/drivers/etnaviv/etnaviv_screen.c index 8751db71dcba2..c786f6782a119 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_screen.c +++ b/src/gallium/drivers/etnaviv/etnaviv_screen.c @@ -241,6 +241,8 @@ etna_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) /* Queries. */ case PIPE_CAP_OCCLUSION_QUERY: + case PIPE_CAP_CONDITIONAL_RENDER: + case PIPE_CAP_CONDITIONAL_RENDER_INVERTED: return VIV_FEATURE(screen, chipMinorFeatures1, HALTI0); /* Preferences */