From 8d274e5f9a9dbe777ffba6a8b3d269adbf682690 Mon Sep 17 00:00:00 2001 From: Erik Abair Date: Mon, 11 Jul 2022 07:18:50 -0700 Subject: [PATCH] nv2a: Match inv_w qualifier to attribute qualifier Calculates both interpolated and flat shaded inv_w so that the appropriate value may be used when undoing the perspective divide in the pixel shader. --- hw/xbox/nv2a/psh.c | 15 +++++++++++---- hw/xbox/nv2a/shaders.c | 25 +++++++++++++++++-------- hw/xbox/nv2a/shaders_common.h | 3 ++- hw/xbox/nv2a/vsh.c | 1 + 4 files changed, 31 insertions(+), 13 deletions(-) diff --git a/hw/xbox/nv2a/psh.c b/hw/xbox/nv2a/psh.c index 1bd09b571a..e80a97d294 100644 --- a/hw/xbox/nv2a/psh.c +++ b/hw/xbox/nv2a/psh.c @@ -801,10 +801,17 @@ static MString* psh_convert(struct PixelShader *ps) /* calculate perspective-correct inputs */ MString *vars = mstring_new(); - mstring_append(vars, "vec4 pD0 = vtxD0 / vtx_inv_w;\n"); - mstring_append(vars, "vec4 pD1 = vtxD1 / vtx_inv_w;\n"); - mstring_append(vars, "vec4 pB0 = vtxB0 / vtx_inv_w;\n"); - mstring_append(vars, "vec4 pB1 = vtxB1 / vtx_inv_w;\n"); + if (ps->state.smooth_shading) { + mstring_append(vars, "vec4 pD0 = vtxD0 / vtx_inv_w;\n"); + mstring_append(vars, "vec4 pD1 = vtxD1 / vtx_inv_w;\n"); + mstring_append(vars, "vec4 pB0 = vtxB0 / vtx_inv_w;\n"); + mstring_append(vars, "vec4 pB1 = vtxB1 / vtx_inv_w;\n"); + } else { + mstring_append(vars, "vec4 pD0 = vtxD0 / vtx_inv_w_flat;\n"); + mstring_append(vars, "vec4 pD1 = vtxD1 / vtx_inv_w_flat;\n"); + mstring_append(vars, "vec4 pB0 = vtxB0 / vtx_inv_w_flat;\n"); + mstring_append(vars, "vec4 pB1 = vtxB1 / vtx_inv_w_flat;\n"); + } mstring_append(vars, "vec4 pFog = vec4(fogColor.rgb, clamp(vtxFog / vtx_inv_w, 0.0, 1.0));\n"); mstring_append(vars, "vec4 pT0 = vtxT0 / vtx_inv_w;\n"); mstring_append(vars, "vec4 pT1 = vtxT1 / vtx_inv_w;\n"); diff --git a/hw/xbox/nv2a/shaders.c b/hw/xbox/nv2a/shaders.c index e4d15128ef..d285e6194c 100644 --- a/hw/xbox/nv2a/shaders.c +++ b/hw/xbox/nv2a/shaders.c @@ -242,6 +242,7 @@ static MString* generate_geometry_shader( " gl_Position = gl_in[index].gl_Position;\n" " gl_PointSize = gl_in[index].gl_PointSize;\n" " vtx_inv_w = v_vtx_inv_w[index];\n" + " vtx_inv_w_flat = v_vtx_inv_w[index];\n" " vtxD0 = v_vtxD0[index];\n" " vtxD1 = v_vtxD1[index];\n" " vtxB0 = v_vtxB0[index];\n" @@ -262,7 +263,8 @@ static MString* generate_geometry_shader( "void emit_vertex(int index, int provoking_index) {\n" " gl_Position = gl_in[index].gl_Position;\n" " gl_PointSize = gl_in[index].gl_PointSize;\n" - " vtx_inv_w = v_vtx_inv_w[provoking_index];\n" + " vtx_inv_w = v_vtx_inv_w[index];\n" + " vtx_inv_w_flat = v_vtx_inv_w[provoking_index];\n" " vtxD0 = v_vtxD0[provoking_index];\n" " vtxD1 = v_vtxD1[provoking_index];\n" " vtxB0 = v_vtxB0[provoking_index];\n" @@ -747,7 +749,8 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz " vtx_inv_w = 1.0;\n" " } else {\n" " vtx_inv_w = 1.0 / oPos.w;\n" - " }\n"); + " }\n" + " vtx_inv_w_flat = vtx_inv_w;\n"); } static MString *generate_vertex_shader(const ShaderState *state, @@ -798,6 +801,7 @@ GLSL_DEFINE(texMat3, GLSL_C_MAT4(NV_IGRAPH_XF_XFCTX_T3MAT)) STRUCT_V_VERTEX_DATA_OUT_FLAT); mstring_append(header, "#define vtx_inv_w v_vtx_inv_w\n" + "#define vtx_inv_w_flat v_vtx_inv_w_flat\n" "#define vtxD0 v_vtxD0\n" "#define vtxD1 v_vtxD1\n" "#define vtxB0 v_vtxB0\n" @@ -932,11 +936,12 @@ GLSL_DEFINE(texMat3, GLSL_C_MAT4(NV_IGRAPH_XF_XFCTX_T3MAT)) } /* Set outputs */ - mstring_append(body, "\n" - " vtxD0 = clamp(oD0, 0.0, 1.0) * vtx_inv_w;\n" - " vtxD1 = clamp(oD1, 0.0, 1.0) * vtx_inv_w;\n" - " vtxB0 = clamp(oB0, 0.0, 1.0) * vtx_inv_w;\n" - " vtxB1 = clamp(oB1, 0.0, 1.0) * vtx_inv_w;\n" + const char *shade_model_mult = state->smooth_shading ? "vtx_inv_w" : "vtx_inv_w_flat"; + mstring_append_fmt(body, "\n" + " vtxD0 = clamp(oD0, 0.0, 1.0) * %s;\n" + " vtxD1 = clamp(oD1, 0.0, 1.0) * %s;\n" + " vtxB0 = clamp(oB0, 0.0, 1.0) * %s;\n" + " vtxB1 = clamp(oB1, 0.0, 1.0) * %s;\n" " vtxFog = oFog.x * vtx_inv_w;\n" " vtxT0 = oT0 * vtx_inv_w;\n" " vtxT1 = oT1 * vtx_inv_w;\n" @@ -945,7 +950,11 @@ GLSL_DEFINE(texMat3, GLSL_C_MAT4(NV_IGRAPH_XF_XFCTX_T3MAT)) " gl_Position = oPos;\n" " gl_PointSize = oPts.x;\n" "\n" - "}\n"); + "}\n", + shade_model_mult, + shade_model_mult, + shade_model_mult, + shade_model_mult); /* Return combined header + source */ diff --git a/hw/xbox/nv2a/shaders_common.h b/hw/xbox/nv2a/shaders_common.h index 084e77b744..ae2ba9f14d 100644 --- a/hw/xbox/nv2a/shaders_common.h +++ b/hw/xbox/nv2a/shaders_common.h @@ -24,7 +24,8 @@ #include "debug.h" #define DEF_VERTEX_DATA(qualifier, in_out, prefix, suffix) \ - qualifier " " in_out " float " prefix "vtx_inv_w" suffix ";\n" \ + "noperspective " in_out " float " prefix "vtx_inv_w" suffix ";\n" \ + "flat " in_out " float " prefix "vtx_inv_w_flat" suffix ";\n" \ qualifier " " in_out " vec4 " prefix "vtxD0" suffix ";\n" \ qualifier " " in_out " vec4 " prefix "vtxD1" suffix ";\n" \ qualifier " " in_out " vec4 " prefix "vtxB0" suffix ";\n" \ diff --git a/hw/xbox/nv2a/vsh.c b/hw/xbox/nv2a/vsh.c index 4635a3a915..87318419c9 100644 --- a/hw/xbox/nv2a/vsh.c +++ b/hw/xbox/nv2a/vsh.c @@ -825,6 +825,7 @@ void vsh_translate(uint16_t version, " } else {\n" " vtx_inv_w = 1.0 / oPos.w;\n" " }\n" + " vtx_inv_w_flat = vtx_inv_w;\n" ); mstring_append(body,