diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_context.c b/src/gallium/drivers/freedreno/a6xx/fd6_context.c index f3b4d5b60db..319680568cc 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_context.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_context.c @@ -170,6 +170,8 @@ setup_state_map(struct fd_context *ctx) fd_context_add_map(ctx, FD_DIRTY_PROG | FD_DIRTY_CONST, BIT(FD6_GROUP_CONST)); fd_context_add_map(ctx, FD_DIRTY_STREAMOUT, BIT(FD6_GROUP_SO)); + fd_context_add_map(ctx, FD_DIRTY_BLEND_COHERENT, + BIT(FD6_GROUP_PRIM_MODE_SYSMEM) | BIT(FD6_GROUP_PRIM_MODE_GMEM)); fd_context_add_shader_map(ctx, PIPE_SHADER_VERTEX, FD_DIRTY_SHADER_TEX, BIT(FD6_GROUP_VS_TEX)); diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_emit.c b/src/gallium/drivers/freedreno/a6xx/fd6_emit.c index 9d3d91e8131..946ab4096ec 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_emit.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_emit.c @@ -530,6 +530,27 @@ fd6_emit_non_ring(struct fd_ringbuffer *ring, struct fd6_emit *emit) assert_dt } } +static struct fd_ringbuffer* +build_prim_mode(struct fd6_emit *emit, struct fd_context *ctx, bool gmem) + assert_dt +{ + struct fd_ringbuffer *ring = + fd_submit_new_ringbuffer(emit->ctx->batch->submit, 2 * 4, FD_RINGBUFFER_STREAMING); + uint32_t prim_mode = NO_FLUSH; + if (emit->fs->fs.uses_fbfetch_output) { + if (gmem) { + prim_mode = ctx->blend->blend_coherent ? FLUSH_PER_OVERLAP : NO_FLUSH; + } else { + prim_mode = FLUSH_PER_OVERLAP_AND_OVERWRITE; + } + } else { + prim_mode = NO_FLUSH; + } + OUT_REG(ring, A6XX_GRAS_SC_CNTL(.ccusinglecachelinesize = 2, + .single_prim_mode = prim_mode)); + return ring; +} + void fd6_emit_3d_state(struct fd_ringbuffer *ring, struct fd6_emit *emit) { @@ -663,17 +684,11 @@ fd6_emit_3d_state(struct fd_ringbuffer *ring, struct fd6_emit *emit) fd6_emit_streamout(ring, emit); break; case FD6_GROUP_PRIM_MODE_SYSMEM: - state = fd_submit_new_ringbuffer(emit->ctx->batch->submit, 2 * 4, FD_RINGBUFFER_STREAMING); - OUT_PKT4(ring, REG_A6XX_GRAS_SC_CNTL, 1); - OUT_RING(ring, A6XX_GRAS_SC_CNTL_CCUSINGLECACHELINESIZE(2) | - emit->fs->fs.uses_fbfetch_output ? A6XX_GRAS_SC_CNTL_SINGLE_PRIM_MODE(FLUSH_PER_OVERLAP_AND_OVERWRITE) : 0); + state = build_prim_mode(emit, ctx, false); fd6_state_take_group(&emit->state, state, FD6_GROUP_PRIM_MODE_SYSMEM); break; case FD6_GROUP_PRIM_MODE_GMEM: - state = fd_submit_new_ringbuffer(emit->ctx->batch->submit, 2 * 4, FD_RINGBUFFER_STREAMING); - OUT_PKT4(ring, REG_A6XX_GRAS_SC_CNTL, 1); - OUT_RING(ring, A6XX_GRAS_SC_CNTL_CCUSINGLECACHELINESIZE(2) | - emit->fs->fs.uses_fbfetch_output ? A6XX_GRAS_SC_CNTL_SINGLE_PRIM_MODE(FLUSH_PER_OVERLAP) : 0); + state = build_prim_mode(emit, ctx, true); fd6_state_take_group(&emit->state, state, FD6_GROUP_PRIM_MODE_GMEM); break; case FD6_GROUP_NON_GROUP: diff --git a/src/gallium/drivers/freedreno/freedreno_context.h b/src/gallium/drivers/freedreno/freedreno_context.h index 665a3ce2d3a..d1892ba7515 100644 --- a/src/gallium/drivers/freedreno/freedreno_context.h +++ b/src/gallium/drivers/freedreno/freedreno_context.h @@ -174,7 +174,8 @@ enum fd_dirty_3d_state { FD_DIRTY_RASTERIZER_DISCARD = BIT(24), FD_DIRTY_RASTERIZER_CLIP_PLANE_ENABLE = BIT(25), FD_DIRTY_BLEND_DUAL = BIT(26), -#define NUM_DIRTY_BITS 27 + FD_DIRTY_BLEND_COHERENT = BIT(27), +#define NUM_DIRTY_BITS 28 /* additional flag for state requires updated resource tracking: */ FD_DIRTY_RESOURCE = BIT(31), diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c index 9a7ad7e9452..5458c35c00e 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.c +++ b/src/gallium/drivers/freedreno/freedreno_screen.c @@ -208,6 +208,7 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_NIR_COMPACT_ARRAYS: case PIPE_CAP_TEXTURE_MIRROR_CLAMP_TO_EDGE: case PIPE_CAP_GL_SPIRV: + case PIPE_CAP_FBFETCH_COHERENT: return 1; case PIPE_CAP_COPY_BETWEEN_COMPRESSED_AND_PLAIN_FORMATS: diff --git a/src/gallium/drivers/freedreno/freedreno_state.c b/src/gallium/drivers/freedreno/freedreno_state.c index 36bda1ad57d..f204d520766 100644 --- a/src/gallium/drivers/freedreno/freedreno_state.c +++ b/src/gallium/drivers/freedreno/freedreno_state.c @@ -515,10 +515,16 @@ fd_blend_state_bind(struct pipe_context *pctx, void *hwcso) in_dt : false; bool new_is_dual = cso ? cso->rt[0].blend_enable && util_blend_state_is_dual(cso, 0) : false; - ctx->blend = hwcso; fd_context_dirty(ctx, FD_DIRTY_BLEND); if (old_is_dual != new_is_dual) fd_context_dirty(ctx, FD_DIRTY_BLEND_DUAL); + + bool old_coherent = get_safe(ctx->blend, blend_coherent); + bool new_coherent = get_safe(cso, blend_coherent); + if (new_coherent != old_coherent) { + fd_context_dirty(ctx, FD_DIRTY_BLEND_COHERENT); + } + ctx->blend = hwcso; update_draw_cost(ctx); }