From 41328453360dc3021b95354ecae6ee7dacf706d8 Mon Sep 17 00:00:00 2001 From: Erik Abair Date: Mon, 20 Jun 2022 17:03:25 -0700 Subject: [PATCH] nv2a: Implement SET_SHADE_MODEL --- hw/xbox/nv2a/nv2a_int.h | 2 + hw/xbox/nv2a/nv2a_regs.h | 3 + hw/xbox/nv2a/pgraph.c | 15 +++ hw/xbox/nv2a/pgraph_methods.h | 1 + hw/xbox/nv2a/psh.c | 23 ++-- hw/xbox/nv2a/psh.h | 2 + hw/xbox/nv2a/shaders.c | 207 ++++++++++++++++++++++------------ hw/xbox/nv2a/shaders.h | 2 + hw/xbox/nv2a/shaders_common.h | 32 ++++-- hw/xbox/nv2a/vsh.c | 4 +- 10 files changed, 193 insertions(+), 98 deletions(-) diff --git a/hw/xbox/nv2a/nv2a_int.h b/hw/xbox/nv2a/nv2a_int.h index 17c4730198..6529435e32 100644 --- a/hw/xbox/nv2a/nv2a_int.h +++ b/hw/xbox/nv2a/nv2a_int.h @@ -348,6 +348,8 @@ typedef struct PGRAPHState { bool ltc1_dirty[NV2A_LTC1_COUNT]; float material_alpha; + // FIXME: Find the correct register for this. + uint32_t shade_model; // should figure out where these are in lighting context float light_infinite_half_vector[NV2A_MAX_LIGHTS][3]; diff --git a/hw/xbox/nv2a/nv2a_regs.h b/hw/xbox/nv2a/nv2a_regs.h index 252b89c83e..4aa5c129bf 100644 --- a/hw/xbox/nv2a/nv2a_regs.h +++ b/hw/xbox/nv2a/nv2a_regs.h @@ -974,6 +974,9 @@ # define NV097_SET_STENCIL_OP_V_INVERT 0x150A # define NV097_SET_STENCIL_OP_V_INCR 0x8507 # define NV097_SET_STENCIL_OP_V_DECR 0x8508 +# define NV097_SET_SHADE_MODEL 0x0000037C +# define NV097_SET_SHADE_MODEL_FLAT 0x1D00 +# define NV097_SET_SHADE_MODEL_SMOOTH 0x1D01 # define NV097_SET_POLYGON_OFFSET_SCALE_FACTOR 0x00000384 # define NV097_SET_POLYGON_OFFSET_BIAS 0x00000388 # define NV097_SET_FRONT_POLYGON_MODE 0x0000038C diff --git a/hw/xbox/nv2a/pgraph.c b/hw/xbox/nv2a/pgraph.c index 5d815683de..aaffa48683 100644 --- a/hw/xbox/nv2a/pgraph.c +++ b/hw/xbox/nv2a/pgraph.c @@ -1840,6 +1840,12 @@ DEF_METHOD(NV097, SET_STENCIL_OP_ZPASS) kelvin_map_stencil_op(parameter)); } +DEF_METHOD(NV097, SET_SHADE_MODEL) +{ + // FIXME: Find the correct register for this. + pg->shade_model = parameter; +} + DEF_METHOD(NV097, SET_POLYGON_OFFSET_SCALE_FACTOR) { pg->regs[NV_PGRAPH_ZOFFSETFACTOR] = parameter; @@ -2973,6 +2979,10 @@ DEF_METHOD(NV097, SET_BEGIN_END) glDisable(GL_DEPTH_CLAMP); } + if (pg->shade_model == NV097_SET_SHADE_MODEL_FLAT) { + glProvokingVertex(GL_FIRST_VERTEX_CONVENTION); + } + if (stencil_test) { glEnable(GL_STENCIL_TEST); @@ -3996,6 +4006,7 @@ void pgraph_init(NV2AState *d) pg->shader_cache = g_hash_table_new(shader_hash, shader_equal); pg->material_alpha = 0.0f; + pg->shade_model = NV097_SET_SHADE_MODEL_SMOOTH; pg->primitive_mode = PRIM_TYPE_INVALID; for (i=0; iprimitive_mode, primitive_mode) \ + CF(pg->shade_model, shade_model) \ CF(pg->surface_scale_factor, surface_scale_factor) \ CF(pg->compressed_attrs, compressed_attrs) \ CFA(pg->texture_matrix_enable, texture_matrix_enable) @@ -4441,6 +4453,9 @@ static void pgraph_bind_shaders(PGRAPHState *pg) state.polygon_back_mode = (enum ShaderPolygonMode)GET_MASK(pg->regs[NV_PGRAPH_SETUPRASTER], NV_PGRAPH_SETUPRASTER_BACKFACEMODE); + state.shade_model_flat = pg->shade_model == NV097_SET_SHADE_MODEL_FLAT; + state.psh.shade_model_flat = pg->shade_model == NV097_SET_SHADE_MODEL_FLAT; + state.program_length = 0; if (vertex_program) { diff --git a/hw/xbox/nv2a/pgraph_methods.h b/hw/xbox/nv2a/pgraph_methods.h index 0d0bb1d7e9..8b94b43744 100644 --- a/hw/xbox/nv2a/pgraph_methods.h +++ b/hw/xbox/nv2a/pgraph_methods.h @@ -66,6 +66,7 @@ DEF_METHOD(NV097, SET_STENCIL_FUNC_MASK) DEF_METHOD(NV097, SET_STENCIL_OP_FAIL) DEF_METHOD(NV097, SET_STENCIL_OP_ZFAIL) DEF_METHOD(NV097, SET_STENCIL_OP_ZPASS) +DEF_METHOD(NV097, SET_SHADE_MODEL) DEF_METHOD(NV097, SET_POLYGON_OFFSET_SCALE_FACTOR) DEF_METHOD(NV097, SET_POLYGON_OFFSET_BIAS) DEF_METHOD(NV097, SET_FRONT_POLYGON_MODE) diff --git a/hw/xbox/nv2a/psh.c b/hw/xbox/nv2a/psh.c index 79cf61f67b..b041cfba55 100644 --- a/hw/xbox/nv2a/psh.c +++ b/hw/xbox/nv2a/psh.c @@ -690,9 +690,8 @@ static MString* psh_convert(struct PixelShader *ps) int i; MString *preflight = mstring_new(); - mstring_append(preflight, STRUCT_VERTEX_DATA); - mstring_append(preflight, "noperspective in VertexData g_vtx;\n"); - mstring_append(preflight, "#define vtx g_vtx\n"); + mstring_append(preflight, + ps->state.shade_model_flat ? STRUCT_VERTEX_DATA_IN_FLAT : STRUCT_VERTEX_DATA_IN_SMOOTH); mstring_append(preflight, "\n"); mstring_append(preflight, "out vec4 fragColor;\n"); mstring_append(preflight, "\n"); @@ -801,19 +800,19 @@ static MString* psh_convert(struct PixelShader *ps) /* calculate perspective-correct inputs */ MString *vars = mstring_new(); - mstring_append(vars, "vec4 pD0 = vtx.D0 / vtx.inv_w;\n"); - mstring_append(vars, "vec4 pD1 = vtx.D1 / vtx.inv_w;\n"); - mstring_append(vars, "vec4 pB0 = vtx.B0 / vtx.inv_w;\n"); - mstring_append(vars, "vec4 pB1 = vtx.B1 / vtx.inv_w;\n"); - mstring_append(vars, "vec4 pFog = vec4(fogColor.rgb, clamp(vtx.Fog / vtx.inv_w, 0.0, 1.0));\n"); - mstring_append(vars, "vec4 pT0 = vtx.T0 / vtx.inv_w;\n"); - mstring_append(vars, "vec4 pT1 = vtx.T1 / vtx.inv_w;\n"); - mstring_append(vars, "vec4 pT2 = vtx.T2 / vtx.inv_w;\n"); + 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"); + 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"); + mstring_append(vars, "vec4 pT2 = vtxT2 / vtx_inv_w;\n"); if (ps->state.point_sprite) { assert(!ps->state.rect_tex[3]); mstring_append(vars, "vec4 pT3 = vec4(gl_PointCoord, 1.0, 1.0);\n"); } else { - mstring_append(vars, "vec4 pT3 = vtx.T3 / vtx.inv_w;\n"); + mstring_append(vars, "vec4 pT3 = vtxT3 / vtx_inv_w;\n"); } mstring_append(vars, "\n"); mstring_append(vars, "vec4 v0 = pD0;\n"); diff --git a/hw/xbox/nv2a/psh.h b/hw/xbox/nv2a/psh.h index 815e775ca7..a80d3ea7c1 100644 --- a/hw/xbox/nv2a/psh.h +++ b/hw/xbox/nv2a/psh.h @@ -78,6 +78,8 @@ typedef struct PshState { enum PshAlphaFunc alpha_func; bool window_clip_exclusive; + + bool shade_model_flat; } PshState; MString *psh_translate(const PshState state); diff --git a/hw/xbox/nv2a/shaders.c b/hw/xbox/nv2a/shaders.c index 181b7e94b1..7d837b5645 100644 --- a/hw/xbox/nv2a/shaders.c +++ b/hw/xbox/nv2a/shaders.c @@ -75,7 +75,8 @@ static MString* generate_geometry_shader( enum ShaderPolygonMode polygon_front_mode, enum ShaderPolygonMode polygon_back_mode, enum ShaderPrimitiveMode primitive_mode, - GLenum *gl_primitive_mode) + GLenum *gl_primitive_mode, + bool shade_model_flat) { /* FIXME: Missing support for 2-sided-poly mode */ @@ -103,10 +104,10 @@ static MString* generate_geometry_shader( assert(polygon_mode == POLY_MODE_LINE); layout_in = "layout(triangles) in;\n"; layout_out = "layout(line_strip, max_vertices = 4) out;\n"; - body = " emit_vertex(0);\n" - " emit_vertex(1);\n" - " emit_vertex(2);\n" - " emit_vertex(0);\n" + body = " emit_vertex(0, 0);\n" + " emit_vertex(1, 0);\n" + " emit_vertex(2, 0);\n" + " emit_vertex(0, 0);\n" " EndPrimitive();\n"; break; case PRIM_TYPE_TRIANGLE_STRIP: @@ -119,15 +120,15 @@ static MString* generate_geometry_shader( * vertex we are using */ body = " if ((gl_PrimitiveIDIn & 1) == 0) {\n" " if (gl_PrimitiveIDIn == 0) {\n" - " emit_vertex(0);\n" /* bottom right */ + " emit_vertex(0, 0);\n" /* bottom right */ " }\n" - " emit_vertex(1);\n" /* top right */ - " emit_vertex(2);\n" /* bottom left */ - " emit_vertex(0);\n" /* bottom right */ + " emit_vertex(1, 0);\n" /* top right */ + " emit_vertex(2, 0);\n" /* bottom left */ + " emit_vertex(0, 0);\n" /* bottom right */ " } else {\n" - " emit_vertex(2);\n" /* bottom left */ - " emit_vertex(1);\n" /* top left */ - " emit_vertex(0);\n" /* top right */ + " emit_vertex(2, 0);\n" /* bottom left */ + " emit_vertex(1, 0);\n" /* top left */ + " emit_vertex(0, 0);\n" /* top right */ " }\n" " EndPrimitive();\n"; break; @@ -140,9 +141,9 @@ static MString* generate_geometry_shader( body = " if (gl_PrimitiveIDIn == 0) {\n" " emit_vertex(0);\n" " }\n" - " emit_vertex(1);\n" - " emit_vertex(2);\n" - " emit_vertex(0);\n" + " emit_vertex(1, 0);\n" + " emit_vertex(2, 0);\n" + " emit_vertex(0, 0);\n" " EndPrimitive();\n"; break; case PRIM_TYPE_QUADS: @@ -150,18 +151,18 @@ static MString* generate_geometry_shader( layout_in = "layout(lines_adjacency) in;\n"; if (polygon_mode == POLY_MODE_LINE) { layout_out = "layout(line_strip, max_vertices = 5) out;\n"; - body = " emit_vertex(0);\n" - " emit_vertex(1);\n" - " emit_vertex(2);\n" - " emit_vertex(3);\n" - " emit_vertex(0);\n" + body = " emit_vertex(0, 3);\n" + " emit_vertex(1, 3);\n" + " emit_vertex(2, 3);\n" + " emit_vertex(3, 3);\n" + " emit_vertex(0, 3);\n" " EndPrimitive();\n"; } else if (polygon_mode == POLY_MODE_FILL) { layout_out = "layout(triangle_strip, max_vertices = 4) out;\n"; - body = " emit_vertex(0);\n" - " emit_vertex(1);\n" - " emit_vertex(3);\n" - " emit_vertex(2);\n" + body = " emit_vertex(3, 3);\n" + " emit_vertex(0, 3);\n" + " emit_vertex(2, 3);\n" + " emit_vertex(1, 3);\n" " EndPrimitive();\n"; } else { assert(false); @@ -175,20 +176,20 @@ static MString* generate_geometry_shader( layout_out = "layout(line_strip, max_vertices = 5) out;\n"; body = " if ((gl_PrimitiveIDIn & 1) != 0) { return; }\n" " if (gl_PrimitiveIDIn == 0) {\n" - " emit_vertex(0);\n" + " emit_vertex(0, 3);\n" " }\n" - " emit_vertex(1);\n" - " emit_vertex(3);\n" - " emit_vertex(2);\n" - " emit_vertex(0);\n" + " emit_vertex(1, 3);\n" + " emit_vertex(3, 3);\n" + " emit_vertex(2, 3);\n" + " emit_vertex(0, 3);\n" " EndPrimitive();\n"; } else if (polygon_mode == POLY_MODE_FILL) { layout_out = "layout(triangle_strip, max_vertices = 4) out;\n"; body = " if ((gl_PrimitiveIDIn & 1) != 0) { return; }\n" - " emit_vertex(0);\n" - " emit_vertex(1);\n" - " emit_vertex(2);\n" - " emit_vertex(3);\n" + " emit_vertex(0, 3);\n" + " emit_vertex(1, 3);\n" + " emit_vertex(2, 3);\n" + " emit_vertex(3, 3);\n" " EndPrimitive();\n"; } else { assert(false); @@ -198,12 +199,25 @@ static MString* generate_geometry_shader( case PRIM_TYPE_POLYGON: if (polygon_mode == POLY_MODE_LINE) { *gl_primitive_mode = GL_LINE_LOOP; - } else if (polygon_mode == POLY_MODE_FILL) { + return NULL; + } + if (polygon_mode == POLY_MODE_FILL) { *gl_primitive_mode = GL_TRIANGLE_FAN; + if (!shade_model_flat) { + return NULL; + } + layout_in = "layout(triangles) in;\n"; + layout_out = "layout(triangle_strip, max_vertices = 3) out;\n"; + body = " emit_vertex(0, 2);\n" + " emit_vertex(1, 2);\n" + " emit_vertex(2, 2);\n" + " EndPrimitive();\n"; } else { assert(false); + return NULL; } - return NULL; + break; + default: assert(false); return NULL; @@ -217,18 +231,52 @@ static MString* generate_geometry_shader( "\n"); mstring_append(s, layout_in); mstring_append(s, layout_out); + mstring_append(s, "\n"); + if (shade_model_flat) { + mstring_append(s, + STRUCT_V_VERTEX_DATA_IN_ARRAY_FLAT + "\n" + STRUCT_VERTEX_DATA_OUT_FLAT + "\n" + "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[index];\n" + " vtxD0 = v_vtxD0[provoking_index];\n" + " vtxD1 = v_vtxD1[provoking_index];\n" + " vtxB0 = v_vtxB0[provoking_index];\n" + " vtxB1 = v_vtxB1[provoking_index];\n" + " vtxFog = v_vtxFog[index];\n" + " vtxT0 = v_vtxT0[index];\n" + " vtxT1 = v_vtxT1[index];\n" + " vtxT2 = v_vtxT2[index];\n" + " vtxT3 = v_vtxT3[index];\n" + " EmitVertex();\n" + "}\n"); + } else { + mstring_append(s, + STRUCT_V_VERTEX_DATA_IN_ARRAY_SMOOTH + "\n" + STRUCT_VERTEX_DATA_OUT_SMOOTH + "\n" + "void emit_vertex(int index, int _unused) {\n" + " 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" + " vtxD0 = v_vtxD0[index];\n" + " vtxD1 = v_vtxD1[index];\n" + " vtxB0 = v_vtxB0[index];\n" + " vtxB1 = v_vtxB1[index];\n" + " vtxFog = v_vtxFog[index];\n" + " vtxT0 = v_vtxT0[index];\n" + " vtxT1 = v_vtxT1[index];\n" + " vtxT2 = v_vtxT2[index];\n" + " vtxT3 = v_vtxT3[index];\n" + " EmitVertex();\n" + "}\n"); + } + mstring_append(s, "\n" - STRUCT_VERTEX_DATA - "noperspective in VertexData v_vtx[];\n" - "noperspective out VertexData g_vtx;\n" - "\n" - "void emit_vertex(int index) {\n" - " gl_Position = gl_in[index].gl_Position;\n" - " gl_PointSize = gl_in[index].gl_PointSize;\n" - " g_vtx = v_vtx[index];\n" - " EmitVertex();\n" - "}\n" - "\n" "void main() {\n"); mstring_append(s, body); mstring_append(s, "}\n"); @@ -694,17 +742,16 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz state->surface_scale_factor); } - mstring_append(body, " if (oPos.w == 0.0 || isinf(oPos.w)) {\n" - " vtx.inv_w = 1.0;\n" + " vtx_inv_w = 1.0;\n" " } else {\n" - " vtx.inv_w = 1.0 / oPos.w;\n" + " vtx_inv_w = 1.0 / oPos.w;\n" " }\n"); } static MString *generate_vertex_shader(const ShaderState *state, - char vtx_prefix) + bool prefix_outputs) { int i; MString *header = mstring_from_str( @@ -758,13 +805,32 @@ GLSL_DEFINE(texMat3, GLSL_C_MAT4(NV_IGRAPH_XF_XFCTX_T3MAT)) " float y = float(bitfieldExtract(cmp, 11, 11)) / 1023.0;\n" " float z = float(bitfieldExtract(cmp, 22, 10)) / 511.0;\n" " return vec4(x, y, z, 1);\n" -"}\n" -STRUCT_VERTEX_DATA); - - mstring_append_fmt(header, "noperspective out VertexData %c_vtx;\n", - vtx_prefix); - mstring_append_fmt(header, "#define vtx %c_vtx\n", - vtx_prefix); +"}\n"); + if (prefix_outputs) { + if (state->shade_model_flat) { + mstring_append(header, STRUCT_V_VERTEX_DATA_OUT_FLAT); + } else { + mstring_append(header, STRUCT_V_VERTEX_DATA_OUT_SMOOTH); + } + mstring_append(header, + "#define vtx_inv_w v_vtx_inv_w\n" + "#define vtxD0 v_vtxD0\n" + "#define vtxD1 v_vtxD1\n" + "#define vtxB0 v_vtxB0\n" + "#define vtxB1 v_vtxB1\n" + "#define vtxFog v_vtxFog\n" + "#define vtxT0 v_vtxT0\n" + "#define vtxT1 v_vtxT1\n" + "#define vtxT2 v_vtxT2\n" + "#define vtxT3 v_vtxT3\n" + ); + } else { + if (state->shade_model_flat) { + mstring_append(header, STRUCT_VERTEX_DATA_OUT_FLAT); + } else { + mstring_append(header, STRUCT_VERTEX_DATA_OUT_SMOOTH); + } + } mstring_append(header, "\n"); for (i = 0; i < NV2A_VERTEXSHADER_ATTRIBUTES; i++) { if (state->compressed_attrs & (1 << i)) { @@ -885,15 +951,15 @@ STRUCT_VERTEX_DATA); /* Set outputs */ mstring_append(body, "\n" - " vtx.D0 = clamp(oD0, 0.0, 1.0) * vtx.inv_w;\n" - " vtx.D1 = clamp(oD1, 0.0, 1.0) * vtx.inv_w;\n" - " vtx.B0 = clamp(oB0, 0.0, 1.0) * vtx.inv_w;\n" - " vtx.B1 = clamp(oB1, 0.0, 1.0) * vtx.inv_w;\n" - " vtx.Fog = oFog.x * vtx.inv_w;\n" - " vtx.T0 = oT0 * vtx.inv_w;\n" - " vtx.T1 = oT1 * vtx.inv_w;\n" - " vtx.T2 = oT2 * vtx.inv_w;\n" - " vtx.T3 = oT3 * vtx.inv_w;\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" + " vtxFog = oFog.x * vtx_inv_w;\n" + " vtxT0 = oT0 * vtx_inv_w;\n" + " vtxT1 = oT1 * vtx_inv_w;\n" + " vtxT2 = oT2 * vtx_inv_w;\n" + " vtxT3 = oT3 * vtx_inv_w;\n" " gl_Position = oPos;\n" " gl_PointSize = oPts.x;\n" "\n" @@ -955,7 +1021,6 @@ ShaderBinding *generate_shaders(const ShaderState *state) /* Ensure numeric values are printed with '.' radix, no grouping */ setlocale(LC_NUMERIC, "C"); - char vtx_prefix; GLuint program = glCreateProgram(); /* Create an option geometry shader and find primitive type */ @@ -964,7 +1029,8 @@ ShaderBinding *generate_shaders(const ShaderState *state) generate_geometry_shader(state->polygon_front_mode, state->polygon_back_mode, state->primitive_mode, - &gl_primitive_mode); + &gl_primitive_mode, + state->shade_model_flat); if (geometry_shader_code) { const char* geometry_shader_code_str = mstring_get_str(geometry_shader_code); @@ -973,13 +1039,10 @@ ShaderBinding *generate_shaders(const ShaderState *state) "geometry shader"); glAttachShader(program, geometry_shader); mstring_unref(geometry_shader_code); - vtx_prefix = 'v'; - } else { - vtx_prefix = 'g'; } /* create the vertex shader */ - MString *vertex_shader_code = generate_vertex_shader(state, vtx_prefix); + MString *vertex_shader_code = generate_vertex_shader(state, geometry_shader_code); GLuint vertex_shader = create_gl_shader(GL_VERTEX_SHADER, mstring_get_str(vertex_shader_code), "vertex shader"); diff --git a/hw/xbox/nv2a/shaders.h b/hw/xbox/nv2a/shaders.h index 9f90d82762..01ef47258f 100644 --- a/hw/xbox/nv2a/shaders.h +++ b/hw/xbox/nv2a/shaders.h @@ -97,6 +97,8 @@ typedef struct ShaderState { bool point_params_enable; float point_size; float point_params[8]; + + bool shade_model_flat; } ShaderState; typedef struct ShaderBinding { diff --git a/hw/xbox/nv2a/shaders_common.h b/hw/xbox/nv2a/shaders_common.h index a2d04782c0..d00f04d514 100644 --- a/hw/xbox/nv2a/shaders_common.h +++ b/hw/xbox/nv2a/shaders_common.h @@ -23,19 +23,27 @@ #include "debug.h" -#define STRUCT_VERTEX_DATA "struct VertexData {\n" \ - " float inv_w;\n" \ - " vec4 D0;\n" \ - " vec4 D1;\n" \ - " vec4 B0;\n" \ - " vec4 B1;\n" \ - " float Fog;\n" \ - " vec4 T0;\n" \ - " vec4 T1;\n" \ - " vec4 T2;\n" \ - " vec4 T3;\n" \ - "};\n" +#define DEF_VERTEX_DATA(qualifier, in_out, prefix, suffix) \ + "noperspective " in_out " float " prefix "vtx_inv_w" 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" \ + qualifier " " in_out " vec4 " prefix "vtxB1" suffix ";\n" \ + "noperspective " in_out " float " prefix "vtxFog" suffix ";\n" \ + "noperspective " in_out " vec4 " prefix "vtxT0" suffix ";\n" \ + "noperspective " in_out " vec4 " prefix "vtxT1" suffix ";\n" \ + "noperspective " in_out " vec4 " prefix "vtxT2" suffix ";\n" \ + "noperspective " in_out " vec4 " prefix "vtxT3" suffix ";\n" +#define STRUCT_VERTEX_DATA_OUT_SMOOTH DEF_VERTEX_DATA("noperspective", "out", "", "") +#define STRUCT_VERTEX_DATA_IN_SMOOTH DEF_VERTEX_DATA("noperspective", "in", "", "") +#define STRUCT_V_VERTEX_DATA_OUT_SMOOTH DEF_VERTEX_DATA("noperspective", "out", "v_", "") +#define STRUCT_V_VERTEX_DATA_IN_ARRAY_SMOOTH DEF_VERTEX_DATA("noperspective", "in", "v_", "[]") + +#define STRUCT_VERTEX_DATA_OUT_FLAT DEF_VERTEX_DATA("flat", "out", "", "") +#define STRUCT_VERTEX_DATA_IN_FLAT DEF_VERTEX_DATA("flat", "in", "", "") +#define STRUCT_V_VERTEX_DATA_OUT_FLAT DEF_VERTEX_DATA("flat", "out", "v_", "") +#define STRUCT_V_VERTEX_DATA_IN_ARRAY_FLAT DEF_VERTEX_DATA("flat", "in", "v_", "[]") typedef struct { int ref; diff --git a/hw/xbox/nv2a/vsh.c b/hw/xbox/nv2a/vsh.c index b4b90877bc..4635a3a915 100644 --- a/hw/xbox/nv2a/vsh.c +++ b/hw/xbox/nv2a/vsh.c @@ -821,9 +821,9 @@ void vsh_translate(uint16_t version, * around the perspective divide */ mstring_append(body, " if (oPos.w == 0.0 || isinf(oPos.w)) {\n" - " vtx.inv_w = 1.0;\n" + " vtx_inv_w = 1.0;\n" " } else {\n" - " vtx.inv_w = 1.0 / oPos.w;\n" + " vtx_inv_w = 1.0 / oPos.w;\n" " }\n" );