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
}
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);
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);
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);
}
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);
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: */
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;
{
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);
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]);
}
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;
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;
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: */
{
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);
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);
}
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;
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;
{
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);
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);
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;
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;
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;
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 *
{
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
{
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 =
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;
}
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;
+ }
}
}
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
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
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
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);
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);