mesa: handle mesh shader in state management

Reviewed-by: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36976>
This commit is contained in:
Qiang Yu 2025-02-27 16:21:42 +08:00
parent a47c70ce42
commit e8a817f196
3 changed files with 105 additions and 9 deletions

View file

@ -107,6 +107,10 @@ _mesa_update_allow_draw_out_of_order(struct gl_context *ctx)
ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY];
struct gl_program *fs =
ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT];
struct gl_program *ts =
ctx->_Shader->CurrentProgram[MESA_SHADER_TASK];
struct gl_program *ms =
ctx->_Shader->CurrentProgram[MESA_SHADER_MESH];
GLenum16 depth_func = ctx->Depth.Func;
/* Z fighting and any primitives with equal Z shouldn't be reordered
@ -141,6 +145,8 @@ _mesa_update_allow_draw_out_of_order(struct gl_context *ctx)
(!tes || !tes->info.writes_memory) &&
(!tcs || !tcs->info.writes_memory) &&
(!gs || !gs->info.writes_memory) &&
(!ts || !ts->info.writes_memory) &&
(!ms || !ms->info.writes_memory) &&
(!fs || !fs->info.writes_memory || !fs->info.fs.early_fragment_tests);
/* If we are disabling out-of-order drawing, we need to flush queued
@ -159,6 +165,8 @@ _mesa_set_active_states(struct gl_context *ctx)
struct gl_program *gp = ctx->GeometryProgram._Current;
struct gl_program *fp = ctx->FragmentProgram._Current;
struct gl_program *cp = ctx->ComputeProgram._Current;
struct gl_program *tp = ctx->TaskProgram._Current;
struct gl_program *mp = ctx->MeshProgram._Current;
BITSET_ZERO(ctx->st->active_states);
@ -184,6 +192,10 @@ _mesa_set_active_states(struct gl_context *ctx)
ST_SET_STATES(ctx->st->active_states, fp->affected_states);
if (cp)
ST_SET_STATES(ctx->st->active_states, cp->affected_states);
if (tp)
ST_SET_STATES(ctx->st->active_states, tp->affected_states);
if (mp)
ST_SET_STATES(ctx->st->active_states, mp->affected_states);
}
/**
@ -214,12 +226,18 @@ update_program(struct gl_context *ctx)
ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT];
struct gl_program *csProg =
ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE];
struct gl_program *tsProg =
ctx->_Shader->CurrentProgram[MESA_SHADER_TASK];
struct gl_program *msProg =
ctx->_Shader->CurrentProgram[MESA_SHADER_MESH];
const struct gl_program *prevVP = ctx->VertexProgram._Current;
const struct gl_program *prevFP = ctx->FragmentProgram._Current;
const struct gl_program *prevGP = ctx->GeometryProgram._Current;
const struct gl_program *prevTCP = ctx->TessCtrlProgram._Current;
const struct gl_program *prevTEP = ctx->TessEvalProgram._Current;
const struct gl_program *prevCP = ctx->ComputeProgram._Current;
const struct gl_program *prevTP = ctx->TaskProgram._Current;
const struct gl_program *prevMP = ctx->MeshProgram._Current;
st_state_bitset prev_vp_affected_states = {0};
if (prevVP) BITSET_COPY(prev_vp_affected_states, prevVP->affected_states);
st_state_bitset prev_tcp_affected_states = {0};
@ -232,6 +250,10 @@ update_program(struct gl_context *ctx)
if (prevFP) BITSET_COPY(prev_fp_affected_states, prevFP->affected_states);
st_state_bitset prev_cp_affected_states = {0};
if (prevCP) BITSET_COPY(prev_cp_affected_states, prevCP->affected_states);
st_state_bitset prev_tp_affected_states = {0};
if (prevTP) BITSET_COPY(prev_tp_affected_states, prevTP->affected_states);
st_state_bitset prev_mp_affected_states = {0};
if (prevMP) BITSET_COPY(prev_mp_affected_states, prevMP->affected_states);
/*
* Set the ctx->VertexProgram._Current and ctx->FragmentProgram._Current
@ -303,6 +325,8 @@ update_program(struct gl_context *ctx)
_mesa_reference_program(ctx, &ctx->TessEvalProgram._Current, tesProg);
_mesa_reference_program(ctx, &ctx->TessCtrlProgram._Current, tcsProg);
_mesa_reference_program(ctx, &ctx->ComputeProgram._Current, csProg);
_mesa_reference_program(ctx, &ctx->TaskProgram._Current, tsProg);
_mesa_reference_program(ctx, &ctx->MeshProgram._Current, msProg);
bool vp_changed = ctx->VertexProgram._Current != prevVP;
bool tcp_changed = ctx->TessCtrlProgram._Current != prevTCP;
@ -310,6 +334,8 @@ update_program(struct gl_context *ctx)
bool gp_changed = ctx->GeometryProgram._Current != prevGP;
bool fp_changed = ctx->FragmentProgram._Current != prevFP;
bool cp_changed = ctx->ComputeProgram._Current != prevCP;
bool tp_changed = ctx->TaskProgram._Current != prevTP;
bool mp_changed = ctx->MeshProgram._Current != prevMP;
/* Set NewDriverState depending on which shaders have changed. */
st_state_bitset dirty = {0};
@ -358,10 +384,25 @@ update_program(struct gl_context *ctx)
ST_SET_STATES(dirty, ctx->ComputeProgram._Current->affected_states);
}
if (tp_changed) {
ST_SET_STATES(dirty, prev_tp_affected_states);
if (ctx->TaskProgram._Current)
ST_SET_STATES(dirty, ctx->TaskProgram._Current->affected_states);
}
if (mp_changed) {
ST_SET_STATES(dirty, prev_mp_affected_states);
if (ctx->MeshProgram._Current)
ST_SET_STATES(dirty, ctx->MeshProgram._Current->affected_states);
}
struct gl_program *last_vertex_stage;
bool last_vertex_stage_dirty;
if (ctx->GeometryProgram._Current) {
if (ctx->MeshProgram._Current) {
last_vertex_stage = ctx->MeshProgram._Current;
last_vertex_stage_dirty = mp_changed;
} else if (ctx->GeometryProgram._Current) {
last_vertex_stage = ctx->GeometryProgram._Current;
last_vertex_stage_dirty = gp_changed;
} else if (ctx->TessEvalProgram._Current) {
@ -393,7 +434,10 @@ update_program(struct gl_context *ctx)
if (st->lower_point_size && last_vertex_stage_dirty &&
!ctx->VertexProgram.PointSizeEnabled && !ctx->PointSizeIsSet) {
if (ctx->GeometryProgram._Current) {
if (ctx->MeshProgram._Current) {
ST_SET_STATE(ctx->NewDriverState, ST_NEW_MS_CONSTANTS);
} else if (ctx->GeometryProgram._Current) {
ST_SET_STATE(ctx->NewDriverState, ST_NEW_GS_CONSTANTS);
} else if (ctx->TessEvalProgram._Current) {
ST_SET_STATE(ctx->NewDriverState, ST_NEW_TES_CONSTANTS);
@ -406,7 +450,7 @@ update_program(struct gl_context *ctx)
/* Let the driver know what's happening: */
if (fp_changed || vp_changed || gp_changed || tep_changed ||
tcp_changed || cp_changed) {
tcp_changed || cp_changed || tp_changed || mp_changed) {
/* This will mask out unused shader resources. */
_mesa_set_active_states(ctx);
@ -466,6 +510,14 @@ update_program_constants(struct gl_context *ctx)
update_single_program_constants(ctx, ctx->TessEvalProgram._Current,
MESA_SHADER_TESS_EVAL);
}
if (_mesa_has_EXT_mesh_shader(ctx)) {
new_state |=
update_single_program_constants(ctx, ctx->TaskProgram._Current,
MESA_SHADER_TASK) |
update_single_program_constants(ctx, ctx->MeshProgram._Current,
MESA_SHADER_MESH);
}
}
return new_state;

View file

@ -112,6 +112,7 @@ typedef BITSET_DECLARE(st_state_bitset, ST_NUM_ATOMS);
do { \
ST_SET_STATE3(bitset, ST_NEW_VS_##state, ST_NEW_TCS_##state, ST_NEW_TES_##state); \
ST_SET_STATE3(bitset, ST_NEW_GS_##state, ST_NEW_FS_##state, ST_NEW_CS_##state); \
ST_SET_STATE2(bitset, ST_NEW_TS_##state, ST_NEW_MS_##state); \
} while (0)
#define ST_SET_FRAMEBUFFER_STATES(bitset) \

View file

@ -192,6 +192,33 @@ st_set_prog_affected_state_flags(struct gl_program *prog)
ST_NEW_CS_ATOMICS);
break;
case MESA_SHADER_TASK:
ST_SET_STATE(prog->affected_states, ST_NEW_TS_STATE);
set_affected_state_flags(prog,
ST_NEW_TS_CONSTANTS,
ST_NEW_TS_SAMPLER_VIEWS,
ST_NEW_TS_SAMPLERS,
ST_NEW_TS_IMAGES,
ST_NEW_TS_UBOS,
ST_NEW_TS_SSBOS,
ST_NEW_TS_ATOMICS);
break;
case MESA_SHADER_MESH:
ST_SET_STATE2(prog->affected_states, ST_NEW_MS_STATE,
ST_NEW_RASTERIZER);
set_affected_state_flags(prog,
ST_NEW_MS_CONSTANTS,
ST_NEW_MS_SAMPLER_VIEWS,
ST_NEW_MS_SAMPLERS,
ST_NEW_MS_IMAGES,
ST_NEW_MS_UBOS,
ST_NEW_MS_SSBOS,
ST_NEW_MS_ATOMICS);
break;
default:
UNREACHABLE("unhandled shader stage");
}
@ -1465,18 +1492,34 @@ st_finalize_program(struct st_context *st, struct gl_program *prog,
MESA_TRACE_FUNC();
if (prog->info.stage == MESA_SHADER_VERTEX)
switch (prog->info.stage) {
case MESA_SHADER_VERTEX:
is_bound = prog == ctx->VertexProgram._Current;
else if (prog->info.stage == MESA_SHADER_TESS_CTRL)
break;
case MESA_SHADER_TESS_CTRL:
is_bound = prog == ctx->TessCtrlProgram._Current;
else if (prog->info.stage == MESA_SHADER_TESS_EVAL)
break;
case MESA_SHADER_TESS_EVAL:
is_bound = prog == ctx->TessEvalProgram._Current;
else if (prog->info.stage == MESA_SHADER_GEOMETRY)
break;
case MESA_SHADER_GEOMETRY:
is_bound = prog == ctx->GeometryProgram._Current;
else if (prog->info.stage == MESA_SHADER_FRAGMENT)
break;
case MESA_SHADER_FRAGMENT:
is_bound = prog == ctx->FragmentProgram._Current;
else if (prog->info.stage == MESA_SHADER_COMPUTE)
break;
case MESA_SHADER_COMPUTE:
is_bound = prog == ctx->ComputeProgram._Current;
break;
case MESA_SHADER_TASK:
is_bound = prog == ctx->TaskProgram._Current;
break;
case MESA_SHADER_MESH:
is_bound = prog == ctx->MeshProgram._Current;
break;
default:
UNREACHABLE("invalid program");
}
if (is_bound) {
if (prog->info.stage == MESA_SHADER_VERTEX) {