mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-20 18:10:11 +01:00
st/mesa: move check_program_state code into _mesa_update_state
_mesa_update_state() receives the _NEW_PROGRAM flag, so we can handle any shader changes there. There may be some overhead reduction because gfx_shaders_may_be_dirty is removed. Reviewed-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/19859>
This commit is contained in:
parent
0311827337
commit
aaa4b0e618
11 changed files with 109 additions and 148 deletions
|
|
@ -296,8 +296,7 @@ prepare_compute(struct gl_context *ctx)
|
|||
_mesa_update_state(ctx);
|
||||
|
||||
if ((st->dirty | ctx->NewDriverState) & st->active_states &
|
||||
ST_PIPELINE_COMPUTE_STATE_MASK ||
|
||||
st->compute_shader_may_be_dirty)
|
||||
ST_PIPELINE_COMPUTE_STATE_MASK)
|
||||
st_validate_state(st, ST_PIPELINE_COMPUTE);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3581,7 +3581,6 @@ struct gl_context
|
|||
|
||||
GLuint TextureStateTimestamp; /**< detect changes to shared state */
|
||||
|
||||
GLboolean LastVertexStageDirty; /**< the last vertex stage has changed */
|
||||
GLboolean PointSizeIsSet; /**< the glPointSize value in the shader is set */
|
||||
|
||||
/** \name For debugging/development only */
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@
|
|||
#include "blend.h"
|
||||
|
||||
#include "state_tracker/st_context.h"
|
||||
#include "state_tracker/st_util.h"
|
||||
|
||||
void
|
||||
_mesa_update_allow_draw_out_of_order(struct gl_context *ctx)
|
||||
|
|
@ -184,6 +185,12 @@ update_program(struct gl_context *ctx)
|
|||
const struct gl_program *prevTCP = ctx->TessCtrlProgram._Current;
|
||||
const struct gl_program *prevTEP = ctx->TessEvalProgram._Current;
|
||||
const struct gl_program *prevCP = ctx->ComputeProgram._Current;
|
||||
uint64_t prev_vp_affected_states = prevVP ? prevVP->affected_states : 0;
|
||||
uint64_t prev_tcp_affected_states = prevTCP ? prevTCP->affected_states : 0;
|
||||
uint64_t prev_tep_affected_states = prevTEP ? prevTEP->affected_states : 0;
|
||||
uint64_t prev_gp_affected_states = prevGP ? prevGP->affected_states : 0;
|
||||
uint64_t prev_fp_affected_states = prevFP ? prevFP->affected_states : 0;
|
||||
uint64_t prev_cp_affected_states = prevCP ? prevCP->affected_states : 0;
|
||||
|
||||
/*
|
||||
* Set the ctx->VertexProgram._Current and ctx->FragmentProgram._Current
|
||||
|
|
@ -259,24 +266,105 @@ update_program(struct gl_context *ctx)
|
|||
_mesa_reference_program(ctx, &ctx->ComputeProgram._Current, csProg);
|
||||
|
||||
bool vp_changed = ctx->VertexProgram._Current != prevVP;
|
||||
bool tcp_changed = ctx->TessCtrlProgram._Current != prevTCP;
|
||||
bool tep_changed = ctx->TessEvalProgram._Current != prevTEP;
|
||||
bool gp_changed = ctx->GeometryProgram._Current != prevGP;
|
||||
if (ctx->GeometryProgram._Current) {
|
||||
ctx->LastVertexStageDirty |= gp_changed;
|
||||
} else if (ctx->TessEvalProgram._Current) {
|
||||
ctx->LastVertexStageDirty |= gp_changed | tep_changed;
|
||||
} else {
|
||||
ctx->LastVertexStageDirty |= gp_changed | tep_changed | vp_changed;
|
||||
bool fp_changed = ctx->FragmentProgram._Current != prevFP;
|
||||
bool cp_changed = ctx->ComputeProgram._Current != prevCP;
|
||||
|
||||
/* Set NewDriverState depending on which shaders have changed. */
|
||||
uint64_t dirty = 0;
|
||||
|
||||
/* Flag states used by both new and old shaders to rebind shader resources
|
||||
* (because shaders pack them and reorder them) and to unbind shader
|
||||
* resources properly when transitioning to shaders that don't use them.
|
||||
*/
|
||||
if (vp_changed) {
|
||||
ctx->Array.NewVertexElements = true;
|
||||
dirty |= prev_vp_affected_states;
|
||||
if (ctx->VertexProgram._Current)
|
||||
dirty |= ST_NEW_VERTEX_PROGRAM(ctx, ctx->VertexProgram._Current);
|
||||
}
|
||||
|
||||
/* Let the driver know what's happening:
|
||||
if (tcp_changed) {
|
||||
dirty |= prev_tcp_affected_states;
|
||||
if (ctx->TessCtrlProgram._Current)
|
||||
dirty |= ctx->TessCtrlProgram._Current->affected_states;
|
||||
}
|
||||
|
||||
if (tep_changed) {
|
||||
dirty |= prev_tep_affected_states;
|
||||
if (ctx->TessEvalProgram._Current)
|
||||
dirty |= ctx->TessEvalProgram._Current->affected_states;
|
||||
}
|
||||
|
||||
if (gp_changed) {
|
||||
dirty |= prev_gp_affected_states;
|
||||
if (ctx->GeometryProgram._Current)
|
||||
dirty |= ctx->GeometryProgram._Current->affected_states;
|
||||
}
|
||||
|
||||
if (fp_changed) {
|
||||
dirty |= prev_fp_affected_states;
|
||||
if (ctx->FragmentProgram._Current)
|
||||
dirty |= ctx->FragmentProgram._Current->affected_states;
|
||||
}
|
||||
|
||||
if (cp_changed) {
|
||||
dirty |= prev_cp_affected_states;
|
||||
if (ctx->ComputeProgram._Current)
|
||||
dirty |= ctx->ComputeProgram._Current->affected_states;
|
||||
}
|
||||
|
||||
struct gl_program *last_vertex_stage;
|
||||
bool last_vertex_stage_dirty;
|
||||
|
||||
if (ctx->GeometryProgram._Current) {
|
||||
last_vertex_stage = ctx->GeometryProgram._Current;
|
||||
last_vertex_stage_dirty = gp_changed;
|
||||
} else if (ctx->TessEvalProgram._Current) {
|
||||
last_vertex_stage = ctx->TessEvalProgram._Current;
|
||||
last_vertex_stage_dirty = gp_changed | tep_changed;
|
||||
} else {
|
||||
last_vertex_stage = ctx->VertexProgram._Current;
|
||||
last_vertex_stage_dirty = gp_changed | tep_changed | vp_changed;
|
||||
}
|
||||
|
||||
/* Find out the number of viewports. This determines how many scissors
|
||||
* and viewport states we need to update.
|
||||
*/
|
||||
if (ctx->FragmentProgram._Current != prevFP ||
|
||||
ctx->VertexProgram._Current != prevVP ||
|
||||
ctx->GeometryProgram._Current != prevGP ||
|
||||
ctx->TessEvalProgram._Current != prevTEP ||
|
||||
ctx->TessCtrlProgram._Current != prevTCP ||
|
||||
ctx->ComputeProgram._Current != prevCP)
|
||||
struct st_context *st = ctx->st;
|
||||
unsigned num_viewports = 1;
|
||||
|
||||
if (last_vertex_stage &&
|
||||
last_vertex_stage->info.outputs_written & (
|
||||
VARYING_BIT_VIEWPORT | VARYING_BIT_VIEWPORT_MASK))
|
||||
num_viewports = ctx->Const.MaxViewports;
|
||||
|
||||
if (st->state.num_viewports != num_viewports) {
|
||||
st->state.num_viewports = num_viewports;
|
||||
dirty |= ST_NEW_VIEWPORT;
|
||||
|
||||
if (ctx->Scissor.EnableFlags & u_bit_consecutive(0, num_viewports))
|
||||
dirty |= ST_NEW_SCISSOR;
|
||||
}
|
||||
|
||||
if (st->lower_point_size && last_vertex_stage_dirty &&
|
||||
!ctx->VertexProgram.PointSizeEnabled && !ctx->PointSizeIsSet) {
|
||||
if (ctx->GeometryProgram._Current) {
|
||||
st->dirty |= ST_NEW_GS_CONSTANTS;
|
||||
} else if (ctx->TessEvalProgram._Current) {
|
||||
st->dirty |= ST_NEW_TES_CONSTANTS;
|
||||
} else {
|
||||
st->dirty |= ST_NEW_VS_CONSTANTS;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->NewDriverState |= dirty;
|
||||
|
||||
/* Let the driver know what's happening: */
|
||||
if (fp_changed || vp_changed || gp_changed || tep_changed ||
|
||||
tcp_changed || cp_changed)
|
||||
return _NEW_PROGRAM;
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -65,104 +65,11 @@ void st_init_atoms( struct st_context *st )
|
|||
call_once(&flag, init_atoms_once);
|
||||
}
|
||||
|
||||
|
||||
void st_destroy_atoms( struct st_context *st )
|
||||
{
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
|
||||
/* Too complex to figure out, just check every time:
|
||||
*/
|
||||
static void check_program_state( struct st_context *st )
|
||||
{
|
||||
struct gl_context *ctx = st->ctx;
|
||||
struct gl_program *old_vp = st->vp;
|
||||
struct gl_program *old_tcp = st->tcp;
|
||||
struct gl_program *old_tep = st->tep;
|
||||
struct gl_program *old_gp = st->gp;
|
||||
struct gl_program *old_fp = st->fp;
|
||||
|
||||
struct gl_program *new_vp = ctx->VertexProgram._Current;
|
||||
struct gl_program *new_tcp = ctx->TessCtrlProgram._Current;
|
||||
struct gl_program *new_tep = ctx->TessEvalProgram._Current;
|
||||
struct gl_program *new_gp = ctx->GeometryProgram._Current;
|
||||
struct gl_program *new_fp = ctx->FragmentProgram._Current;
|
||||
uint64_t dirty = 0;
|
||||
unsigned num_viewports = 1;
|
||||
|
||||
/* Flag states used by both new and old shaders to unbind shader resources
|
||||
* properly when transitioning to shaders that don't use them.
|
||||
*/
|
||||
if (unlikely(new_vp != old_vp)) {
|
||||
ctx->Array.NewVertexElements = true;
|
||||
if (old_vp)
|
||||
dirty |= old_vp->affected_states;
|
||||
if (new_vp)
|
||||
dirty |= ST_NEW_VERTEX_PROGRAM(st, new_vp);
|
||||
}
|
||||
|
||||
if (unlikely(new_tcp != old_tcp)) {
|
||||
if (old_tcp)
|
||||
dirty |= old_tcp->affected_states;
|
||||
if (new_tcp)
|
||||
dirty |= new_tcp->affected_states;
|
||||
}
|
||||
|
||||
if (unlikely(new_tep != old_tep)) {
|
||||
if (old_tep)
|
||||
dirty |= old_tep->affected_states;
|
||||
if (new_tep)
|
||||
dirty |= new_tep->affected_states;
|
||||
}
|
||||
|
||||
if (unlikely(new_gp != old_gp)) {
|
||||
if (old_gp)
|
||||
dirty |= old_gp->affected_states;
|
||||
if (new_gp)
|
||||
dirty |= new_gp->affected_states;
|
||||
}
|
||||
|
||||
if (unlikely(new_fp != old_fp)) {
|
||||
if (old_fp)
|
||||
dirty |= old_fp->affected_states;
|
||||
if (new_fp)
|
||||
dirty |= new_fp->affected_states;
|
||||
}
|
||||
|
||||
/* Find out the number of viewports. This determines how many scissors
|
||||
* and viewport states we need to update.
|
||||
*/
|
||||
struct gl_program *last_prim_shader = new_gp ? new_gp :
|
||||
new_tep ? new_tep : new_vp;
|
||||
if (last_prim_shader &&
|
||||
last_prim_shader->info.outputs_written & (
|
||||
VARYING_BIT_VIEWPORT | VARYING_BIT_VIEWPORT_MASK))
|
||||
num_viewports = ctx->Const.MaxViewports;
|
||||
|
||||
if (st->state.num_viewports != num_viewports) {
|
||||
st->state.num_viewports = num_viewports;
|
||||
dirty |= ST_NEW_VIEWPORT;
|
||||
|
||||
if (ctx->Scissor.EnableFlags & u_bit_consecutive(0, num_viewports))
|
||||
dirty |= ST_NEW_SCISSOR;
|
||||
}
|
||||
|
||||
if (st->lower_point_size && st->ctx->LastVertexStageDirty &&
|
||||
!st->ctx->VertexProgram.PointSizeEnabled && !st->ctx->PointSizeIsSet) {
|
||||
if (new_gp) {
|
||||
st->dirty |= ST_NEW_GS_CONSTANTS;
|
||||
} else if (new_tep) {
|
||||
st->dirty |= ST_NEW_TES_CONSTANTS;
|
||||
} else {
|
||||
st->dirty |= ST_NEW_VS_CONSTANTS;
|
||||
}
|
||||
}
|
||||
st->ctx->LastVertexStageDirty = false;
|
||||
|
||||
st->dirty |= dirty;
|
||||
}
|
||||
|
||||
void st_update_edgeflags(struct st_context *st, bool per_vertex_edgeflags)
|
||||
{
|
||||
bool edgeflags_enabled = st->ctx->Polygon.FrontMode != GL_FILL ||
|
||||
|
|
@ -174,7 +81,7 @@ void st_update_edgeflags(struct st_context *st, bool per_vertex_edgeflags)
|
|||
|
||||
struct gl_program *vp = st->ctx->VertexProgram._Current;
|
||||
if (vp)
|
||||
st->dirty |= ST_NEW_VERTEX_PROGRAM(st, vp);
|
||||
st->dirty |= ST_NEW_VERTEX_PROGRAM(st->ctx, vp);
|
||||
}
|
||||
|
||||
bool edgeflag_culls_prims = edgeflags_enabled && !vertdata_edgeflags &&
|
||||
|
|
@ -214,11 +121,6 @@ void st_validate_state( struct st_context *st, enum st_pipeline pipeline )
|
|||
if (st->ctx->API == API_OPENGL_COMPAT)
|
||||
check_attrib_edgeflag(st);
|
||||
|
||||
if (st->gfx_shaders_may_be_dirty) {
|
||||
check_program_state(st);
|
||||
st->gfx_shaders_may_be_dirty = false;
|
||||
}
|
||||
|
||||
if (pipeline == ST_PIPELINE_RENDER)
|
||||
pipeline_mask = ST_PIPELINE_RENDER_STATE_MASK;
|
||||
else
|
||||
|
|
@ -230,11 +132,6 @@ void st_validate_state( struct st_context *st, enum st_pipeline pipeline )
|
|||
break;
|
||||
|
||||
case ST_PIPELINE_META:
|
||||
if (st->gfx_shaders_may_be_dirty) {
|
||||
check_program_state(st);
|
||||
st->gfx_shaders_may_be_dirty = false;
|
||||
}
|
||||
|
||||
pipeline_mask = ST_PIPELINE_META_STATE_MASK;
|
||||
break;
|
||||
|
||||
|
|
@ -243,18 +140,6 @@ void st_validate_state( struct st_context *st, enum st_pipeline pipeline )
|
|||
break;
|
||||
|
||||
case ST_PIPELINE_COMPUTE: {
|
||||
struct gl_program *old_cp = st->cp;
|
||||
struct gl_program *new_cp = ctx->ComputeProgram._Current;
|
||||
|
||||
if (new_cp != old_cp) {
|
||||
if (old_cp)
|
||||
st->dirty |= old_cp->affected_states;
|
||||
assert(new_cp);
|
||||
st->dirty |= new_cp->affected_states;
|
||||
}
|
||||
|
||||
st->compute_shader_may_be_dirty = false;
|
||||
|
||||
/*
|
||||
* We add the ST_NEW_FB_STATE bit here as well, because glBindFramebuffer
|
||||
* acts as a barrier that breaks feedback loops between the framebuffer
|
||||
|
|
|
|||
|
|
@ -120,8 +120,8 @@ enum {
|
|||
ST_NEW_SAMPLE_STATE | \
|
||||
ST_NEW_SAMPLE_SHADING)
|
||||
|
||||
#define ST_NEW_VERTEX_PROGRAM(st, p) ((p)->affected_states | \
|
||||
(st_user_clip_planes_enabled(st->ctx) ? \
|
||||
#define ST_NEW_VERTEX_PROGRAM(ctx, p) ((p)->affected_states | \
|
||||
(st_user_clip_planes_enabled(ctx) ? \
|
||||
ST_NEW_CLIP_STATE : 0))
|
||||
|
||||
#define ST_NEW_CONSTANTS (ST_NEW_VS_CONSTANTS | \
|
||||
|
|
|
|||
|
|
@ -618,8 +618,7 @@ st_Bitmap(struct gl_context *ctx, GLint x, GLint y,
|
|||
* explicitly uploaded in the draw_bitmap_quad() function.
|
||||
*/
|
||||
if ((st->dirty | ctx->NewDriverState) & st->active_states &
|
||||
~ST_NEW_CONSTANTS & ST_PIPELINE_RENDER_STATE_MASK ||
|
||||
st->gfx_shaders_may_be_dirty) {
|
||||
~ST_NEW_CONSTANTS & ST_PIPELINE_RENDER_STATE_MASK) {
|
||||
st_validate_state(st, ST_PIPELINE_META);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -313,7 +313,7 @@ st_RenderMode(struct gl_context *ctx, GLenum newMode )
|
|||
ctx->Driver.DrawGalliumMultiMode = st_feedback_draw_vbo_multi_mode;
|
||||
/* need to generate/use a vertex program that emits pos/color/tex */
|
||||
if (vp)
|
||||
st->dirty |= ST_NEW_VERTEX_PROGRAM(st, vp);
|
||||
st->dirty |= ST_NEW_VERTEX_PROGRAM(ctx, vp);
|
||||
}
|
||||
|
||||
/* Restore geometry shader states when leaving GL_SELECT mode. */
|
||||
|
|
|
|||
|
|
@ -185,8 +185,6 @@ st_invalidate_state(struct gl_context *ctx)
|
|||
|
||||
/* Which shaders are dirty will be determined manually. */
|
||||
if (new_state & _NEW_PROGRAM) {
|
||||
st->gfx_shaders_may_be_dirty = true;
|
||||
st->compute_shader_may_be_dirty = true;
|
||||
/* This will mask out unused shader resources. */
|
||||
st->active_states = st_get_active_states(ctx);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -249,12 +249,6 @@ struct st_context
|
|||
/** This masks out unused shader resources. Only valid in draw calls. */
|
||||
uint64_t active_states;
|
||||
|
||||
/* If true, further analysis of states is required to know if something
|
||||
* has changed. Used mainly for shaders.
|
||||
*/
|
||||
bool gfx_shaders_may_be_dirty;
|
||||
bool compute_shader_may_be_dirty;
|
||||
|
||||
GLboolean vertdata_edgeflags;
|
||||
GLboolean edgeflag_culls_prims;
|
||||
|
||||
|
|
|
|||
|
|
@ -86,8 +86,7 @@ prepare_draw(struct st_context *st, struct gl_context *ctx, uint64_t state_mask,
|
|||
st_invalidate_readpix_cache(st);
|
||||
|
||||
/* Validate state. */
|
||||
if ((st->dirty | ctx->NewDriverState) & st->active_states & state_mask ||
|
||||
st->gfx_shaders_may_be_dirty) {
|
||||
if ((st->dirty | ctx->NewDriverState) & st->active_states & state_mask) {
|
||||
st_validate_state(st, pipeline);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1314,7 +1314,7 @@ st_finalize_program(struct st_context *st, struct gl_program *prog)
|
|||
if (st->current_program[prog->info.stage] == prog) {
|
||||
if (prog->info.stage == MESA_SHADER_VERTEX) {
|
||||
st->ctx->Array.NewVertexElements = true;
|
||||
st->dirty |= ST_NEW_VERTEX_PROGRAM(st, prog);
|
||||
st->dirty |= ST_NEW_VERTEX_PROGRAM(st->ctx, prog);
|
||||
} else {
|
||||
st->dirty |= prog->affected_states;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue