mirror of https://github.com/xemu-project/xemu.git
nv2a/glsl: Unify dirty shader state check
This commit is contained in:
parent
b7eb957e65
commit
d17be812ea
|
@ -696,87 +696,13 @@ static void update_shader_uniforms(PGRAPHState *pg, ShaderBinding *binding)
|
|||
&psh_values, PshUniform__COUNT);
|
||||
}
|
||||
|
||||
static bool test_shaders_dirty(PGRAPHState *pg)
|
||||
{
|
||||
#define CR_1(reg) CR_x(reg, 1)
|
||||
#define CR_4(reg) CR_x(reg, 4)
|
||||
#define CR_8(reg) CR_x(reg, 8)
|
||||
#define CF(src, name) CF_x(typeof(src), (&src), name, 1)
|
||||
#define CFA(src, name) CF_x(typeof(src[0]), src, name, ARRAY_SIZE(src))
|
||||
#define CNAME(name) reg_check__ ## name
|
||||
#define CX_x__define(type, name, x) static type CNAME(name)[x];
|
||||
#define CR_x__define(reg, x) CX_x__define(uint32_t, reg, x)
|
||||
#define CF_x__define(type, src, name, x) CX_x__define(type, name, x)
|
||||
#define CR_x__check(reg, x) \
|
||||
for (int i = 0; i < x; i++) { if (pgraph_reg_r(pg, reg+i*4) != CNAME(reg)[i]) goto dirty; }
|
||||
#define CF_x__check(type, src, name, x) \
|
||||
for (int i = 0; i < x; i++) { if (src[i] != CNAME(name)[i]) goto dirty; }
|
||||
#define CR_x__update(reg, x) \
|
||||
for (int i = 0; i < x; i++) { CNAME(reg)[i] = pgraph_reg_r(pg, reg+i*4); }
|
||||
#define CF_x__update(type, src, name, x) \
|
||||
for (int i = 0; i < x; i++) { CNAME(name)[i] = src[i]; }
|
||||
|
||||
#define DIRTY_REGS \
|
||||
CR_1(NV_PGRAPH_COMBINECTL) \
|
||||
CR_1(NV_PGRAPH_SHADERCTL) \
|
||||
CR_1(NV_PGRAPH_SHADOWCTL) \
|
||||
CR_1(NV_PGRAPH_COMBINESPECFOG0) \
|
||||
CR_1(NV_PGRAPH_COMBINESPECFOG1) \
|
||||
CR_1(NV_PGRAPH_CONTROL_0) \
|
||||
CR_1(NV_PGRAPH_CONTROL_3) \
|
||||
CR_1(NV_PGRAPH_CSV0_C) \
|
||||
CR_1(NV_PGRAPH_CSV0_D) \
|
||||
CR_1(NV_PGRAPH_CSV1_A) \
|
||||
CR_1(NV_PGRAPH_CSV1_B) \
|
||||
CR_1(NV_PGRAPH_SETUPRASTER) \
|
||||
CR_1(NV_PGRAPH_SHADERPROG) \
|
||||
CR_1(NV_PGRAPH_ZCOMPRESSOCCLUDE) \
|
||||
CR_8(NV_PGRAPH_COMBINECOLORI0) \
|
||||
CR_8(NV_PGRAPH_COMBINECOLORO0) \
|
||||
CR_8(NV_PGRAPH_COMBINEALPHAI0) \
|
||||
CR_8(NV_PGRAPH_COMBINEALPHAO0) \
|
||||
CR_8(NV_PGRAPH_COMBINEFACTOR0) \
|
||||
CR_8(NV_PGRAPH_COMBINEFACTOR1) \
|
||||
CR_1(NV_PGRAPH_SHADERCLIPMODE) \
|
||||
CR_4(NV_PGRAPH_TEXCTL0_0) \
|
||||
CR_4(NV_PGRAPH_TEXFMT0) \
|
||||
CR_4(NV_PGRAPH_TEXFILTER0) \
|
||||
CR_8(NV_PGRAPH_WINDOWCLIPX0) \
|
||||
CR_8(NV_PGRAPH_WINDOWCLIPY0) \
|
||||
CF(pg->primitive_mode, primitive_mode) \
|
||||
CF(pg->surface_scale_factor, surface_scale_factor) \
|
||||
CF(pg->compressed_attrs, compressed_attrs) \
|
||||
CFA(pg->texture_matrix_enable, texture_matrix_enable) \
|
||||
CR_4(NV_PGRAPH_COLORKEYCOLOR0)
|
||||
|
||||
#define CR_x(reg, x) CR_x__define(reg, x)
|
||||
#define CF_x(type, src, name, x) CF_x__define(type, src, name, x)
|
||||
DIRTY_REGS
|
||||
#undef CR_x
|
||||
#undef CF_x
|
||||
|
||||
#define CR_x(reg, x) CR_x__check(reg, x)
|
||||
#define CF_x(type, src, name, x) CF_x__check(type, src, name, x)
|
||||
DIRTY_REGS
|
||||
#undef CR_x
|
||||
#undef CF_x
|
||||
return false;
|
||||
|
||||
dirty:
|
||||
#define CR_x(reg, x) CR_x__update(reg, x)
|
||||
#define CF_x(type, src, name, x) CF_x__update(type, src, name, x)
|
||||
DIRTY_REGS
|
||||
#undef CR_x
|
||||
#undef CF_x
|
||||
return true;
|
||||
}
|
||||
|
||||
void pgraph_gl_bind_shaders(PGRAPHState *pg)
|
||||
{
|
||||
PGRAPHGLState *r = pg->gl_renderer_state;
|
||||
|
||||
bool binding_changed = false;
|
||||
if (r->shader_binding && !test_shaders_dirty(pg) && !pg->program_data_dirty) {
|
||||
if (r->shader_binding &&
|
||||
!pgraph_check_shader_state_dirty(pg, &r->shader_binding->state)) {
|
||||
nv2a_profile_inc_counter(NV2A_PROF_SHADER_BIND_NOTDIRTY);
|
||||
goto update_uniforms;
|
||||
}
|
||||
|
|
|
@ -34,3 +34,60 @@ ShaderState pgraph_get_shader_state(PGRAPHState *pg)
|
|||
|
||||
return state;
|
||||
}
|
||||
|
||||
bool pgraph_check_shader_state_dirty(PGRAPHState *pg, const ShaderState *state)
|
||||
{
|
||||
if (pg->program_data_dirty) {
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int regs[] = {
|
||||
NV_PGRAPH_COMBINECTL, NV_PGRAPH_COMBINESPECFOG0,
|
||||
NV_PGRAPH_COMBINESPECFOG1, NV_PGRAPH_CONTROL_0,
|
||||
NV_PGRAPH_CONTROL_3, NV_PGRAPH_CSV0_C,
|
||||
NV_PGRAPH_CSV0_D, NV_PGRAPH_CSV1_A,
|
||||
NV_PGRAPH_CSV1_B, NV_PGRAPH_POINTSIZE,
|
||||
NV_PGRAPH_SETUPRASTER, NV_PGRAPH_SHADERCLIPMODE,
|
||||
NV_PGRAPH_SHADERCTL, NV_PGRAPH_SHADERPROG,
|
||||
NV_PGRAPH_SHADOWCTL, NV_PGRAPH_ZCOMPRESSOCCLUDE,
|
||||
};
|
||||
for (int i = 0; i < ARRAY_SIZE(regs); i++) {
|
||||
if (pgraph_is_reg_dirty(pg, regs[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
int num_stages = pgraph_reg_r(pg, NV_PGRAPH_COMBINECTL) & 0xFF;
|
||||
for (int i = 0; i < num_stages; i++) {
|
||||
if (pgraph_is_reg_dirty(pg, NV_PGRAPH_COMBINEALPHAI0 + i * 4) ||
|
||||
pgraph_is_reg_dirty(pg, NV_PGRAPH_COMBINEALPHAO0 + i * 4) ||
|
||||
pgraph_is_reg_dirty(pg, NV_PGRAPH_COMBINECOLORI0 + i * 4) ||
|
||||
pgraph_is_reg_dirty(pg, NV_PGRAPH_COMBINECOLORO0 + i * 4)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (pg->uniform_attrs != state->vsh.uniform_attrs ||
|
||||
pg->swizzle_attrs != state->vsh.swizzle_attrs ||
|
||||
pg->compressed_attrs != state->vsh.compressed_attrs ||
|
||||
pg->primitive_mode != state->vsh.primitive_mode ||
|
||||
pg->surface_scale_factor != state->vsh.surface_scale_factor) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Textures
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (pgraph_is_reg_dirty(pg, NV_PGRAPH_TEXCTL0_0 + i * 4) ||
|
||||
pgraph_is_reg_dirty(pg, NV_PGRAPH_TEXFILTER0 + i * 4) ||
|
||||
pgraph_is_reg_dirty(pg, NV_PGRAPH_TEXFMT0 + i * 4)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pg->texture_matrix_enable[i] !=
|
||||
state->vsh.fixed_function.texture_matrix_enable[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -33,4 +33,6 @@ typedef struct PGRAPHState PGRAPHState;
|
|||
|
||||
ShaderState pgraph_get_shader_state(PGRAPHState *pg);
|
||||
|
||||
bool pgraph_check_shader_state_dirty(PGRAPHState *pg, const ShaderState *state);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -382,84 +382,6 @@ static ShaderBinding *gen_shaders(PGRAPHState *pg, ShaderState *state)
|
|||
return snode;
|
||||
}
|
||||
|
||||
// Quickly check PGRAPH state to see if any registers have changed that
|
||||
// necessitate a full shader state inspection.
|
||||
static bool check_shaders_dirty(PGRAPHState *pg)
|
||||
{
|
||||
PGRAPHVkState *r = pg->vk_renderer_state;
|
||||
|
||||
if (!r->shader_binding) {
|
||||
return true;
|
||||
}
|
||||
if (pg->program_data_dirty) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int num_stages = pgraph_reg_r(pg, NV_PGRAPH_COMBINECTL) & 0xFF;
|
||||
for (int i = 0; i < num_stages; i++) {
|
||||
if (pgraph_is_reg_dirty(pg, NV_PGRAPH_COMBINEALPHAI0 + i * 4) ||
|
||||
pgraph_is_reg_dirty(pg, NV_PGRAPH_COMBINEALPHAO0 + i * 4) ||
|
||||
pgraph_is_reg_dirty(pg, NV_PGRAPH_COMBINECOLORI0 + i * 4) ||
|
||||
pgraph_is_reg_dirty(pg, NV_PGRAPH_COMBINECOLORO0 + i * 4)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int regs[] = {
|
||||
NV_PGRAPH_COMBINECTL,
|
||||
NV_PGRAPH_COMBINESPECFOG0,
|
||||
NV_PGRAPH_COMBINESPECFOG1,
|
||||
NV_PGRAPH_CONTROL_0,
|
||||
NV_PGRAPH_CONTROL_3,
|
||||
NV_PGRAPH_CSV0_C,
|
||||
NV_PGRAPH_CSV0_D,
|
||||
NV_PGRAPH_CSV1_A,
|
||||
NV_PGRAPH_CSV1_B,
|
||||
NV_PGRAPH_POINTSIZE,
|
||||
NV_PGRAPH_SETUPRASTER,
|
||||
NV_PGRAPH_SHADERCLIPMODE,
|
||||
NV_PGRAPH_SHADERCTL,
|
||||
NV_PGRAPH_SHADERPROG,
|
||||
NV_PGRAPH_SHADOWCTL,
|
||||
NV_PGRAPH_ZCOMPRESSOCCLUDE,
|
||||
};
|
||||
for (int i = 0; i < ARRAY_SIZE(regs); i++) {
|
||||
if (pgraph_is_reg_dirty(pg, regs[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
ShaderState *state = &r->shader_binding->state;
|
||||
if (pg->uniform_attrs != state->vsh.uniform_attrs ||
|
||||
pg->swizzle_attrs != state->vsh.swizzle_attrs ||
|
||||
pg->compressed_attrs != state->vsh.compressed_attrs ||
|
||||
pg->primitive_mode != state->vsh.primitive_mode ||
|
||||
pg->surface_scale_factor != state->vsh.surface_scale_factor) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Textures
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (pgraph_is_reg_dirty(pg, NV_PGRAPH_TEXCTL0_0 + i * 4) ||
|
||||
pgraph_is_reg_dirty(pg, NV_PGRAPH_TEXFILTER0 + i * 4) ||
|
||||
pgraph_is_reg_dirty(pg, NV_PGRAPH_TEXFMT0 + i * 4)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pg->vk_renderer_state->shader_binding->state.vsh
|
||||
.is_fixed_function &&
|
||||
(pg->texture_matrix_enable[i] !=
|
||||
pg->vk_renderer_state->shader_binding->state.vsh.fixed_function
|
||||
.texture_matrix_enable[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
nv2a_profile_inc_counter(NV2A_PROF_SHADER_BIND_NOTDIRTY);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void apply_uniform_updates(ShaderUniformLayout *layout,
|
||||
const UniformInfo *info, int *locs,
|
||||
void *values, size_t count)
|
||||
|
@ -533,12 +455,16 @@ void pgraph_vk_bind_shaders(PGRAPHState *pg)
|
|||
|
||||
r->shader_bindings_changed = false;
|
||||
|
||||
if (check_shaders_dirty(pg)) {
|
||||
if (!r->shader_binding ||
|
||||
pgraph_check_shader_state_dirty(pg, &r->shader_binding->state)) {
|
||||
ShaderState new_state = pgraph_get_shader_state(pg);
|
||||
if (!r->shader_binding || memcmp(&r->shader_binding->state, &new_state, sizeof(ShaderState))) {
|
||||
if (!r->shader_binding || memcmp(&r->shader_binding->state, &new_state,
|
||||
sizeof(ShaderState))) {
|
||||
r->shader_binding = gen_shaders(pg, &new_state);
|
||||
r->shader_bindings_changed = true;
|
||||
}
|
||||
} else {
|
||||
nv2a_profile_inc_counter(NV2A_PROF_SHADER_BIND_NOTDIRTY);
|
||||
}
|
||||
|
||||
update_shader_uniforms(pg);
|
||||
|
|
Loading…
Reference in New Issue