Mesa (master): freedreno: refactor dirty state handling

Rob Clark robclark at kemper.freedesktop.org
Tue Apr 18 20:51:10 UTC 2017


Module: Mesa
Branch: master
Commit: 4299849ec7a873edf46a3a366749282fdec020fe
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=4299849ec7a873edf46a3a366749282fdec020fe

Author: Rob Clark <robdclark at gmail.com>
Date:   Sat Apr 15 10:04:55 2017 -0400

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 <robdclark at gmail.com>

---

 src/gallium/drivers/freedreno/a2xx/fd2_draw.c      |  5 +-
 src/gallium/drivers/freedreno/a2xx/fd2_emit.c      |  6 +-
 src/gallium/drivers/freedreno/a2xx/fd2_emit.h      |  2 +-
 src/gallium/drivers/freedreno/a2xx/fd2_program.c   |  6 +-
 src/gallium/drivers/freedreno/a3xx/fd3_draw.c      |  6 +-
 src/gallium/drivers/freedreno/a3xx/fd3_emit.c      |  8 +--
 src/gallium/drivers/freedreno/a3xx/fd3_emit.h      |  2 +-
 src/gallium/drivers/freedreno/a4xx/fd4_draw.c      |  8 ++-
 src/gallium/drivers/freedreno/a4xx/fd4_emit.c      |  6 +-
 src/gallium/drivers/freedreno/a4xx/fd4_emit.h      |  2 +-
 src/gallium/drivers/freedreno/a5xx/fd5_draw.c      |  6 +-
 src/gallium/drivers/freedreno/a5xx/fd5_emit.c      |  6 +-
 src/gallium/drivers/freedreno/a5xx/fd5_emit.h      |  2 +-
 src/gallium/drivers/freedreno/freedreno_context.h  | 72 +++++++++++++---------
 src/gallium/drivers/freedreno/freedreno_program.c  |  6 +-
 src/gallium/drivers/freedreno/freedreno_resource.c | 40 ++++++------
 src/gallium/drivers/freedreno/freedreno_state.c    |  3 +-
 src/gallium/drivers/freedreno/freedreno_texture.c  | 22 ++-----
 src/gallium/drivers/freedreno/ir3/ir3_shader.c     | 12 ++--
 19 files changed, 119 insertions(+), 101 deletions(-)

diff --git a/src/gallium/drivers/freedreno/a2xx/fd2_draw.c b/src/gallium/drivers/freedreno/a2xx/fd2_draw.c
index feec59fa5d..f360ec2f6e 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 fe2750ba10..d745e44b0a 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 6a26c85c14..d908b11351 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 8dcbb97938..9a77457251 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 c36e507166..b3e42f37a2 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 04e3300efd..ca97a08d54 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 6e7dee25da..5e574da199 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 869c69b25b..a76f9e8c43 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 4c79a67ba5..f0a1fdea0d 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 00f92faaf3..a724caedc2 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 147f707003..4ef0c7303d 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 1e5b6dbc29..f2c9a6b85d 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 0525b3e732..b18c0a8cb6 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 7f47eaf2a7..733c64b180 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 db6b258e21..0bb5d68752 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 427ada8b66..3b06709552 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 06dfd228dc..3b02e63064 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 e9d90aa3a7..1487f7441c 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 402d12a205..1d54d5330a 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);




More information about the mesa-commit mailing list