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>
This commit is contained in:
Christian Gmeiner 2019-11-29 16:20:43 +01:00
parent a603413eb8
commit 62e0f6bf32
9 changed files with 63 additions and 7 deletions

View File

@ -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)

View File

@ -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);

View File

@ -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 {

View File

@ -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);

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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. */

View File

@ -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 */