From 8642456472fba21bbbc63c0182d5e3591a79ebb5 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 3 Mar 2021 10:51:55 -0800 Subject: [PATCH] freedreno: Deduplicate fixup_shader_state() All the ir3 gens had the same thing, time to move it out into a shared helper. The keeping the storage in fdN_context is to avoid namespace clashes between ir3 and ir2. Signed-off-by: Rob Clark Part-of: --- .../drivers/freedreno/a3xx/fd3_context.c | 2 ++ .../drivers/freedreno/a3xx/fd3_context.h | 5 +--- src/gallium/drivers/freedreno/a3xx/fd3_draw.c | 28 +------------------ .../drivers/freedreno/a4xx/fd4_context.c | 2 ++ .../drivers/freedreno/a4xx/fd4_context.h | 5 +--- src/gallium/drivers/freedreno/a4xx/fd4_draw.c | 28 +------------------ .../drivers/freedreno/a5xx/fd5_context.c | 1 + .../drivers/freedreno/a5xx/fd5_context.h | 5 +--- src/gallium/drivers/freedreno/a5xx/fd5_draw.c | 28 +------------------ .../drivers/freedreno/a6xx/fd6_context.c | 1 + .../drivers/freedreno/a6xx/fd6_context.h | 5 +--- src/gallium/drivers/freedreno/a6xx/fd6_draw.c | 28 +------------------ .../drivers/freedreno/freedreno_context.h | 11 ++++++++ .../drivers/freedreno/ir3/ir3_gallium.c | 28 +++++++++++++++++++ .../drivers/freedreno/ir3/ir3_gallium.h | 4 +++ 15 files changed, 57 insertions(+), 124 deletions(-) diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_context.c b/src/gallium/drivers/freedreno/a3xx/fd3_context.c index 56034716163..344c26604c6 100644 --- a/src/gallium/drivers/freedreno/a3xx/fd3_context.c +++ b/src/gallium/drivers/freedreno/a3xx/fd3_context.c @@ -72,6 +72,7 @@ static const uint8_t primtypes[] = { struct pipe_context * fd3_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) + in_dt { struct fd_screen *screen = fd_screen(pscreen); struct fd3_context *fd3_ctx = CALLOC_STRUCT(fd3_context); @@ -85,6 +86,7 @@ fd3_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) fd3_ctx->base.dev = fd_device_ref(screen->dev); fd3_ctx->base.screen = fd_screen(pscreen); + fd3_ctx->base.last.key = &fd3_ctx->last_key; pctx->destroy = fd3_context_destroy; pctx->create_blend_state = fd3_blend_state_create; diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_context.h b/src/gallium/drivers/freedreno/a3xx/fd3_context.h index 9000a64336e..c5c4f4e4194 100644 --- a/src/gallium/drivers/freedreno/a3xx/fd3_context.h +++ b/src/gallium/drivers/freedreno/a3xx/fd3_context.h @@ -47,10 +47,7 @@ struct fd3_context { struct u_upload_mgr *border_color_uploader; struct pipe_resource *border_color_buf; - /* some state changes require a different shader variant. Keep - * track of this so we know when we need to re-emit shader state - * due to variant change. See fixup_shader_state() - */ + /* storage for ctx->last.key: */ struct ir3_shader_key last_key; }; diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_draw.c b/src/gallium/drivers/freedreno/a3xx/fd3_draw.c index 4f6d03187ca..2b65198dba4 100644 --- a/src/gallium/drivers/freedreno/a3xx/fd3_draw.c +++ b/src/gallium/drivers/freedreno/a3xx/fd3_draw.c @@ -88,32 +88,6 @@ draw_impl(struct fd_context *ctx, struct fd_ringbuffer *ring, info, emit->draw, index_offset); } -/* fixup dirty shader state in case some "unrelated" (from the state- - * tracker's perspective) state change causes us to switch to a - * different variant. - */ -static void -fixup_shader_state(struct fd_context *ctx, struct ir3_shader_key *key) - assert_dt -{ - struct fd3_context *fd3_ctx = fd3_context(ctx); - struct ir3_shader_key *last_key = &fd3_ctx->last_key; - - if (!ir3_shader_key_equal(last_key, key)) { - if (ir3_shader_key_changes_fs(last_key, key)) { - ctx->dirty_shader[PIPE_SHADER_FRAGMENT] |= FD_DIRTY_SHADER_PROG; - ctx->dirty |= FD_DIRTY_PROG; - } - - if (ir3_shader_key_changes_vs(last_key, key)) { - ctx->dirty_shader[PIPE_SHADER_VERTEX] |= FD_DIRTY_SHADER_PROG; - ctx->dirty |= FD_DIRTY_PROG; - } - - fd3_ctx->last_key = *key; - } -} - static bool fd3_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info, const struct pipe_draw_indirect_info *indirect, @@ -137,7 +111,7 @@ fd3_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info, if (fd3_needs_manual_clipping(ir3_get_shader(ctx->prog.vs), ctx->rasterizer)) emit.key.ucp_enables = ctx->rasterizer->clip_plane_enable; - fixup_shader_state(ctx, &emit.key); + ir3_fixup_shader_state(&ctx->base, &emit.key); unsigned dirty = ctx->dirty; const struct ir3_shader_variant *vp = fd3_emit_get_vp(&emit); diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_context.c b/src/gallium/drivers/freedreno/a4xx/fd4_context.c index ed08f8dfaa9..9bcd63531f4 100644 --- a/src/gallium/drivers/freedreno/a4xx/fd4_context.c +++ b/src/gallium/drivers/freedreno/a4xx/fd4_context.c @@ -72,6 +72,7 @@ static const uint8_t primtypes[] = { struct pipe_context * fd4_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) + in_dt { struct fd_screen *screen = fd_screen(pscreen); struct fd4_context *fd4_ctx = CALLOC_STRUCT(fd4_context); @@ -85,6 +86,7 @@ fd4_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) fd4_ctx->base.dev = fd_device_ref(screen->dev); fd4_ctx->base.screen = fd_screen(pscreen); + fd4_ctx->base.last.key = &fd4_ctx->last_key; pctx->destroy = fd4_context_destroy; pctx->create_blend_state = fd4_blend_state_create; diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_context.h b/src/gallium/drivers/freedreno/a4xx/fd4_context.h index 917e2778b1f..95d0402af8c 100644 --- a/src/gallium/drivers/freedreno/a4xx/fd4_context.h +++ b/src/gallium/drivers/freedreno/a4xx/fd4_context.h @@ -51,10 +51,7 @@ struct fd4_context { /* bitmask of samplers which need astc srgb workaround: */ uint16_t vastc_srgb, fastc_srgb; - /* some state changes require a different shader variant. Keep - * track of this so we know when we need to re-emit shader state - * due to variant change. See fixup_shader_state() - */ + /* storage for ctx->last.key: */ struct ir3_shader_key last_key; }; diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_draw.c b/src/gallium/drivers/freedreno/a4xx/fd4_draw.c index 91d7beffd1b..9ffdecb973a 100644 --- a/src/gallium/drivers/freedreno/a4xx/fd4_draw.c +++ b/src/gallium/drivers/freedreno/a4xx/fd4_draw.c @@ -72,32 +72,6 @@ draw_impl(struct fd_context *ctx, struct fd_ringbuffer *ring, info, emit->indirect, emit->draw, index_offset); } -/* fixup dirty shader state in case some "unrelated" (from the state- - * tracker's perspective) state change causes us to switch to a - * different variant. - */ -static void -fixup_shader_state(struct fd_context *ctx, struct ir3_shader_key *key) - assert_dt -{ - struct fd4_context *fd4_ctx = fd4_context(ctx); - struct ir3_shader_key *last_key = &fd4_ctx->last_key; - - if (!ir3_shader_key_equal(last_key, key)) { - if (ir3_shader_key_changes_fs(last_key, key)) { - ctx->dirty_shader[PIPE_SHADER_FRAGMENT] |= FD_DIRTY_SHADER_PROG; - ctx->dirty |= FD_DIRTY_PROG; - } - - if (ir3_shader_key_changes_vs(last_key, key)) { - ctx->dirty_shader[PIPE_SHADER_VERTEX] |= FD_DIRTY_SHADER_PROG; - ctx->dirty |= FD_DIRTY_PROG; - } - - fd4_ctx->last_key = *key; - } -} - static bool fd4_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info, const struct pipe_draw_indirect_info *indirect, @@ -125,7 +99,7 @@ fd4_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info, .sprite_coord_mode = ctx->rasterizer->sprite_coord_mode, }; - fixup_shader_state(ctx, &emit.key); + ir3_fixup_shader_state(&ctx->base, &emit.key); enum fd_dirty_3d_state dirty = ctx->dirty; const struct ir3_shader_variant *vp = fd4_emit_get_vp(&emit); diff --git a/src/gallium/drivers/freedreno/a5xx/fd5_context.c b/src/gallium/drivers/freedreno/a5xx/fd5_context.c index 8ab28633d42..0bef048ca47 100644 --- a/src/gallium/drivers/freedreno/a5xx/fd5_context.c +++ b/src/gallium/drivers/freedreno/a5xx/fd5_context.c @@ -85,6 +85,7 @@ fd5_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) fd5_ctx->base.dev = fd_device_ref(screen->dev); fd5_ctx->base.screen = fd_screen(pscreen); + fd5_ctx->base.last.key = &fd5_ctx->last_key; pctx->destroy = fd5_context_destroy; pctx->create_blend_state = fd5_blend_state_create; diff --git a/src/gallium/drivers/freedreno/a5xx/fd5_context.h b/src/gallium/drivers/freedreno/a5xx/fd5_context.h index 4d96bc35873..3da77a6aa44 100644 --- a/src/gallium/drivers/freedreno/a5xx/fd5_context.h +++ b/src/gallium/drivers/freedreno/a5xx/fd5_context.h @@ -54,10 +54,7 @@ struct fd5_context { /* bitmask of samplers which need astc srgb workaround: */ uint16_t vastc_srgb, fastc_srgb; - /* some state changes require a different shader variant. Keep - * track of this so we know when we need to re-emit shader state - * due to variant change. See fixup_shader_state() - */ + /* storage for ctx->last.key: */ struct ir3_shader_key last_key; /* number of active samples-passed queries: */ diff --git a/src/gallium/drivers/freedreno/a5xx/fd5_draw.c b/src/gallium/drivers/freedreno/a5xx/fd5_draw.c index 97fd45bd6ba..5d6891646a2 100644 --- a/src/gallium/drivers/freedreno/a5xx/fd5_draw.c +++ b/src/gallium/drivers/freedreno/a5xx/fd5_draw.c @@ -67,32 +67,6 @@ draw_impl(struct fd_context *ctx, struct fd_ringbuffer *ring, info, emit->indirect, emit->draw, index_offset); } -/* fixup dirty shader state in case some "unrelated" (from the state- - * tracker's perspective) state change causes us to switch to a - * different variant. - */ -static void -fixup_shader_state(struct fd_context *ctx, struct ir3_shader_key *key) - assert_dt -{ - struct fd5_context *fd5_ctx = fd5_context(ctx); - struct ir3_shader_key *last_key = &fd5_ctx->last_key; - - if (!ir3_shader_key_equal(last_key, key)) { - if (ir3_shader_key_changes_fs(last_key, key)) { - ctx->dirty_shader[PIPE_SHADER_FRAGMENT] |= FD_DIRTY_SHADER_PROG; - ctx->dirty |= FD_DIRTY_PROG; - } - - if (ir3_shader_key_changes_vs(last_key, key)) { - ctx->dirty_shader[PIPE_SHADER_VERTEX] |= FD_DIRTY_SHADER_PROG; - ctx->dirty |= FD_DIRTY_PROG; - } - - fd5_ctx->last_key = *key; - } -} - static bool fd5_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info, const struct pipe_draw_indirect_info *indirect, @@ -120,7 +94,7 @@ fd5_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info, .sprite_coord_mode = ctx->rasterizer->sprite_coord_mode, }; - fixup_shader_state(ctx, &emit.key); + ir3_fixup_shader_state(&ctx->base, &emit.key); unsigned dirty = ctx->dirty; const struct ir3_shader_variant *vp = fd5_emit_get_vp(&emit); diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_context.c b/src/gallium/drivers/freedreno/a6xx/fd6_context.c index 99e2f3a9ab1..4dcaf03b156 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_context.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_context.c @@ -142,6 +142,7 @@ fd6_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) fd6_ctx->base.dev = fd_device_ref(screen->dev); fd6_ctx->base.screen = fd_screen(pscreen); + fd6_ctx->base.last.key = &fd6_ctx->last_key; pctx->destroy = fd6_context_destroy; pctx->create_blend_state = fd6_blend_state_create; diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_context.h b/src/gallium/drivers/freedreno/a6xx/fd6_context.h index d8552f31c55..1a1102f95a8 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_context.h +++ b/src/gallium/drivers/freedreno/a6xx/fd6_context.h @@ -70,10 +70,7 @@ struct fd6_context { struct u_upload_mgr *border_color_uploader; struct pipe_resource *border_color_buf; - /* some state changes require a different shader variant. Keep - * track of this so we know when we need to re-emit shader state - * due to variant change. See fixup_shader_state() - */ + /* storage for ctx->last.key: */ struct ir3_shader_key last_key; /* Is there current VS driver-param state set? */ diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_draw.c b/src/gallium/drivers/freedreno/a6xx/fd6_draw.c index 87f9c922bde..3292cc2040a 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_draw.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_draw.c @@ -128,32 +128,6 @@ draw_emit(struct fd_ringbuffer *ring, } } -/* fixup dirty shader state in case some "unrelated" (from the state- - * tracker's perspective) state change causes us to switch to a - * different variant. - */ -static void -fixup_shader_state(struct fd_context *ctx, struct ir3_shader_key *key) - assert_dt -{ - struct fd6_context *fd6_ctx = fd6_context(ctx); - struct ir3_shader_key *last_key = &fd6_ctx->last_key; - - if (!ir3_shader_key_equal(last_key, key)) { - if (ir3_shader_key_changes_fs(last_key, key)) { - ctx->dirty_shader[PIPE_SHADER_FRAGMENT] |= FD_DIRTY_SHADER_PROG; - ctx->dirty |= FD_DIRTY_PROG; - } - - if (ir3_shader_key_changes_vs(last_key, key)) { - ctx->dirty_shader[PIPE_SHADER_VERTEX] |= FD_DIRTY_SHADER_PROG; - ctx->dirty |= FD_DIRTY_PROG; - } - - fd6_ctx->last_key = *key; - } -} - static void fixup_draw_state(struct fd_context *ctx, struct fd6_emit *emit) assert_dt @@ -219,7 +193,7 @@ fd6_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info, if (!(emit.key.hs || emit.key.ds || emit.key.gs || indirect)) fd6_vsc_update_sizes(ctx->batch, info, draw); - fixup_shader_state(ctx, &emit.key.key); + ir3_fixup_shader_state(&ctx->base, &emit.key.key); if (!(ctx->dirty & FD_DIRTY_PROG)) { emit.prog = fd6_ctx->prog; diff --git a/src/gallium/drivers/freedreno/freedreno_context.h b/src/gallium/drivers/freedreno/freedreno_context.h index 418454049cd..717ecedf890 100644 --- a/src/gallium/drivers/freedreno/freedreno_context.h +++ b/src/gallium/drivers/freedreno/freedreno_context.h @@ -176,6 +176,8 @@ enum fd_dirty_shader_state { struct fd_hw_sample_provider; struct fd_hw_sample; +struct ir3_shader_key; + struct fd_context { struct pipe_context base; @@ -466,6 +468,15 @@ struct fd_context { uint32_t instance_start; uint32_t restart_index; uint32_t streamout_mask; + + /* some state changes require a different shader variant. Keep + * track of this so we know when we need to re-emit shader state + * due to variant change. See ir3_fixup_shader_state() + * + * (used for a3xx+, NULL otherwise) + */ + struct ir3_shader_key *key; + } last dt; }; diff --git a/src/gallium/drivers/freedreno/ir3/ir3_gallium.c b/src/gallium/drivers/freedreno/ir3/ir3_gallium.c index a01c1cfee7e..23e898cfb93 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_gallium.c +++ b/src/gallium/drivers/freedreno/ir3/ir3_gallium.c @@ -443,6 +443,34 @@ ir3_get_shader_info(struct ir3_shader_state *hwcso) return &hwcso->shader->nir->info; } +/* fixup dirty shader state in case some "unrelated" (from the state- + * tracker's perspective) state change causes us to switch to a + * different variant. + */ +void +ir3_fixup_shader_state(struct pipe_context *pctx, struct ir3_shader_key *key) +{ + struct fd_context *ctx = fd_context(pctx); + + if (!ir3_shader_key_equal(ctx->last.key, key)) { + if (ir3_shader_key_changes_fs(ctx->last.key, key)) { + ctx->dirty_shader[PIPE_SHADER_FRAGMENT] |= FD_DIRTY_SHADER_PROG; + ctx->dirty |= FD_DIRTY_PROG; + } + + if (ir3_shader_key_changes_vs(ctx->last.key, key)) { + ctx->dirty_shader[PIPE_SHADER_VERTEX] |= FD_DIRTY_SHADER_PROG; + ctx->dirty |= FD_DIRTY_PROG; + } + + /* NOTE: currently only a6xx has gs/tess, but needs no + * gs/tess specific lowering. + */ + + *ctx->last.key = *key; + } +} + static void ir3_screen_finalize_nir(struct pipe_screen *pscreen, void *nir, bool optimize) { diff --git a/src/gallium/drivers/freedreno/ir3/ir3_gallium.h b/src/gallium/drivers/freedreno/ir3/ir3_gallium.h index 8523895e684..663e8d48676 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_gallium.h +++ b/src/gallium/drivers/freedreno/ir3/ir3_gallium.h @@ -31,6 +31,8 @@ #include "pipe/p_screen.h" #include "ir3/ir3_shader.h" +#include "freedreno_util.h" + /** * The ir3 hwcso type, use ir3_get_shader() to dereference the * underlying ir3_shader @@ -49,6 +51,8 @@ void ir3_shader_state_delete(struct pipe_context *pctx, void *hwcso); struct ir3_shader * ir3_get_shader(struct ir3_shader_state *hwcso); struct shader_info * ir3_get_shader_info(struct ir3_shader_state *hwcso); +void ir3_fixup_shader_state(struct pipe_context *pctx, struct ir3_shader_key *key) assert_dt; + void ir3_prog_init(struct pipe_context *pctx); void ir3_screen_init(struct pipe_screen *pscreen); void ir3_screen_fini(struct pipe_screen *pscreen);