summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Gmeiner <cgmeiner@igalia.com>2019-11-29 16:20:43 +0100
committerChristian Gmeiner <cgmeiner@igalia.com>2023-06-09 20:35:24 +0200
commit62e0f6bf328e37f3c4704ca35427c3dde0744977 (patch)
treef1dc8c296d1533d4981930c1871a26727cd72a38
parenta603413eb8a8ad4e3e5dacd7360100c4225cb9b3 (diff)
etnaviv: Add support for conditional rendering
The hardware doesn't support native conditional rendering, so it is implemented by software. Code borrowed from Freedreno and Panfrost. Signed-off-by: Christian Gmeiner <cgmeiner@igalia.com> Reviewed-by: Lucas Stach <l.stach@pengutronix.de> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/23392>
-rw-r--r--docs/features.txt2
-rw-r--r--src/gallium/drivers/etnaviv/etnaviv_blt.c3
-rw-r--r--src/gallium/drivers/etnaviv/etnaviv_clear_blit.c16
-rw-r--r--src/gallium/drivers/etnaviv/etnaviv_clear_blit.h2
-rw-r--r--src/gallium/drivers/etnaviv/etnaviv_context.c22
-rw-r--r--src/gallium/drivers/etnaviv/etnaviv_context.h8
-rw-r--r--src/gallium/drivers/etnaviv/etnaviv_query.c12
-rw-r--r--src/gallium/drivers/etnaviv/etnaviv_rs.c3
-rw-r--r--src/gallium/drivers/etnaviv/etnaviv_screen.c2
9 files changed, 63 insertions, 7 deletions
diff --git a/docs/features.txt b/docs/features.txt
index 49139661f8e..32495bd0284 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 e00aeb22584..b9a5fa36604 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 4233a1221b0..b7b8ebab2c3 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 2249a5b12e0..2348f207abc 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 9797bf3a0a8..3c2d9b5f7ee 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 2b61369d743..50af6b95501 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 01ec3bebc8e..6d869db89e9 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_query.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_query.c
@@ -120,6 +120,17 @@ etna_get_driver_query_group_info(struct pipe_screen *pscreen, unsigned index,
}
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)
{
struct etna_context *ctx = etna_context(pctx);
@@ -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 0dd58a9ed14..13fb43cf54e 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 8751db71dcb..c786f6782a1 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 */