From: Rob Clark Date: Sat, 15 Apr 2017 14:04:55 +0000 (-0400) Subject: freedreno: refactor dirty state handling X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=4299849ec7a873edf46a3a366749282fdec020fe;p=mesa.git freedreno: refactor dirty state handling In particular, move per-shader-stage info out to a seperate array of enum's indexed by shader stage. This will make it easier to add more shader stages as well as new per-stage state (like SSBOs). Signed-off-by: Rob Clark --- diff --git a/src/gallium/drivers/freedreno/a2xx/fd2_draw.c b/src/gallium/drivers/freedreno/a2xx/fd2_draw.c index feec59fa5de..f360ec2f6e2 100644 --- a/src/gallium/drivers/freedreno/a2xx/fd2_draw.c +++ b/src/gallium/drivers/freedreno/a2xx/fd2_draw.c @@ -284,9 +284,12 @@ fd2_clear(struct fd_context *ctx, unsigned buffers, FD_DIRTY_RASTERIZER | FD_DIRTY_SAMPLE_MASK | FD_DIRTY_PROG | - FD_DIRTY_CONSTBUF | + FD_DIRTY_CONST | FD_DIRTY_BLEND | FD_DIRTY_FRAMEBUFFER; + + ctx->dirty_shader[PIPE_SHADER_VERTEX] |= FD_DIRTY_SHADER_PROG; + ctx->dirty_shader[PIPE_SHADER_FRAGMENT] |= FD_DIRTY_SHADER_PROG | FD_DIRTY_SHADER_CONST; } void diff --git a/src/gallium/drivers/freedreno/a2xx/fd2_emit.c b/src/gallium/drivers/freedreno/a2xx/fd2_emit.c index fe2750ba10b..d745e44b0ad 100644 --- a/src/gallium/drivers/freedreno/a2xx/fd2_emit.c +++ b/src/gallium/drivers/freedreno/a2xx/fd2_emit.c @@ -182,7 +182,7 @@ fd2_emit_vertex_bufs(struct fd_ringbuffer *ring, uint32_t val, } void -fd2_emit_state(struct fd_context *ctx, const uint32_t dirty) +fd2_emit_state(struct fd_context *ctx, const enum fd_dirty_3d_state dirty) { struct fd2_blend_stateobj *blend = fd2_blend_stateobj(ctx->blend); struct fd2_zsa_stateobj *zsa = fd2_zsa_stateobj(ctx->zsa); @@ -284,7 +284,7 @@ fd2_emit_state(struct fd_context *ctx, const uint32_t dirty) fd2_program_emit(ring, &ctx->prog); } - if (dirty & (FD_DIRTY_PROG | FD_DIRTY_CONSTBUF)) { + if (dirty & (FD_DIRTY_PROG | FD_DIRTY_CONST)) { emit_constants(ring, VS_CONST_BASE * 4, &ctx->constbuf[PIPE_SHADER_VERTEX], (dirty & FD_DIRTY_PROG) ? ctx->prog.vp : NULL); @@ -309,7 +309,7 @@ fd2_emit_state(struct fd_context *ctx, const uint32_t dirty) OUT_RING(ring, blend->rb_colormask); } - if (dirty & (FD_DIRTY_VERTTEX | FD_DIRTY_FRAGTEX | FD_DIRTY_PROG)) + if (dirty & (FD_DIRTY_TEX | FD_DIRTY_PROG)) emit_textures(ring, ctx); } diff --git a/src/gallium/drivers/freedreno/a2xx/fd2_emit.h b/src/gallium/drivers/freedreno/a2xx/fd2_emit.h index 6a26c85c142..d908b113514 100644 --- a/src/gallium/drivers/freedreno/a2xx/fd2_emit.h +++ b/src/gallium/drivers/freedreno/a2xx/fd2_emit.h @@ -42,7 +42,7 @@ struct fd2_vertex_buf { void fd2_emit_vertex_bufs(struct fd_ringbuffer *ring, uint32_t val, struct fd2_vertex_buf *vbufs, uint32_t n); -void fd2_emit_state(struct fd_context *ctx, uint32_t dirty); +void fd2_emit_state(struct fd_context *ctx, enum fd_dirty_3d_state dirty); void fd2_emit_restore(struct fd_context *ctx, struct fd_ringbuffer *ring); void fd2_emit_init(struct pipe_context *pctx); diff --git a/src/gallium/drivers/freedreno/a2xx/fd2_program.c b/src/gallium/drivers/freedreno/a2xx/fd2_program.c index 8dcbb979383..9a774572514 100644 --- a/src/gallium/drivers/freedreno/a2xx/fd2_program.c +++ b/src/gallium/drivers/freedreno/a2xx/fd2_program.c @@ -241,16 +241,18 @@ void fd2_program_validate(struct fd_context *ctx) { struct fd_program_stateobj *prog = &ctx->prog; + bool dirty_fp = !!(ctx->dirty_shader[PIPE_SHADER_FRAGMENT] & FD_DIRTY_SHADER_PROG); + bool dirty_vp = !!(ctx->dirty_shader[PIPE_SHADER_VERTEX] & FD_DIRTY_SHADER_PROG); /* if vertex or frag shader is dirty, we may need to recompile. Compile * frag shader first, as that assigns the register slots for exports * from the vertex shader. And therefore if frag shader has changed we * need to recompile both vert and frag shader. */ - if (ctx->dirty & FD_SHADER_DIRTY_FP) + if (dirty_fp) compile(prog, prog->fp); - if (ctx->dirty & (FD_SHADER_DIRTY_FP | FD_SHADER_DIRTY_VP)) + if (dirty_fp || dirty_vp) compile(prog, prog->vp); /* if necessary, fix up vertex fetch instructions: */ diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_draw.c b/src/gallium/drivers/freedreno/a3xx/fd3_draw.c index c36e5071660..b3e42f37a2a 100644 --- a/src/gallium/drivers/freedreno/a3xx/fd3_draw.c +++ b/src/gallium/drivers/freedreno/a3xx/fd3_draw.c @@ -101,11 +101,13 @@ fixup_shader_state(struct fd_context *ctx, struct ir3_shader_key *key) if (!ir3_shader_key_equal(last_key, key)) { if (ir3_shader_key_changes_fs(last_key, key)) { - ctx->dirty |= FD_SHADER_DIRTY_FP; + 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 |= FD_SHADER_DIRTY_VP; + ctx->dirty_shader[PIPE_SHADER_VERTEX] |= FD_DIRTY_SHADER_PROG; + ctx->dirty |= FD_DIRTY_PROG; } fd3_ctx->last_key = *key; diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_emit.c b/src/gallium/drivers/freedreno/a3xx/fd3_emit.c index 04e3300efde..ca97a08d544 100644 --- a/src/gallium/drivers/freedreno/a3xx/fd3_emit.c +++ b/src/gallium/drivers/freedreno/a3xx/fd3_emit.c @@ -490,7 +490,7 @@ fd3_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring, { const struct ir3_shader_variant *vp = fd3_emit_get_vp(emit); const struct ir3_shader_variant *fp = fd3_emit_get_fp(emit); - const uint32_t dirty = emit->dirty; + const enum fd_dirty_3d_state dirty = emit->dirty; emit_marker(ring, 5); @@ -783,13 +783,13 @@ fd3_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring, A3XX_RB_BLEND_ALPHA_FLOAT(bcolor->color[3])); } - if (dirty & (FD_DIRTY_VERTTEX | FD_DIRTY_FRAGTEX)) + if (dirty & FD_DIRTY_TEX) fd_wfi(ctx->batch, ring); - if (dirty & FD_DIRTY_VERTTEX) + if (ctx->dirty_shader[PIPE_SHADER_VERTEX] & FD_DIRTY_SHADER_TEX) emit_textures(ctx, ring, SB_VERT_TEX, &ctx->tex[PIPE_SHADER_VERTEX]); - if (dirty & FD_DIRTY_FRAGTEX) + if (ctx->dirty_shader[PIPE_SHADER_FRAGMENT] & FD_DIRTY_SHADER_TEX) emit_textures(ctx, ring, SB_FRAG_TEX, &ctx->tex[PIPE_SHADER_FRAGMENT]); } diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_emit.h b/src/gallium/drivers/freedreno/a3xx/fd3_emit.h index 6e7dee25daa..5e574da199d 100644 --- a/src/gallium/drivers/freedreno/a3xx/fd3_emit.h +++ b/src/gallium/drivers/freedreno/a3xx/fd3_emit.h @@ -48,7 +48,7 @@ struct fd3_emit { const struct fd_program_stateobj *prog; const struct pipe_draw_info *info; struct ir3_shader_key key; - uint32_t dirty; + enum fd_dirty_3d_state dirty; uint32_t sprite_coord_enable; bool sprite_coord_mode; diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_draw.c b/src/gallium/drivers/freedreno/a4xx/fd4_draw.c index 869c69b25b3..a76f9e8c434 100644 --- a/src/gallium/drivers/freedreno/a4xx/fd4_draw.c +++ b/src/gallium/drivers/freedreno/a4xx/fd4_draw.c @@ -85,11 +85,13 @@ fixup_shader_state(struct fd_context *ctx, struct ir3_shader_key *key) if (!ir3_shader_key_equal(last_key, key)) { if (ir3_shader_key_changes_fs(last_key, key)) { - ctx->dirty |= FD_SHADER_DIRTY_FP; + 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 |= FD_SHADER_DIRTY_VP; + ctx->dirty_shader[PIPE_SHADER_VERTEX] |= FD_DIRTY_SHADER_PROG; + ctx->dirty |= FD_DIRTY_PROG; } fd4_ctx->last_key = *key; @@ -131,7 +133,7 @@ fd4_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info) fixup_shader_state(ctx, &emit.key); - unsigned dirty = ctx->dirty; + enum fd_dirty_3d_state dirty = ctx->dirty; /* do regular pass first, since that is more likely to fail compiling: */ diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_emit.c b/src/gallium/drivers/freedreno/a4xx/fd4_emit.c index 4c79a67ba59..f0a1fdea0df 100644 --- a/src/gallium/drivers/freedreno/a4xx/fd4_emit.c +++ b/src/gallium/drivers/freedreno/a4xx/fd4_emit.c @@ -499,7 +499,7 @@ fd4_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring, { const struct ir3_shader_variant *vp = fd4_emit_get_vp(emit); const struct ir3_shader_variant *fp = fd4_emit_get_fp(emit); - const uint32_t dirty = emit->dirty; + const enum fd_dirty_3d_state dirty = emit->dirty; emit_marker(ring, 5); @@ -740,10 +740,10 @@ fd4_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring, OUT_RING(ring, A4XX_RB_BLEND_ALPHA_F32(bcolor->color[3])); } - if (dirty & FD_DIRTY_VERTTEX) + if (ctx->dirty_shader[PIPE_SHADER_VERTEX] & FD_DIRTY_SHADER_TEX) emit_textures(ctx, ring, SB4_VS_TEX, &ctx->tex[PIPE_SHADER_VERTEX], vp); - if (dirty & FD_DIRTY_FRAGTEX) + if (ctx->dirty_shader[PIPE_SHADER_FRAGMENT] & FD_DIRTY_SHADER_TEX) emit_textures(ctx, ring, SB4_FS_TEX, &ctx->tex[PIPE_SHADER_FRAGMENT], fp); } diff --git a/src/gallium/drivers/freedreno/a4xx/fd4_emit.h b/src/gallium/drivers/freedreno/a4xx/fd4_emit.h index 00f92faaf35..a724caedc29 100644 --- a/src/gallium/drivers/freedreno/a4xx/fd4_emit.h +++ b/src/gallium/drivers/freedreno/a4xx/fd4_emit.h @@ -48,7 +48,7 @@ struct fd4_emit { const struct fd_program_stateobj *prog; const struct pipe_draw_info *info; struct ir3_shader_key key; - uint32_t dirty; + enum fd_dirty_3d_state dirty; uint32_t sprite_coord_enable; /* bitmask */ bool sprite_coord_mode; diff --git a/src/gallium/drivers/freedreno/a5xx/fd5_draw.c b/src/gallium/drivers/freedreno/a5xx/fd5_draw.c index 147f7070039..4ef0c7303d2 100644 --- a/src/gallium/drivers/freedreno/a5xx/fd5_draw.c +++ b/src/gallium/drivers/freedreno/a5xx/fd5_draw.c @@ -78,11 +78,13 @@ fixup_shader_state(struct fd_context *ctx, struct ir3_shader_key *key) if (!ir3_shader_key_equal(last_key, key)) { if (ir3_shader_key_changes_fs(last_key, key)) { - ctx->dirty |= FD_SHADER_DIRTY_FP; + 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 |= FD_SHADER_DIRTY_VP; + ctx->dirty_shader[PIPE_SHADER_VERTEX] |= FD_DIRTY_SHADER_PROG; + ctx->dirty |= FD_DIRTY_PROG; } fd5_ctx->last_key = *key; diff --git a/src/gallium/drivers/freedreno/a5xx/fd5_emit.c b/src/gallium/drivers/freedreno/a5xx/fd5_emit.c index 1e5b6dbc292..f2c9a6b85d5 100644 --- a/src/gallium/drivers/freedreno/a5xx/fd5_emit.c +++ b/src/gallium/drivers/freedreno/a5xx/fd5_emit.c @@ -398,7 +398,7 @@ fd5_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring, { const struct ir3_shader_variant *vp = fd5_emit_get_vp(emit); const struct ir3_shader_variant *fp = fd5_emit_get_fp(emit); - const uint32_t dirty = emit->dirty; + const enum fd_dirty_3d_state dirty = emit->dirty; bool needs_border = false; emit_marker5(ring, 5); @@ -647,14 +647,14 @@ fd5_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring, OUT_RING(ring, A5XX_RB_BLEND_ALPHA_F32(bcolor->color[3])); } - if (dirty & FD_DIRTY_VERTTEX) { + if (ctx->dirty_shader[PIPE_SHADER_VERTEX] & FD_DIRTY_SHADER_TEX) { needs_border |= emit_textures(ctx, ring, SB4_VS_TEX, &ctx->tex[PIPE_SHADER_VERTEX]); OUT_PKT4(ring, REG_A5XX_TPL1_VS_TEX_COUNT, 1); OUT_RING(ring, ctx->tex[PIPE_SHADER_VERTEX].num_textures); } - if (dirty & FD_DIRTY_FRAGTEX) { + if (ctx->dirty_shader[PIPE_SHADER_FRAGMENT] & FD_DIRTY_SHADER_TEX) { needs_border |= emit_textures(ctx, ring, SB4_FS_TEX, &ctx->tex[PIPE_SHADER_FRAGMENT]); OUT_PKT4(ring, REG_A5XX_TPL1_FS_TEX_COUNT, 1); diff --git a/src/gallium/drivers/freedreno/a5xx/fd5_emit.h b/src/gallium/drivers/freedreno/a5xx/fd5_emit.h index 0525b3e7326..b18c0a8cb66 100644 --- a/src/gallium/drivers/freedreno/a5xx/fd5_emit.h +++ b/src/gallium/drivers/freedreno/a5xx/fd5_emit.h @@ -44,7 +44,7 @@ struct fd5_emit { const struct fd_program_stateobj *prog; const struct pipe_draw_info *info; struct ir3_shader_key key; - uint32_t dirty; + enum fd_dirty_3d_state dirty; uint32_t sprite_coord_enable; /* bitmask */ bool sprite_coord_mode; diff --git a/src/gallium/drivers/freedreno/freedreno_context.h b/src/gallium/drivers/freedreno/freedreno_context.h index 7f47eaf2a71..733c64b1807 100644 --- a/src/gallium/drivers/freedreno/freedreno_context.h +++ b/src/gallium/drivers/freedreno/freedreno_context.h @@ -107,6 +107,42 @@ struct fd_vertex_state { struct fd_vertexbuf_stateobj vertexbuf; }; +/* global 3d pipeline dirty state: */ +enum fd_dirty_3d_state { + FD_DIRTY_BLEND = BIT(0), + FD_DIRTY_RASTERIZER = BIT(1), + FD_DIRTY_ZSA = BIT(2), + FD_DIRTY_BLEND_COLOR = BIT(3), + FD_DIRTY_STENCIL_REF = BIT(4), + FD_DIRTY_SAMPLE_MASK = BIT(5), + FD_DIRTY_FRAMEBUFFER = BIT(6), + FD_DIRTY_STIPPLE = BIT(7), + FD_DIRTY_VIEWPORT = BIT(8), + FD_DIRTY_VTXSTATE = BIT(9), + FD_DIRTY_VTXBUF = BIT(10), + FD_DIRTY_INDEXBUF = BIT(11), + FD_DIRTY_SCISSOR = BIT(12), + FD_DIRTY_STREAMOUT = BIT(13), + FD_DIRTY_UCP = BIT(14), + FD_DIRTY_BLEND_DUAL = BIT(15), + + /* These are a bit redundent with fd_dirty_shader_state, and possibly + * should be removed. (But OTOH kinda convenient in some places) + */ + FD_DIRTY_PROG = BIT(16), + FD_DIRTY_CONST = BIT(17), + FD_DIRTY_TEX = BIT(18), + + /* only used by a2xx.. possibly can be removed.. */ + FD_DIRTY_TEXSTATE = BIT(19), +}; + +/* per shader-stage dirty state: */ +enum fd_dirty_shader_state { + FD_DIRTY_SHADER_PROG = BIT(0), + FD_DIRTY_SHADER_CONST = BIT(1), + FD_DIRTY_SHADER_TEX = BIT(2), +}; struct fd_context { struct pipe_context base; @@ -196,34 +232,10 @@ struct fd_context { struct fd_tile tile[512]; /* which state objects need to be re-emit'd: */ - enum { - FD_DIRTY_BLEND = (1 << 0), - FD_DIRTY_RASTERIZER = (1 << 1), - FD_DIRTY_ZSA = (1 << 2), - FD_DIRTY_FRAGTEX = (1 << 3), - FD_DIRTY_VERTTEX = (1 << 4), - FD_DIRTY_TEXSTATE = (1 << 5), - - FD_SHADER_DIRTY_VP = (1 << 6), - FD_SHADER_DIRTY_FP = (1 << 7), - /* skip geom/tcs/tes/compute */ - FD_DIRTY_PROG = FD_SHADER_DIRTY_FP | FD_SHADER_DIRTY_VP, - - FD_DIRTY_BLEND_COLOR = (1 << 12), - FD_DIRTY_STENCIL_REF = (1 << 13), - FD_DIRTY_SAMPLE_MASK = (1 << 14), - FD_DIRTY_FRAMEBUFFER = (1 << 15), - FD_DIRTY_STIPPLE = (1 << 16), - FD_DIRTY_VIEWPORT = (1 << 17), - FD_DIRTY_CONSTBUF = (1 << 18), - FD_DIRTY_VTXSTATE = (1 << 19), - FD_DIRTY_VTXBUF = (1 << 20), - FD_DIRTY_INDEXBUF = (1 << 21), - FD_DIRTY_SCISSOR = (1 << 22), - FD_DIRTY_STREAMOUT = (1 << 23), - FD_DIRTY_UCP = (1 << 24), - FD_DIRTY_BLEND_DUAL = (1 << 25), - } dirty; + enum fd_dirty_3d_state dirty; + + /* per shader-stage dirty status: */ + enum fd_dirty_shader_state dirty_shader[PIPE_SHADER_TYPES]; struct pipe_blend_state *blend; struct pipe_rasterizer_state *rasterizer; @@ -330,12 +342,16 @@ static inline void fd_context_all_dirty(struct fd_context *ctx) { ctx->dirty = ~0; + for (unsigned i = 0; i < PIPE_SHADER_TYPES; i++) + ctx->dirty_shader[i] = ~0; } static inline void fd_context_all_clean(struct fd_context *ctx) { ctx->dirty = 0; + for (unsigned i = 0; i < PIPE_SHADER_TYPES; i++) + ctx->dirty_shader[i] = 0; } static inline struct pipe_scissor_state * diff --git a/src/gallium/drivers/freedreno/freedreno_program.c b/src/gallium/drivers/freedreno/freedreno_program.c index db6b258e21c..0bb5d68752c 100644 --- a/src/gallium/drivers/freedreno/freedreno_program.c +++ b/src/gallium/drivers/freedreno/freedreno_program.c @@ -37,7 +37,8 @@ fd_fp_state_bind(struct pipe_context *pctx, void *hwcso) { struct fd_context *ctx = fd_context(pctx); ctx->prog.fp = hwcso; - ctx->dirty |= FD_SHADER_DIRTY_FP; + ctx->dirty_shader[PIPE_SHADER_FRAGMENT] |= FD_DIRTY_SHADER_PROG; + ctx->dirty |= FD_DIRTY_PROG; } static void @@ -45,7 +46,8 @@ fd_vp_state_bind(struct pipe_context *pctx, void *hwcso) { struct fd_context *ctx = fd_context(pctx); ctx->prog.vp = hwcso; - ctx->dirty |= FD_SHADER_DIRTY_VP; + ctx->dirty_shader[PIPE_SHADER_VERTEX] |= FD_DIRTY_SHADER_PROG; + ctx->dirty |= FD_DIRTY_PROG; } static const char *solid_fp = diff --git a/src/gallium/drivers/freedreno/freedreno_resource.c b/src/gallium/drivers/freedreno/freedreno_resource.c index 427ada8b667..3b067095523 100644 --- a/src/gallium/drivers/freedreno/freedreno_resource.c +++ b/src/gallium/drivers/freedreno/freedreno_resource.c @@ -51,23 +51,13 @@ static void fd_invalidate_resource(struct fd_context *ctx, struct pipe_resource *prsc) { - int i; - /* Go through the entire state and see if the resource is bound * anywhere. If it is, mark the relevant state as dirty. This is called on * realloc_bo. */ - /* Constbufs */ - for (i = 1; i < PIPE_MAX_CONSTANT_BUFFERS && !(ctx->dirty & FD_DIRTY_CONSTBUF); i++) { - if (ctx->constbuf[PIPE_SHADER_VERTEX].cb[i].buffer == prsc) - ctx->dirty |= FD_DIRTY_CONSTBUF; - if (ctx->constbuf[PIPE_SHADER_FRAGMENT].cb[i].buffer == prsc) - ctx->dirty |= FD_DIRTY_CONSTBUF; - } - /* VBOs */ - for (i = 0; i < ctx->vtx.vertexbuf.count && !(ctx->dirty & FD_DIRTY_VTXBUF); i++) { + for (unsigned i = 0; i < ctx->vtx.vertexbuf.count && !(ctx->dirty & FD_DIRTY_VTXBUF); i++) { if (ctx->vtx.vertexbuf.vb[i].buffer == prsc) ctx->dirty |= FD_DIRTY_VTXBUF; } @@ -76,14 +66,26 @@ fd_invalidate_resource(struct fd_context *ctx, struct pipe_resource *prsc) if (ctx->indexbuf.buffer == prsc) ctx->dirty |= FD_DIRTY_INDEXBUF; - /* Textures */ - for (i = 0; i < ctx->tex[PIPE_SHADER_VERTEX].num_textures && !(ctx->dirty & FD_DIRTY_VERTTEX); i++) { - if (ctx->tex[PIPE_SHADER_VERTEX].textures[i] && (ctx->tex[PIPE_SHADER_VERTEX].textures[i]->texture == prsc)) - ctx->dirty |= FD_DIRTY_VERTTEX; - } - for (i = 0; i < ctx->tex[PIPE_SHADER_FRAGMENT].num_textures && !(ctx->dirty & FD_DIRTY_FRAGTEX); i++) { - if (ctx->tex[PIPE_SHADER_FRAGMENT].textures[i] && (ctx->tex[PIPE_SHADER_FRAGMENT].textures[i]->texture == prsc)) - ctx->dirty |= FD_DIRTY_FRAGTEX; + /* per-shader-stage resources: */ + for (unsigned stage = 0; stage < PIPE_SHADER_TYPES; stage++) { + /* Constbufs.. note that constbuf[0] is normal uniforms emitted in + * cmdstream rather than by pointer.. + */ + const unsigned num_ubos = util_last_bit(ctx->constbuf[stage].enabled_mask); + for (unsigned i = 1; i < num_ubos; i++) { + if (ctx->dirty_shader[stage] & FD_DIRTY_SHADER_CONST) + break; + if (ctx->constbuf[stage].cb[i].buffer == prsc) + ctx->dirty_shader[stage] |= FD_DIRTY_SHADER_CONST; + } + + /* Textures */ + for (unsigned i = 0; i < ctx->tex[stage].num_textures; i++) { + if (ctx->dirty_shader[stage] & FD_DIRTY_SHADER_TEX) + break; + if (ctx->tex[stage].textures[i] && (ctx->tex[stage].textures[i]->texture == prsc)) + ctx->dirty_shader[stage] |= FD_DIRTY_SHADER_TEX; + } } } diff --git a/src/gallium/drivers/freedreno/freedreno_state.c b/src/gallium/drivers/freedreno/freedreno_state.c index 06dfd228dcc..3b02e630646 100644 --- a/src/gallium/drivers/freedreno/freedreno_state.c +++ b/src/gallium/drivers/freedreno/freedreno_state.c @@ -109,7 +109,8 @@ fd_set_constant_buffer(struct pipe_context *pctx, so->enabled_mask |= 1 << index; so->dirty_mask |= 1 << index; - ctx->dirty |= FD_DIRTY_CONSTBUF; + ctx->dirty_shader[shader] |= FD_DIRTY_SHADER_CONST; + ctx->dirty |= FD_DIRTY_CONST; } static void diff --git a/src/gallium/drivers/freedreno/freedreno_texture.c b/src/gallium/drivers/freedreno/freedreno_texture.c index e9d90aa3a77..1487f7441c9 100644 --- a/src/gallium/drivers/freedreno/freedreno_texture.c +++ b/src/gallium/drivers/freedreno/freedreno_texture.c @@ -92,13 +92,8 @@ fd_sampler_states_bind(struct pipe_context *pctx, struct fd_context *ctx = fd_context(pctx); bind_sampler_states(&ctx->tex[shader], start, nr, hwcso); - - if (shader == PIPE_SHADER_FRAGMENT) { - ctx->dirty |= FD_DIRTY_FRAGTEX; - } - else if (shader == PIPE_SHADER_VERTEX) { - ctx->dirty |= FD_DIRTY_VERTTEX; - } + ctx->dirty_shader[shader] |= FD_DIRTY_SHADER_TEX; + ctx->dirty |= FD_DIRTY_TEX; } void @@ -109,17 +104,8 @@ fd_set_sampler_views(struct pipe_context *pctx, enum pipe_shader_type shader, struct fd_context *ctx = fd_context(pctx); set_sampler_views(&ctx->tex[shader], start, nr, views); - - switch (shader) { - case PIPE_SHADER_FRAGMENT: - ctx->dirty |= FD_DIRTY_FRAGTEX; - break; - case PIPE_SHADER_VERTEX: - ctx->dirty |= FD_DIRTY_VERTTEX; - break; - default: - break; - } + ctx->dirty_shader[shader] |= FD_DIRTY_SHADER_TEX; + ctx->dirty |= FD_DIRTY_TEX; } void diff --git a/src/gallium/drivers/freedreno/ir3/ir3_shader.c b/src/gallium/drivers/freedreno/ir3/ir3_shader.c index 402d12a205c..1d54d5330ad 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_shader.c +++ b/src/gallium/drivers/freedreno/ir3/ir3_shader.c @@ -658,16 +658,16 @@ void ir3_emit_vs_consts(const struct ir3_shader_variant *v, struct fd_ringbuffer *ring, struct fd_context *ctx, const struct pipe_draw_info *info) { - uint32_t dirty = ctx->dirty; + enum fd_dirty_shader_state dirty = ctx->dirty_shader[PIPE_SHADER_VERTEX]; debug_assert(v->type == SHADER_VERTEX); - if (dirty & (FD_DIRTY_PROG | FD_DIRTY_CONSTBUF)) { + if (dirty & (FD_DIRTY_SHADER_PROG | FD_DIRTY_SHADER_CONST)) { struct fd_constbuf_stateobj *constbuf; bool shader_dirty; constbuf = &ctx->constbuf[PIPE_SHADER_VERTEX]; - shader_dirty = !!(dirty & FD_SHADER_DIRTY_VP); + shader_dirty = !!(dirty & FD_DIRTY_SHADER_PROG); emit_user_consts(ctx, v, ring, constbuf); emit_ubos(ctx, v, ring, constbuf); @@ -718,16 +718,16 @@ void ir3_emit_fs_consts(const struct ir3_shader_variant *v, struct fd_ringbuffer *ring, struct fd_context *ctx) { - uint32_t dirty = ctx->dirty; + enum fd_dirty_shader_state dirty = ctx->dirty_shader[PIPE_SHADER_FRAGMENT]; debug_assert(v->type == SHADER_FRAGMENT); - if (dirty & (FD_DIRTY_PROG | FD_DIRTY_CONSTBUF)) { + if (dirty & (FD_DIRTY_SHADER_PROG | FD_DIRTY_SHADER_CONST)) { struct fd_constbuf_stateobj *constbuf; bool shader_dirty; constbuf = &ctx->constbuf[PIPE_SHADER_FRAGMENT]; - shader_dirty = !!(dirty & FD_SHADER_DIRTY_FP); + shader_dirty = !!(dirty & FD_DIRTY_SHADER_PROG); emit_user_consts(ctx, v, ring, constbuf); emit_ubos(ctx, v, ring, constbuf);