nv2a: Extract VshState from ShaderState

This commit is contained in:
Matt Borgerson
2025-06-28 00:08:45 -07:00
committed by mborgerson
parent 9d9c88f71d
commit c575b08b5f
10 changed files with 244 additions and 231 deletions

View File

@ -195,7 +195,7 @@ static void update_shader_constant_locations(ShaderBinding *binding)
binding->point_params_loc[i] = glGetUniformLocation(binding->gl_program, tmp); binding->point_params_loc[i] = glGetUniformLocation(binding->gl_program, tmp);
} }
if (binding->state.fixed_function) { if (binding->state.vsh.is_fixed_function) {
binding->material_alpha_loc = binding->material_alpha_loc =
glGetUniformLocation(binding->gl_program, "material_alpha"); glGetUniformLocation(binding->gl_program, "material_alpha");
binding->specular_power_loc = binding->specular_power_loc =
@ -230,14 +230,11 @@ static void generate_shaders(ShaderBinding *binding)
ShaderState *state = &binding->state; ShaderState *state = &binding->state;
/* Create an optional geometry shader and find primitive type */ /* Create an optional geometry shader and find primitive type */
GLenum gl_primitive_mode = GLenum gl_primitive_mode = get_gl_primitive_mode(
get_gl_primitive_mode(state->polygon_front_mode, state->primitive_mode); state->vsh.polygon_front_mode, state->vsh.primitive_mode);
MString* geometry_shader_code = MString *geometry_shader_code = pgraph_gen_geom_glsl(
pgraph_gen_geom_glsl(state->polygon_front_mode, state->vsh.polygon_front_mode, state->vsh.polygon_back_mode,
state->polygon_back_mode, state->vsh.primitive_mode, state->vsh.smooth_shading, false);
state->primitive_mode,
state->smooth_shading,
false);
if (geometry_shader_code) { if (geometry_shader_code) {
const char* geometry_shader_code_str = const char* geometry_shader_code_str =
mstring_get_str(geometry_shader_code); mstring_get_str(geometry_shader_code);
@ -250,7 +247,7 @@ static void generate_shaders(ShaderBinding *binding)
/* create the vertex shader */ /* create the vertex shader */
MString *vertex_shader_code = MString *vertex_shader_code =
pgraph_gen_vsh_glsl(state, geometry_shader_code != NULL); pgraph_gen_vsh_glsl(&state->vsh, geometry_shader_code != NULL);
GLuint vertex_shader = create_gl_shader(GL_VERTEX_SHADER, GLuint vertex_shader = create_gl_shader(GL_VERTEX_SHADER,
mstring_get_str(vertex_shader_code), mstring_get_str(vertex_shader_code),
"vertex shader"); "vertex shader");
@ -378,8 +375,9 @@ bool pgraph_gl_shader_load_from_memory(ShaderBinding *binding)
glUseProgram(gl_program); glUseProgram(gl_program);
binding->gl_program = gl_program; binding->gl_program = gl_program;
binding->gl_primitive_mode = get_gl_primitive_mode( binding->gl_primitive_mode =
binding->state.polygon_front_mode, binding->state.primitive_mode); get_gl_primitive_mode(binding->state.vsh.polygon_front_mode,
binding->state.vsh.primitive_mode);
binding->initialized = true; binding->initialized = true;
g_free(binding->program); g_free(binding->program);
@ -814,7 +812,7 @@ static void shader_update_constants(PGRAPHState *pg, ShaderBinding *binding,
assert(0); assert(0);
} }
if (state->fixed_function) { if (state->vsh.is_fixed_function) {
/* update lighting constants */ /* update lighting constants */
struct { struct {
uint32_t* v; uint32_t* v;
@ -1047,7 +1045,7 @@ void pgraph_gl_bind_shaders(PGRAPHState *pg)
ShaderBinding *old_binding = r->shader_binding; ShaderBinding *old_binding = r->shader_binding;
ShaderState state = pgraph_get_shader_state(pg); ShaderState state = pgraph_get_shader_state(pg);
assert(!state.vulkan); assert(!state.vsh.vulkan);
NV2A_GL_DGROUP_BEGIN("%s (VP: %s FFP: %s)", __func__, NV2A_GL_DGROUP_BEGIN("%s (VP: %s FFP: %s)", __func__,
state.vertex_program ? "yes" : "no", state.vertex_program ? "yes" : "no",

View File

@ -29,7 +29,7 @@ static void append_skinning_code(MString* str, bool mix,
const char* output, const char* input, const char* output, const char* input,
const char* matrix, const char* swizzle); const char* matrix, const char* swizzle);
void pgraph_gen_vsh_ff_glsl(const ShaderState *state, MString *header, void pgraph_gen_vsh_ff_glsl(const VshState *state, MString *header,
MString *body, MString *uniforms) MString *body, MString *uniforms)
{ {
int i, j; int i, j;
@ -119,7 +119,7 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
/* Skinning */ /* Skinning */
unsigned int count; unsigned int count;
bool mix; bool mix;
switch (state->skinning) { switch (state->fixed_function.skinning) {
case SKINNING_OFF: case SKINNING_OFF:
mix = false; count = 0; break; mix = false; count = 0; break;
case SKINNING_1WEIGHTS: case SKINNING_1WEIGHTS:
@ -139,7 +139,7 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
break; break;
} }
mstring_append_fmt(body, "/* Skinning mode %d */\n", mstring_append_fmt(body, "/* Skinning mode %d */\n",
state->skinning); state->fixed_function.skinning);
append_skinning_code(body, mix, count, "vec4", append_skinning_code(body, mix, count, "vec4",
"tPosition", "position", "tPosition", "position",
@ -149,7 +149,7 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
"invModelViewMat", "xyz"); "invModelViewMat", "xyz");
/* Normalization */ /* Normalization */
if (state->normalization) { if (state->fixed_function.normalization) {
mstring_append(body, "tNormal = normalize(tNormal);\n"); mstring_append(body, "tNormal = normalize(tNormal);\n");
} }
@ -163,7 +163,7 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
/* TODO: TexGen View Model missing! */ /* TODO: TexGen View Model missing! */
char c = "xyzw"[j]; char c = "xyzw"[j];
char cSuffix = "STRQ"[j]; char cSuffix = "STRQ"[j];
switch (state->texgen[i][j]) { switch (state->fixed_function.texgen[i][j]) {
case TEXGEN_DISABLE: case TEXGEN_DISABLE:
mstring_append_fmt(body, "oT%d.%c = texture%d.%c;\n", mstring_append_fmt(body, "oT%d.%c = texture%d.%c;\n",
i, c, i, c); i, c, i, c);
@ -220,7 +220,7 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
/* Apply texture matrices */ /* Apply texture matrices */
for (i = 0; i < NV2A_MAX_TEXTURES; i++) { for (i = 0; i < NV2A_MAX_TEXTURES; i++) {
if (state->texture_matrix_enable[i]) { if (state->fixed_function.texture_matrix_enable[i]) {
mstring_append_fmt(body, mstring_append_fmt(body,
"oT%d = oT%d * texMat%d;\n", "oT%d = oT%d * texMat%d;\n",
i, i, i); i, i, i);
@ -228,7 +228,7 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
} }
/* Lighting */ /* Lighting */
if (!state->lighting) { if (!state->fixed_function.lighting) {
mstring_append(body, " oD0 = diffuse;\n"); mstring_append(body, " oD0 = diffuse;\n");
mstring_append(body, " oD1 = specular;\n"); mstring_append(body, " oD1 = specular;\n");
mstring_append(body, " oB0 = backDiffuse;\n"); mstring_append(body, " oB0 = backDiffuse;\n");
@ -242,47 +242,47 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
static char alpha_source_specular[] = "specular.a"; static char alpha_source_specular[] = "specular.a";
static char alpha_source_material[] = "material_alpha"; static char alpha_source_material[] = "material_alpha";
const char *alpha_source = alpha_source_diffuse; const char *alpha_source = alpha_source_diffuse;
if (state->diffuse_src == MATERIAL_COLOR_SRC_MATERIAL) { if (state->fixed_function.diffuse_src == MATERIAL_COLOR_SRC_MATERIAL) {
mstring_append_fmt(uniforms, "%sfloat material_alpha;\n", u); mstring_append_fmt(uniforms, "%sfloat material_alpha;\n", u);
alpha_source = alpha_source_material; alpha_source = alpha_source_material;
} else if (state->diffuse_src == MATERIAL_COLOR_SRC_SPECULAR) { } else if (state->fixed_function.diffuse_src == MATERIAL_COLOR_SRC_SPECULAR) {
alpha_source = alpha_source_specular; alpha_source = alpha_source_specular;
} }
if (state->ambient_src == MATERIAL_COLOR_SRC_MATERIAL) { if (state->fixed_function.ambient_src == MATERIAL_COLOR_SRC_MATERIAL) {
mstring_append_fmt(body, "oD0 = vec4(sceneAmbientColor, %s);\n", alpha_source); mstring_append_fmt(body, "oD0 = vec4(sceneAmbientColor, %s);\n", alpha_source);
} else if (state->ambient_src == MATERIAL_COLOR_SRC_DIFFUSE) { } else if (state->fixed_function.ambient_src == MATERIAL_COLOR_SRC_DIFFUSE) {
mstring_append_fmt(body, "oD0 = vec4(diffuse.rgb, %s);\n", alpha_source); mstring_append_fmt(body, "oD0 = vec4(diffuse.rgb, %s);\n", alpha_source);
} else if (state->ambient_src == MATERIAL_COLOR_SRC_SPECULAR) { } else if (state->fixed_function.ambient_src == MATERIAL_COLOR_SRC_SPECULAR) {
mstring_append_fmt(body, "oD0 = vec4(specular.rgb, %s);\n", alpha_source); mstring_append_fmt(body, "oD0 = vec4(specular.rgb, %s);\n", alpha_source);
} }
mstring_append(body, "oD0.rgb *= materialEmissionColor.rgb;\n"); mstring_append(body, "oD0.rgb *= materialEmissionColor.rgb;\n");
if (state->emission_src == MATERIAL_COLOR_SRC_MATERIAL) { if (state->fixed_function.emission_src == MATERIAL_COLOR_SRC_MATERIAL) {
mstring_append(body, "oD0.rgb += sceneAmbientColor;\n"); mstring_append(body, "oD0.rgb += sceneAmbientColor;\n");
} else if (state->emission_src == MATERIAL_COLOR_SRC_DIFFUSE) { } else if (state->fixed_function.emission_src == MATERIAL_COLOR_SRC_DIFFUSE) {
mstring_append(body, "oD0.rgb += diffuse.rgb;\n"); mstring_append(body, "oD0.rgb += diffuse.rgb;\n");
} else if (state->emission_src == MATERIAL_COLOR_SRC_SPECULAR) { } else if (state->fixed_function.emission_src == MATERIAL_COLOR_SRC_SPECULAR) {
mstring_append(body, "oD0.rgb += specular.rgb;\n"); mstring_append(body, "oD0.rgb += specular.rgb;\n");
} }
mstring_append(body, "oD1 = vec4(0.0, 0.0, 0.0, specular.a);\n"); mstring_append(body, "oD1 = vec4(0.0, 0.0, 0.0, specular.a);\n");
if (state->local_eye) { if (state->fixed_function.local_eye) {
mstring_append(body, mstring_append(body,
"vec3 VPeye = normalize(eyePosition.xyz / eyePosition.w - tPosition.xyz / tPosition.w);\n" "vec3 VPeye = normalize(eyePosition.xyz / eyePosition.w - tPosition.xyz / tPosition.w);\n"
); );
} }
for (i = 0; i < NV2A_MAX_LIGHTS; i++) { for (i = 0; i < NV2A_MAX_LIGHTS; i++) {
if (state->light[i] == LIGHT_OFF) { if (state->fixed_function.light[i] == LIGHT_OFF) {
continue; continue;
} }
mstring_append_fmt(body, "/* Light %d */ {\n", i); mstring_append_fmt(body, "/* Light %d */ {\n", i);
if (state->light[i] == LIGHT_LOCAL if (state->fixed_function.light[i] == LIGHT_LOCAL
|| state->light[i] == LIGHT_SPOT) { || state->fixed_function.light[i] == LIGHT_SPOT) {
mstring_append_fmt(uniforms, mstring_append_fmt(uniforms,
"%svec3 lightLocalPosition%d;\n" "%svec3 lightLocalPosition%d;\n"
@ -301,11 +301,11 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
" float nDotVP = max(0.0, dot(tNormal, VP));\n" " float nDotVP = max(0.0, dot(tNormal, VP));\n"
" float nDotHV = max(0.0, dot(tNormal, halfVector));\n", " float nDotHV = max(0.0, dot(tNormal, halfVector));\n",
i, i, i, i, i, i, i, i, i, i,
state->local_eye ? "VPeye" : "vec3(0.0, 0.0, 0.0)" state->fixed_function.local_eye ? "VPeye" : "vec3(0.0, 0.0, 0.0)"
); );
} }
switch(state->light[i]) { switch(state->fixed_function.light[i]) {
case LIGHT_INFINITE: case LIGHT_INFINITE:
/* lightLocalRange will be 1e+30 here */ /* lightLocalRange will be 1e+30 here */
@ -320,7 +320,7 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
" vec3 lightDirection = normalize(lightInfiniteDirection%d);\n" " vec3 lightDirection = normalize(lightInfiniteDirection%d);\n"
" float nDotVP = max(0.0, dot(tNormal, lightDirection));\n", " float nDotVP = max(0.0, dot(tNormal, lightDirection));\n",
i); i);
if (state->local_eye) { if (state->fixed_function.local_eye) {
mstring_append(body, mstring_append(body,
" float nDotHV = max(0.0, dot(tNormal, normalize(lightDirection + VPeye)));\n" " float nDotHV = max(0.0, dot(tNormal, normalize(lightDirection + VPeye)));\n"
); );
@ -371,7 +371,7 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
mstring_append(body, mstring_append(body,
" oD0.xyz += lightAmbient;\n"); " oD0.xyz += lightAmbient;\n");
switch (state->diffuse_src) { switch (state->fixed_function.diffuse_src) {
case MATERIAL_COLOR_SRC_MATERIAL: case MATERIAL_COLOR_SRC_MATERIAL:
mstring_append(body, mstring_append(body,
" oD0.xyz += lightDiffuse;\n"); " oD0.xyz += lightDiffuse;\n");
@ -386,7 +386,7 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
break; break;
} }
switch (state->specular_src) { switch (state->fixed_function.specular_src) {
case MATERIAL_COLOR_SRC_MATERIAL: case MATERIAL_COLOR_SRC_MATERIAL:
mstring_append(body, mstring_append(body,
" oD1.xyz += lightSpecular;\n"); " oD1.xyz += lightSpecular;\n");
@ -415,7 +415,7 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
mstring_append(body, " oB1 = vec4(0.0, 0.0, 0.0, 1.0);\n"); mstring_append(body, " oB1 = vec4(0.0, 0.0, 0.0, 1.0);\n");
} else { } else {
if (!state->separate_specular) { if (!state->separate_specular) {
if (state->lighting) { if (state->fixed_function.lighting) {
mstring_append(body, mstring_append(body,
" oD0.xyz += oD1.xyz;\n" " oD0.xyz += oD1.xyz;\n"
" oB0.xyz += oB1.xyz;\n" " oB0.xyz += oB1.xyz;\n"
@ -438,7 +438,7 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
if (state->fog_enable) { if (state->fog_enable) {
/* From: https://www.opengl.org/registry/specs/NV/fog_distance.txt */ /* From: https://www.opengl.org/registry/specs/NV/fog_distance.txt */
switch(state->foggen) { switch(state->fixed_function.foggen) {
case FOGGEN_SPEC_ALPHA: case FOGGEN_SPEC_ALPHA:
/* FIXME: Do we have to clamp here? */ /* FIXME: Do we have to clamp here? */
mstring_append(body, " float fogDistance = clamp(specular.a, 0.0, 1.0);\n"); mstring_append(body, " float fogDistance = clamp(specular.a, 0.0, 1.0);\n");
@ -449,7 +449,7 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
case FOGGEN_PLANAR: case FOGGEN_PLANAR:
case FOGGEN_ABS_PLANAR: case FOGGEN_ABS_PLANAR:
mstring_append(body, " float fogDistance = dot(fogPlane.xyz, tPosition.xyz) + fogPlane.w;\n"); mstring_append(body, " float fogDistance = dot(fogPlane.xyz, tPosition.xyz) + fogPlane.w;\n");
if (state->foggen == FOGGEN_ABS_PLANAR) { if (state->fixed_function.foggen == FOGGEN_ABS_PLANAR) {
mstring_append(body, " fogDistance = abs(fogDistance);\n"); mstring_append(body, " fogDistance = abs(fogDistance);\n");
} }
break; break;
@ -464,7 +464,7 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
} }
/* If skinning is off the composite matrix already includes the MV matrix */ /* If skinning is off the composite matrix already includes the MV matrix */
if (state->skinning == SKINNING_OFF) { if (state->fixed_function.skinning == SKINNING_OFF) {
mstring_append(body, " tPosition = position;\n"); mstring_append(body, " tPosition = position;\n");
} }

View File

@ -25,7 +25,7 @@
#include "qemu/mstring.h" #include "qemu/mstring.h"
#include "hw/xbox/nv2a/pgraph/shaders.h" #include "hw/xbox/nv2a/pgraph/shaders.h"
void pgraph_gen_vsh_ff_glsl(const ShaderState *state, MString *header, void pgraph_gen_vsh_ff_glsl(const VshState *state, MString *header,
MString *body, MString *uniforms); MString *body, MString *uniforms);
#endif #endif

View File

@ -27,7 +27,7 @@
#include "vsh-prog.h" #include "vsh-prog.h"
#include <stdbool.h> #include <stdbool.h>
MString *pgraph_gen_vsh_glsl(const ShaderState *state, bool prefix_outputs) MString *pgraph_gen_vsh_glsl(const VshState *state, bool prefix_outputs)
{ {
int i; int i;
MString *output = mstring_new(); MString *output = mstring_new();
@ -158,23 +158,20 @@ MString *pgraph_gen_vsh_glsl(const ShaderState *state, bool prefix_outputs)
} }
if (state->fixed_function) { if (state->is_fixed_function) {
pgraph_gen_vsh_ff_glsl(state, header, body, uniforms); pgraph_gen_vsh_ff_glsl(state, header, body, uniforms);
} else if (state->vertex_program) {
pgraph_gen_vsh_prog_glsl(VSH_VERSION_XVS,
(uint32_t *)state->program_data,
state->program_length,
state->vulkan, header, body);
} else { } else {
assert(false); pgraph_gen_vsh_prog_glsl(VSH_VERSION_XVS,
(uint32_t *)state->programmable.program_data,
state->programmable.program_length,
state->vulkan, header, body);
} }
/* Fog */ /* Fog */
if (state->fog_enable) { if (state->fog_enable) {
if (state->vertex_program) { if (!state->is_fixed_function) {
/* FIXME: Does foggen do something here? Let's do some tracking.. /* FIXME: Does foggen do something here? Let's do some tracking..
* *
* "RollerCoaster Tycoon" has * "RollerCoaster Tycoon" has

View File

@ -28,6 +28,6 @@
// FIXME: Move to struct // FIXME: Move to struct
#define VSH_UBO_BINDING 0 #define VSH_UBO_BINDING 0
MString *pgraph_gen_vsh_glsl(const ShaderState *state, bool prefix_outputs); MString *pgraph_gen_vsh_glsl(const VshState *state, bool prefix_outputs);
#endif #endif

View File

@ -67,15 +67,15 @@ ShaderState pgraph_get_shader_state(PGRAPHState *pg)
// We will hash it, so make sure any padding is zeroed // We will hash it, so make sure any padding is zeroed
memset(&state, 0, sizeof(ShaderState)); memset(&state, 0, sizeof(ShaderState));
state.surface_scale_factor = pg->surface_scale_factor; state.vsh.surface_scale_factor = pg->surface_scale_factor;
state.compressed_attrs = pg->compressed_attrs; state.vsh.compressed_attrs = pg->compressed_attrs;
state.uniform_attrs = pg->uniform_attrs; state.vsh.uniform_attrs = pg->uniform_attrs;
state.swizzle_attrs = pg->swizzle_attrs; state.vsh.swizzle_attrs = pg->swizzle_attrs;
/* register combiner stuff */ /* register combiner stuff */
state.psh.window_clip_exclusive = state.psh.window_clip_exclusive = pgraph_reg_r(pg, NV_PGRAPH_SETUPRASTER) &
pgraph_reg_r(pg, NV_PGRAPH_SETUPRASTER) & NV_PGRAPH_SETUPRASTER_WINDOWCLIPTYPE; NV_PGRAPH_SETUPRASTER_WINDOWCLIPTYPE;
state.psh.combiner_control = pgraph_reg_r(pg, NV_PGRAPH_COMBINECTL); state.psh.combiner_control = pgraph_reg_r(pg, NV_PGRAPH_COMBINECTL);
state.psh.shader_stage_program = pgraph_reg_r(pg, NV_PGRAPH_SHADERPROG); state.psh.shader_stage_program = pgraph_reg_r(pg, NV_PGRAPH_SHADERPROG);
state.psh.other_stage_input = pgraph_reg_r(pg, NV_PGRAPH_SHADERCTL); state.psh.other_stage_input = pgraph_reg_r(pg, NV_PGRAPH_SHADERCTL);
@ -93,35 +93,41 @@ ShaderState pgraph_get_shader_state(PGRAPHState *pg)
state.psh.shadow_depth_func = (enum PshShadowDepthFunc)GET_MASK( state.psh.shadow_depth_func = (enum PshShadowDepthFunc)GET_MASK(
pgraph_reg_r(pg, NV_PGRAPH_SHADOWCTL), NV_PGRAPH_SHADOWCTL_SHADOW_ZFUNC); pgraph_reg_r(pg, NV_PGRAPH_SHADOWCTL), NV_PGRAPH_SHADOWCTL_SHADOW_ZFUNC);
state.fixed_function = fixed_function; state.vsh.is_fixed_function = fixed_function;
state.specular_enable = GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), state.vsh.specular_enable = GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CSV0_C),
NV_PGRAPH_CSV0_C_SPECULAR_ENABLE); NV_PGRAPH_CSV0_C_SPECULAR_ENABLE);
/* fixed function stuff */ /* fixed function stuff */
if (fixed_function) { if (fixed_function) {
state.skinning = (enum VshSkinning)GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CSV0_D), state.vsh.fixed_function.skinning = (enum VshSkinning)GET_MASK(
NV_PGRAPH_CSV0_D_SKIN); pgraph_reg_r(pg, NV_PGRAPH_CSV0_D), NV_PGRAPH_CSV0_D_SKIN);
state.lighting = state.vsh.fixed_function.lighting = GET_MASK(
GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_LIGHTING); pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_LIGHTING);
state.normalization = state.vsh.fixed_function.normalization =
pgraph_reg_r(pg, NV_PGRAPH_CSV0_C) & NV_PGRAPH_CSV0_C_NORMALIZATION_ENABLE; pgraph_reg_r(pg, NV_PGRAPH_CSV0_C) &
NV_PGRAPH_CSV0_C_NORMALIZATION_ENABLE;
/* color material */ /* color material */
state.emission_src = (enum MaterialColorSource)GET_MASK( state.vsh.fixed_function.emission_src =
pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_EMISSION); (enum MaterialColorSource)GET_MASK(
state.ambient_src = (enum MaterialColorSource)GET_MASK( pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_EMISSION);
pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_AMBIENT); state.vsh.fixed_function.ambient_src =
state.diffuse_src = (enum MaterialColorSource)GET_MASK( (enum MaterialColorSource)GET_MASK(
pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_DIFFUSE); pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_AMBIENT);
state.specular_src = (enum MaterialColorSource)GET_MASK( state.vsh.fixed_function.diffuse_src =
pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_SPECULAR); (enum MaterialColorSource)GET_MASK(
pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_DIFFUSE);
state.vsh.fixed_function.specular_src =
(enum MaterialColorSource)GET_MASK(
pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_SPECULAR);
state.local_eye = GET_MASK( state.vsh.fixed_function.local_eye = GET_MASK(
pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_LOCALEYE); pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_LOCALEYE);
/* Texture matrices */ /* Texture matrices */
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
state.texture_matrix_enable[i] = pg->texture_matrix_enable[i]; state.vsh.fixed_function.texture_matrix_enable[i] =
pg->texture_matrix_enable[i];
} }
/* Texgen */ /* Texgen */
@ -134,62 +140,62 @@ ShaderState pgraph_get_shader_state(PGRAPHState *pg)
(i % 2) ? NV_PGRAPH_CSV1_A_T1_R : NV_PGRAPH_CSV1_A_T0_R, (i % 2) ? NV_PGRAPH_CSV1_A_T1_R : NV_PGRAPH_CSV1_A_T0_R,
(i % 2) ? NV_PGRAPH_CSV1_A_T1_Q : NV_PGRAPH_CSV1_A_T0_Q (i % 2) ? NV_PGRAPH_CSV1_A_T1_Q : NV_PGRAPH_CSV1_A_T0_Q
}; };
state.texgen[i][j] = state.vsh.fixed_function.texgen[i][j] =
(enum VshTexgen)GET_MASK(pgraph_reg_r(pg, reg), masks[j]); (enum VshTexgen)GET_MASK(pgraph_reg_r(pg, reg), masks[j]);
} }
} }
} }
state.separate_specular = GET_MASK( state.vsh.separate_specular = GET_MASK(
pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_SEPARATE_SPECULAR); pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_SEPARATE_SPECULAR);
state.ignore_specular_alpha = !GET_MASK( state.vsh.ignore_specular_alpha = !GET_MASK(
pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_ALPHA_FROM_MATERIAL_SPECULAR); pgraph_reg_r(pg, NV_PGRAPH_CSV0_C), NV_PGRAPH_CSV0_C_ALPHA_FROM_MATERIAL_SPECULAR);
state.specular_power = pg->specular_power; state.vsh.specular_power = pg->specular_power;
state.specular_power_back = pg->specular_power_back; state.vsh.specular_power_back = pg->specular_power_back;
/* vertex program stuff */ /* vertex program stuff */
state.vertex_program = vertex_program, state.vsh.z_perspective = pgraph_reg_r(pg, NV_PGRAPH_CONTROL_0) &
state.z_perspective = pgraph_reg_r(pg, NV_PGRAPH_CONTROL_0) &
NV_PGRAPH_CONTROL_0_Z_PERSPECTIVE_ENABLE; NV_PGRAPH_CONTROL_0_Z_PERSPECTIVE_ENABLE;
state.psh.z_perspective = state.z_perspective; state.psh.z_perspective = state.vsh.z_perspective;
state.point_params_enable = GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CSV0_D), state.vsh.point_params_enable = GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CSV0_D),
NV_PGRAPH_CSV0_D_POINTPARAMSENABLE); NV_PGRAPH_CSV0_D_POINTPARAMSENABLE);
state.point_size = state.vsh.point_size =
GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_POINTSIZE), NV097_SET_POINT_SIZE_V) / 8.0f; GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_POINTSIZE), NV097_SET_POINT_SIZE_V) / 8.0f;
if (state.point_params_enable) { if (state.vsh.point_params_enable) {
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
state.point_params[i] = pg->point_params[i]; state.vsh.point_params[i] = pg->point_params[i];
} }
} }
/* geometry shader stuff */ /* geometry shader stuff */
state.primitive_mode = (enum ShaderPrimitiveMode)pg->primitive_mode; state.vsh.primitive_mode = (enum ShaderPrimitiveMode)pg->primitive_mode;
state.polygon_front_mode = (enum ShaderPolygonMode)GET_MASK( state.vsh.polygon_front_mode = (enum ShaderPolygonMode)GET_MASK(
pgraph_reg_r(pg, NV_PGRAPH_SETUPRASTER), NV_PGRAPH_SETUPRASTER_FRONTFACEMODE); pgraph_reg_r(pg, NV_PGRAPH_SETUPRASTER), NV_PGRAPH_SETUPRASTER_FRONTFACEMODE);
state.polygon_back_mode = (enum ShaderPolygonMode)GET_MASK( state.vsh.polygon_back_mode = (enum ShaderPolygonMode)GET_MASK(
pgraph_reg_r(pg, NV_PGRAPH_SETUPRASTER), NV_PGRAPH_SETUPRASTER_BACKFACEMODE); pgraph_reg_r(pg, NV_PGRAPH_SETUPRASTER), NV_PGRAPH_SETUPRASTER_BACKFACEMODE);
state.smooth_shading = GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CONTROL_3), state.vsh.smooth_shading = GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CONTROL_3),
NV_PGRAPH_CONTROL_3_SHADEMODE) == NV_PGRAPH_CONTROL_3_SHADEMODE) ==
NV_PGRAPH_CONTROL_3_SHADEMODE_SMOOTH; NV_PGRAPH_CONTROL_3_SHADEMODE_SMOOTH;
state.psh.smooth_shading = state.smooth_shading; state.psh.smooth_shading = state.vsh.smooth_shading;
state.psh.depth_clipping = GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_ZCOMPRESSOCCLUDE), state.psh.depth_clipping = GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_ZCOMPRESSOCCLUDE),
NV_PGRAPH_ZCOMPRESSOCCLUDE_ZCLAMP_EN) == NV_PGRAPH_ZCOMPRESSOCCLUDE_ZCLAMP_EN) ==
NV_PGRAPH_ZCOMPRESSOCCLUDE_ZCLAMP_EN_CULL; NV_PGRAPH_ZCOMPRESSOCCLUDE_ZCLAMP_EN_CULL;
state.program_length = 0;
if (vertex_program) { if (vertex_program) {
// copy in vertex program tokens // copy in vertex program tokens
state.vsh.programmable.program_length = 0;
for (int i = program_start; i < NV2A_MAX_TRANSFORM_PROGRAM_LENGTH; for (int i = program_start; i < NV2A_MAX_TRANSFORM_PROGRAM_LENGTH;
i++) { i++) {
uint32_t *cur_token = (uint32_t *)&pg->program_data[i]; uint32_t *cur_token = (uint32_t *)&pg->program_data[i];
memcpy(&state.program_data[state.program_length], cur_token, memcpy(&state.vsh.programmable
VSH_TOKEN_SIZE * sizeof(uint32_t)); .program_data[state.vsh.programmable.program_length],
state.program_length++; cur_token, VSH_TOKEN_SIZE * sizeof(uint32_t));
state.vsh.programmable.program_length++;
if (vsh_get_field(cur_token, FLD_FINAL)) { if (vsh_get_field(cur_token, FLD_FINAL)) {
break; break;
@ -198,35 +204,40 @@ ShaderState pgraph_get_shader_state(PGRAPHState *pg)
} }
/* Fog */ /* Fog */
state.fog_enable = state.vsh.fog_enable =
pgraph_reg_r(pg, NV_PGRAPH_CONTROL_3) & NV_PGRAPH_CONTROL_3_FOGENABLE; pgraph_reg_r(pg, NV_PGRAPH_CONTROL_3) & NV_PGRAPH_CONTROL_3_FOGENABLE;
if (state.fog_enable) { if (state.vsh.fog_enable) {
/*FIXME: Use CSV0_D? */ /*FIXME: Use CSV0_D? */
state.fog_mode = (enum VshFogMode)GET_MASK( state.vsh.fog_mode = (enum VshFogMode)GET_MASK(
pgraph_reg_r(pg, NV_PGRAPH_CONTROL_3), NV_PGRAPH_CONTROL_3_FOG_MODE); pgraph_reg_r(pg, NV_PGRAPH_CONTROL_3), NV_PGRAPH_CONTROL_3_FOG_MODE);
state.foggen = (enum VshFoggen)GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CSV0_D), state.vsh.fixed_function.foggen = (enum VshFoggen)GET_MASK(
NV_PGRAPH_CSV0_D_FOGGENMODE); pgraph_reg_r(pg, NV_PGRAPH_CSV0_D), NV_PGRAPH_CSV0_D_FOGGENMODE);
} else { } else {
/* FIXME: Do we still pass the fogmode? */ /* FIXME: Do we still pass the fogmode? */
state.fog_mode = (enum VshFogMode)0; state.vsh.fog_mode = (enum VshFogMode)0;
state.foggen = (enum VshFoggen)0; state.vsh.fixed_function.foggen = (enum VshFoggen)0;
} }
/* Lighting */ /* Lighting */
if (state.lighting) { if (state.vsh.fixed_function.lighting) {
for (int i = 0; i < NV2A_MAX_LIGHTS; i++) { for (int i = 0; i < NV2A_MAX_LIGHTS; i++) {
state.light[i] = (enum VshLight)GET_MASK( state.vsh.fixed_function.light[i] =
pgraph_reg_r(pg, NV_PGRAPH_CSV0_D), NV_PGRAPH_CSV0_D_LIGHT0 << (i * 2)); (enum VshLight)GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CSV0_D),
NV_PGRAPH_CSV0_D_LIGHT0 << (i * 2));
} }
} }
/* Copy content of enabled combiner stages */ /* Copy content of enabled combiner stages */
int num_stages = pgraph_reg_r(pg, NV_PGRAPH_COMBINECTL) & 0xFF; int num_stages = pgraph_reg_r(pg, NV_PGRAPH_COMBINECTL) & 0xFF;
for (int i = 0; i < num_stages; i++) { for (int i = 0; i < num_stages; i++) {
state.psh.rgb_inputs[i] = pgraph_reg_r(pg, NV_PGRAPH_COMBINECOLORI0 + i * 4); state.psh.rgb_inputs[i] =
state.psh.rgb_outputs[i] = pgraph_reg_r(pg, NV_PGRAPH_COMBINECOLORO0 + i * 4); pgraph_reg_r(pg, NV_PGRAPH_COMBINECOLORI0 + i * 4);
state.psh.alpha_inputs[i] = pgraph_reg_r(pg, NV_PGRAPH_COMBINEALPHAI0 + i * 4); state.psh.rgb_outputs[i] =
state.psh.alpha_outputs[i] = pgraph_reg_r(pg, NV_PGRAPH_COMBINEALPHAO0 + i * 4); pgraph_reg_r(pg, NV_PGRAPH_COMBINECOLORO0 + i * 4);
state.psh.alpha_inputs[i] =
pgraph_reg_r(pg, NV_PGRAPH_COMBINEALPHAI0 + i * 4);
state.psh.alpha_outputs[i] =
pgraph_reg_r(pg, NV_PGRAPH_COMBINEALPHAO0 + i * 4);
// constant_0[i] = pgraph_reg_r(pg, NV_PGRAPH_COMBINEFACTOR0 + i * 4); // constant_0[i] = pgraph_reg_r(pg, NV_PGRAPH_COMBINEFACTOR0 + i * 4);
// constant_1[i] = pgraph_reg_r(pg, NV_PGRAPH_COMBINEFACTOR1 + i * 4); // constant_1[i] = pgraph_reg_r(pg, NV_PGRAPH_COMBINEFACTOR1 + i * 4);
} }

View File

@ -22,91 +22,13 @@
#define HW_XBOX_NV2A_PGRAPH_SHADERS_H #define HW_XBOX_NV2A_PGRAPH_SHADERS_H
#include <stdint.h> #include <stdint.h>
#include "hw/xbox/nv2a/nv2a_regs.h"
#include "vsh.h" #include "vsh.h"
#include "psh.h" #include "psh.h"
enum ShaderPrimitiveMode {
PRIM_TYPE_INVALID,
PRIM_TYPE_POINTS,
PRIM_TYPE_LINES,
PRIM_TYPE_LINE_LOOP,
PRIM_TYPE_LINE_STRIP,
PRIM_TYPE_TRIANGLES,
PRIM_TYPE_TRIANGLE_STRIP,
PRIM_TYPE_TRIANGLE_FAN,
PRIM_TYPE_QUADS,
PRIM_TYPE_QUAD_STRIP,
PRIM_TYPE_POLYGON,
};
enum ShaderPolygonMode {
POLY_MODE_FILL,
POLY_MODE_POINT,
POLY_MODE_LINE,
};
enum MaterialColorSource {
MATERIAL_COLOR_SRC_MATERIAL,
MATERIAL_COLOR_SRC_DIFFUSE,
MATERIAL_COLOR_SRC_SPECULAR,
};
typedef struct ShaderState { typedef struct ShaderState {
bool vulkan; VshState vsh;
bool use_push_constants_for_uniform_attrs;
unsigned int surface_scale_factor;
PshState psh; PshState psh;
uint16_t compressed_attrs;
uint16_t uniform_attrs;
uint16_t swizzle_attrs;
bool texture_matrix_enable[4];
enum VshTexgen texgen[4][4];
bool fog_enable;
enum VshFoggen foggen;
enum VshFogMode fog_mode;
enum VshSkinning skinning;
bool normalization;
enum MaterialColorSource emission_src;
enum MaterialColorSource ambient_src;
enum MaterialColorSource diffuse_src;
enum MaterialColorSource specular_src;
bool separate_specular;
bool ignore_specular_alpha;
bool local_eye;
float specular_power;
float specular_power_back;
bool lighting;
enum VshLight light[NV2A_MAX_LIGHTS];
bool fixed_function;
bool specular_enable;
/* vertex program */
bool vertex_program;
uint32_t program_data[NV2A_MAX_TRANSFORM_PROGRAM_LENGTH][VSH_TOKEN_SIZE];
int program_length;
bool z_perspective;
/* primitive format for geometry shader */
enum ShaderPolygonMode polygon_front_mode;
enum ShaderPolygonMode polygon_back_mode;
enum ShaderPrimitiveMode primitive_mode;
bool point_params_enable;
float point_size;
float point_params[8];
bool smooth_shading;
} ShaderState; } ShaderState;
typedef struct PGRAPHState PGRAPHState; typedef struct PGRAPHState PGRAPHState;

View File

@ -51,8 +51,8 @@ static VkPrimitiveTopology get_primitive_topology(PGRAPHState *pg)
{ {
PGRAPHVkState *r = pg->vk_renderer_state; PGRAPHVkState *r = pg->vk_renderer_state;
int polygon_mode = r->shader_binding->state.polygon_front_mode; int polygon_mode = r->shader_binding->state.vsh.polygon_front_mode;
int primitive_mode = r->shader_binding->state.primitive_mode; int primitive_mode = r->shader_binding->state.vsh.primitive_mode;
if (polygon_mode == POLY_MODE_POINT) { if (polygon_mode == POLY_MODE_POINT) {
return VK_PRIMITIVE_TOPOLOGY_POINT_LIST; return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
@ -816,7 +816,7 @@ static void create_pipeline(PGRAPHState *pg)
.depthClampEnable = VK_TRUE, .depthClampEnable = VK_TRUE,
.rasterizerDiscardEnable = VK_FALSE, .rasterizerDiscardEnable = VK_FALSE,
.polygonMode = pgraph_polygon_mode_vk_map[r->shader_binding->state .polygonMode = pgraph_polygon_mode_vk_map[r->shader_binding->state
.polygon_front_mode], .vsh.polygon_front_mode],
.lineWidth = 1.0f, .lineWidth = 1.0f,
.frontFace = (pgraph_reg_r(pg, NV_PGRAPH_SETUPRASTER) & .frontFace = (pgraph_reg_r(pg, NV_PGRAPH_SETUPRASTER) &
NV_PGRAPH_SETUPRASTER_FRONTFACE) ? NV_PGRAPH_SETUPRASTER_FRONTFACE) ?
@ -951,11 +951,11 @@ static void create_pipeline(PGRAPHState *pg)
int num_dynamic_states = 2; int num_dynamic_states = 2;
snode->has_dynamic_line_width = snode->has_dynamic_line_width =
(r->enabled_physical_device_features.wideLines == VK_TRUE) (r->enabled_physical_device_features.wideLines == VK_TRUE) &&
&& (r->shader_binding->state.polygon_front_mode == POLY_MODE_LINE || (r->shader_binding->state.vsh.polygon_front_mode == POLY_MODE_LINE ||
r->shader_binding->state.primitive_mode == PRIM_TYPE_LINES || r->shader_binding->state.vsh.primitive_mode == PRIM_TYPE_LINES ||
r->shader_binding->state.primitive_mode == PRIM_TYPE_LINE_LOOP || r->shader_binding->state.vsh.primitive_mode == PRIM_TYPE_LINE_LOOP ||
r->shader_binding->state.primitive_mode == PRIM_TYPE_LINE_STRIP); r->shader_binding->state.vsh.primitive_mode == PRIM_TYPE_LINE_STRIP);
if (snode->has_dynamic_line_width) { if (snode->has_dynamic_line_width) {
dynamic_states[num_dynamic_states++] = VK_DYNAMIC_STATE_LINE_WIDTH; dynamic_states[num_dynamic_states++] = VK_DYNAMIC_STATE_LINE_WIDTH;
} }
@ -1012,9 +1012,9 @@ static void create_pipeline(PGRAPHState *pg)
}; };
VkPushConstantRange push_constant_range; VkPushConstantRange push_constant_range;
if (r->shader_binding->state.use_push_constants_for_uniform_attrs) { if (r->shader_binding->state.vsh.use_push_constants_for_uniform_attrs) {
int num_uniform_attributes = int num_uniform_attributes =
__builtin_popcount(r->shader_binding->state.uniform_attrs); __builtin_popcount(r->shader_binding->state.vsh.uniform_attrs);
if (num_uniform_attributes) { if (num_uniform_attributes) {
push_constant_range = (VkPushConstantRange){ push_constant_range = (VkPushConstantRange){
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT, .stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
@ -1067,7 +1067,7 @@ static void push_vertex_attr_values(PGRAPHState *pg)
{ {
PGRAPHVkState *r = pg->vk_renderer_state; PGRAPHVkState *r = pg->vk_renderer_state;
if (!r->shader_binding->state.use_push_constants_for_uniform_attrs) { if (!r->shader_binding->state.vsh.use_push_constants_for_uniform_attrs) {
return; return;
} }
@ -1076,8 +1076,8 @@ static void push_vertex_attr_values(PGRAPHState *pg)
float values[NV2A_VERTEXSHADER_ATTRIBUTES][4]; float values[NV2A_VERTEXSHADER_ATTRIBUTES][4];
int num_uniform_attrs = 0; int num_uniform_attrs = 0;
pgraph_get_inline_values(pg, r->shader_binding->state.uniform_attrs, values, pgraph_get_inline_values(pg, r->shader_binding->state.vsh.uniform_attrs,
&num_uniform_attrs); values, &num_uniform_attrs);
if (num_uniform_attrs > 0) { if (num_uniform_attrs > 0) {
vkCmdPushConstants(r->command_buffer, r->pipeline_binding->layout, vkCmdPushConstants(r->command_buffer, r->pipeline_binding->layout,

View File

@ -405,8 +405,8 @@ static ShaderBinding *gen_shaders(PGRAPHState *pg, ShaderState *state)
setlocale(LC_NUMERIC, "C"); setlocale(LC_NUMERIC, "C");
MString *geometry_shader_code = pgraph_gen_geom_glsl( MString *geometry_shader_code = pgraph_gen_geom_glsl(
state->polygon_front_mode, state->polygon_back_mode, state->vsh.polygon_front_mode, state->vsh.polygon_back_mode,
state->primitive_mode, state->smooth_shading, true); state->vsh.primitive_mode, state->vsh.smooth_shading, true);
if (geometry_shader_code) { if (geometry_shader_code) {
NV2A_VK_DPRINTF("geometry shader: \n%s", NV2A_VK_DPRINTF("geometry shader: \n%s",
mstring_get_str(geometry_shader_code)); mstring_get_str(geometry_shader_code));
@ -419,7 +419,7 @@ static ShaderBinding *gen_shaders(PGRAPHState *pg, ShaderState *state)
} }
MString *vertex_shader_code = MString *vertex_shader_code =
pgraph_gen_vsh_glsl(state, geometry_shader_code != NULL); pgraph_gen_vsh_glsl(&state->vsh, geometry_shader_code != NULL);
NV2A_VK_DPRINTF("vertex shader: \n%s", NV2A_VK_DPRINTF("vertex shader: \n%s",
mstring_get_str(vertex_shader_code)); mstring_get_str(vertex_shader_code));
snode->vertex = pgraph_vk_create_shader_module_from_glsl( snode->vertex = pgraph_vk_create_shader_module_from_glsl(
@ -453,7 +453,7 @@ static void update_uniform_attr_values(PGRAPHState *pg, ShaderBinding *binding)
float values[NV2A_VERTEXSHADER_ATTRIBUTES][4]; float values[NV2A_VERTEXSHADER_ATTRIBUTES][4];
int num_uniform_attrs = 0; int num_uniform_attrs = 0;
pgraph_get_inline_values(pg, binding->state.uniform_attrs, values, pgraph_get_inline_values(pg, binding->state.vsh.uniform_attrs, values,
&num_uniform_attrs); &num_uniform_attrs);
if (num_uniform_attrs > 0) { if (num_uniform_attrs > 0) {
@ -463,9 +463,7 @@ static void update_uniform_attr_values(PGRAPHState *pg, ShaderBinding *binding)
} }
// FIXME: Move to common // FIXME: Move to common
static void shader_update_constants(PGRAPHState *pg, ShaderBinding *binding, static void shader_update_constants(PGRAPHState *pg, ShaderBinding *binding)
bool binding_changed, bool vertex_program,
bool fixed_function)
{ {
ShaderState *state = &binding->state; ShaderState *state = &binding->state;
@ -548,7 +546,10 @@ static void shader_update_constants(PGRAPHState *pg, ShaderBinding *binding,
if (loc != -1) { if (loc != -1) {
assert(pg->vk_renderer_state->texture_bindings[i] != NULL); assert(pg->vk_renderer_state->texture_bindings[i] != NULL);
float scale = pg->vk_renderer_state->texture_bindings[i]->key.scale; float scale = pg->vk_renderer_state->texture_bindings[i]->key.scale;
BasicColorFormatInfo f_basic = kelvin_color_format_info_map[pg->vk_renderer_state->texture_bindings[i]->key.state.color_format]; BasicColorFormatInfo f_basic =
kelvin_color_format_info_map[pg->vk_renderer_state
->texture_bindings[i]
->key.state.color_format];
if (!f_basic.linear) { if (!f_basic.linear) {
scale = 1.0; scale = 1.0;
} }
@ -592,7 +593,7 @@ static void shader_update_constants(PGRAPHState *pg, ShaderBinding *binding,
assert(0); assert(0);
} }
if (fixed_function) { if (binding->state.vsh.is_fixed_function) {
/* update lighting constants */ /* update lighting constants */
struct { struct {
uint32_t *v; uint32_t *v;
@ -733,7 +734,8 @@ static void shader_update_constants(PGRAPHState *pg, ShaderBinding *binding,
pg->material_alpha); pg->material_alpha);
} }
if (!state->use_push_constants_for_uniform_attrs && state->uniform_attrs) { if (!state->vsh.use_push_constants_for_uniform_attrs &&
state->vsh.uniform_attrs) {
update_uniform_attr_values(pg, binding); update_uniform_attr_values(pg, binding);
} }
} }
@ -786,22 +788,29 @@ static bool check_shaders_dirty(PGRAPHState *pg)
} }
ShaderState *state = &r->shader_binding->state; ShaderState *state = &r->shader_binding->state;
if (pg->uniform_attrs != state->uniform_attrs || if (pg->uniform_attrs != state->vsh.uniform_attrs ||
pg->swizzle_attrs != state->swizzle_attrs || pg->swizzle_attrs != state->vsh.swizzle_attrs ||
pg->compressed_attrs != state->compressed_attrs || pg->compressed_attrs != state->vsh.compressed_attrs ||
pg->primitive_mode != state->primitive_mode || pg->primitive_mode != state->vsh.primitive_mode ||
pg->surface_scale_factor != state->surface_scale_factor) { pg->surface_scale_factor != state->vsh.surface_scale_factor) {
return true; return true;
} }
// Textures // Textures
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
if (pg->texture_matrix_enable[i] != pg->vk_renderer_state->shader_binding->state.texture_matrix_enable[i] || if (pgraph_is_reg_dirty(pg, NV_PGRAPH_TEXCTL0_0 + i * 4) ||
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_TEXFILTER0 + i * 4) ||
pgraph_is_reg_dirty(pg, NV_PGRAPH_TEXFMT0 + i * 4)) { pgraph_is_reg_dirty(pg, NV_PGRAPH_TEXFMT0 + i * 4)) {
return true; 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); nv2a_profile_inc_counter(NV2A_PROF_SHADER_BIND_NOTDIRTY);
@ -821,11 +830,11 @@ void pgraph_vk_bind_shaders(PGRAPHState *pg)
ShaderState new_state; ShaderState new_state;
memset(&new_state, 0, sizeof(ShaderState)); memset(&new_state, 0, sizeof(ShaderState));
new_state = pgraph_get_shader_state(pg); new_state = pgraph_get_shader_state(pg);
new_state.vulkan = true; new_state.vsh.vulkan = true;
new_state.psh.vulkan = true; new_state.vsh.use_push_constants_for_uniform_attrs =
new_state.use_push_constants_for_uniform_attrs =
(r->device_props.limits.maxPushConstantsSize >= (r->device_props.limits.maxPushConstantsSize >=
MAX_UNIFORM_ATTR_VALUES_SIZE); MAX_UNIFORM_ATTR_VALUES_SIZE);
new_state.psh.vulkan = true;
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_binding = gen_shaders(pg, &new_state);
@ -849,9 +858,7 @@ void pgraph_vk_update_shader_uniforms(PGRAPHState *pg)
ShaderBinding *binding = r->shader_binding; ShaderBinding *binding = r->shader_binding;
ShaderUniformLayout *layouts[] = { &binding->vertex->uniforms, ShaderUniformLayout *layouts[] = { &binding->vertex->uniforms,
&binding->fragment->uniforms }; &binding->fragment->uniforms };
shader_update_constants(pg, r->shader_binding, true, shader_update_constants(pg, r->shader_binding);
r->shader_binding->state.vertex_program,
r->shader_binding->state.fixed_function);
for (int i = 0; i < ARRAY_SIZE(layouts); i++) { for (int i = 0; i < ARRAY_SIZE(layouts); i++) {
uint64_t hash = fast_hash(layouts[i]->allocation, layouts[i]->total_size); uint64_t hash = fast_hash(layouts[i]->allocation, layouts[i]->total_size);

View File

@ -20,8 +20,8 @@
#ifndef HW_NV2A_VSH_H #ifndef HW_NV2A_VSH_H
#define HW_NV2A_VSH_H #define HW_NV2A_VSH_H
#include <stdbool.h> #include "qemu/osdep.h"
#include "qemu/mstring.h" #include "hw/xbox/nv2a/nv2a_regs.h"
enum VshLight { enum VshLight {
LIGHT_OFF, LIGHT_OFF,
@ -128,4 +128,82 @@ typedef enum {
uint8_t vsh_get_field(const uint32_t *shader_token, VshFieldName field_name); uint8_t vsh_get_field(const uint32_t *shader_token, VshFieldName field_name);
enum ShaderPrimitiveMode {
PRIM_TYPE_INVALID,
PRIM_TYPE_POINTS,
PRIM_TYPE_LINES,
PRIM_TYPE_LINE_LOOP,
PRIM_TYPE_LINE_STRIP,
PRIM_TYPE_TRIANGLES,
PRIM_TYPE_TRIANGLE_STRIP,
PRIM_TYPE_TRIANGLE_FAN,
PRIM_TYPE_QUADS,
PRIM_TYPE_QUAD_STRIP,
PRIM_TYPE_POLYGON,
};
enum ShaderPolygonMode {
POLY_MODE_FILL,
POLY_MODE_POINT,
POLY_MODE_LINE,
};
enum MaterialColorSource {
MATERIAL_COLOR_SRC_MATERIAL,
MATERIAL_COLOR_SRC_DIFFUSE,
MATERIAL_COLOR_SRC_SPECULAR,
};
typedef struct {
bool vulkan;
bool use_push_constants_for_uniform_attrs;
unsigned int surface_scale_factor; // FIXME: Remove
uint16_t compressed_attrs;
uint16_t uniform_attrs;
uint16_t swizzle_attrs;
/* primitive format for geometry shader */
enum ShaderPolygonMode polygon_front_mode;
enum ShaderPolygonMode polygon_back_mode;
enum ShaderPrimitiveMode primitive_mode;
bool is_fixed_function;
struct {
bool normalization;
bool texture_matrix_enable[4];
enum VshTexgen texgen[4][4];
enum VshFoggen foggen;
enum VshSkinning skinning;
bool lighting;
enum VshLight light[NV2A_MAX_LIGHTS];
enum MaterialColorSource emission_src;
enum MaterialColorSource ambient_src;
enum MaterialColorSource diffuse_src;
enum MaterialColorSource specular_src;
bool local_eye;
} fixed_function;
struct {
uint32_t program_data[NV2A_MAX_TRANSFORM_PROGRAM_LENGTH]
[VSH_TOKEN_SIZE];
int program_length;
} programmable;
bool fog_enable;
enum VshFogMode fog_mode;
bool specular_enable;
bool separate_specular;
bool ignore_specular_alpha;
float specular_power;
float specular_power_back;
bool z_perspective;
bool point_params_enable;
float point_size;
float point_params[8];
bool smooth_shading;
} VshState;
#endif #endif