From 83e16c996d6f007bbeb4c5531fb6b0a81d31df05 Mon Sep 17 00:00:00 2001 From: Matt Borgerson <contact@mborgerson.com> Date: Sat, 25 Jun 2022 20:12:50 -0700 Subject: [PATCH] nv2a: Store shading mode in CONTROL_3 --- hw/xbox/nv2a/nv2a_int.h | 2 - hw/xbox/nv2a/nv2a_regs.h | 9 ++-- hw/xbox/nv2a/pgraph.c | 31 +++++++++---- hw/xbox/nv2a/pgraph_methods.h | 2 +- hw/xbox/nv2a/psh.c | 5 ++- hw/xbox/nv2a/psh.h | 2 +- hw/xbox/nv2a/shaders.c | 84 ++++++++++++++++++----------------- hw/xbox/nv2a/shaders.h | 2 +- 8 files changed, 78 insertions(+), 59 deletions(-) diff --git a/hw/xbox/nv2a/nv2a_int.h b/hw/xbox/nv2a/nv2a_int.h index 6529435e32..17c4730198 100644 --- a/hw/xbox/nv2a/nv2a_int.h +++ b/hw/xbox/nv2a/nv2a_int.h @@ -348,8 +348,6 @@ 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 4aa5c129bf..225f075fcb 100644 --- a/hw/xbox/nv2a/nv2a_regs.h +++ b/hw/xbox/nv2a/nv2a_regs.h @@ -448,6 +448,9 @@ # define NV_PGRAPH_CONTROL_2_STENCIL_OP_V_INCR 7 # define NV_PGRAPH_CONTROL_2_STENCIL_OP_V_DECR 8 #define NV_PGRAPH_CONTROL_3 0x00001958 +# define NV_PGRAPH_CONTROL_3_SHADEMODE (1 << 7) +# define NV_PGRAPH_CONTROL_3_SHADEMODE_FLAT 0 +# define NV_PGRAPH_CONTROL_3_SHADEMODE_SMOOTH 1 # define NV_PGRAPH_CONTROL_3_FOGENABLE (1 << 8) # define NV_PGRAPH_CONTROL_3_FOG_MODE 0x00070000 # define NV_PGRAPH_CONTROL_3_FOG_MODE_LINEAR 0 @@ -974,9 +977,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_SHADE_MODE 0x0000037C +# define NV097_SET_SHADE_MODE_V_FLAT 0x1D00 +# define NV097_SET_SHADE_MODE_V_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 aaffa48683..657aba7027 100644 --- a/hw/xbox/nv2a/pgraph.c +++ b/hw/xbox/nv2a/pgraph.c @@ -1840,10 +1840,21 @@ DEF_METHOD(NV097, SET_STENCIL_OP_ZPASS) kelvin_map_stencil_op(parameter)); } -DEF_METHOD(NV097, SET_SHADE_MODEL) +DEF_METHOD(NV097, SET_SHADE_MODE) { - // FIXME: Find the correct register for this. - pg->shade_model = parameter; + switch (parameter) { + case NV097_SET_SHADE_MODE_V_FLAT: + SET_MASK(pg->regs[NV_PGRAPH_CONTROL_3], NV_PGRAPH_CONTROL_3_SHADEMODE, + NV_PGRAPH_CONTROL_3_SHADEMODE_FLAT); + break; + case NV097_SET_SHADE_MODE_V_SMOOTH: + SET_MASK(pg->regs[NV_PGRAPH_CONTROL_3], NV_PGRAPH_CONTROL_3_SHADEMODE, + NV_PGRAPH_CONTROL_3_SHADEMODE_SMOOTH); + break; + default: + /* Discard */ + break; + } } DEF_METHOD(NV097, SET_POLYGON_OFFSET_SCALE_FACTOR) @@ -2979,7 +2990,9 @@ DEF_METHOD(NV097, SET_BEGIN_END) glDisable(GL_DEPTH_CLAMP); } - if (pg->shade_model == NV097_SET_SHADE_MODEL_FLAT) { + if (GET_MASK(pg->regs[NV_PGRAPH_CONTROL_3], + NV_PGRAPH_CONTROL_3_SHADEMODE) == + NV_PGRAPH_CONTROL_3_SHADEMODE_FLAT) { glProvokingVertex(GL_FIRST_VERTEX_CONVENTION); } @@ -4006,7 +4019,8 @@ 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; + SET_MASK(pg->regs[NV_PGRAPH_CONTROL_3], NV_PGRAPH_CONTROL_3_SHADEMODE, + NV_PGRAPH_CONTROL_3_SHADEMODE_SMOOTH); pg->primitive_mode = PRIM_TYPE_INVALID; for (i=0; i<NV2A_VERTEXSHADER_ATTRIBUTES; i++) { @@ -4331,7 +4345,6 @@ static bool pgraph_bind_shaders_test_dirty(PGRAPHState *pg) CR_8(NV_PGRAPH_WINDOWCLIPX0) \ CR_8(NV_PGRAPH_WINDOWCLIPY0) \ CF(pg->primitive_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) @@ -4453,8 +4466,10 @@ 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.smooth_shading = GET_MASK(pg->regs[NV_PGRAPH_CONTROL_3], + NV_PGRAPH_CONTROL_3_SHADEMODE) == + NV_PGRAPH_CONTROL_3_SHADEMODE_SMOOTH; + state.psh.smooth_shading = state.smooth_shading; state.program_length = 0; diff --git a/hw/xbox/nv2a/pgraph_methods.h b/hw/xbox/nv2a/pgraph_methods.h index 8b94b43744..b3de47959d 100644 --- a/hw/xbox/nv2a/pgraph_methods.h +++ b/hw/xbox/nv2a/pgraph_methods.h @@ -66,7 +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_SHADE_MODE) 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 b041cfba55..bf3d4bc79e 100644 --- a/hw/xbox/nv2a/psh.c +++ b/hw/xbox/nv2a/psh.c @@ -690,8 +690,9 @@ static MString* psh_convert(struct PixelShader *ps) int i; MString *preflight = mstring_new(); - mstring_append(preflight, - ps->state.shade_model_flat ? STRUCT_VERTEX_DATA_IN_FLAT : STRUCT_VERTEX_DATA_IN_SMOOTH); + mstring_append(preflight, ps->state.smooth_shading ? + STRUCT_VERTEX_DATA_IN_SMOOTH : + STRUCT_VERTEX_DATA_IN_FLAT); mstring_append(preflight, "\n"); mstring_append(preflight, "out vec4 fragColor;\n"); mstring_append(preflight, "\n"); diff --git a/hw/xbox/nv2a/psh.h b/hw/xbox/nv2a/psh.h index a80d3ea7c1..449997a0c6 100644 --- a/hw/xbox/nv2a/psh.h +++ b/hw/xbox/nv2a/psh.h @@ -79,7 +79,7 @@ typedef struct PshState { bool window_clip_exclusive; - bool shade_model_flat; + bool smooth_shading; } PshState; MString *psh_translate(const PshState state); diff --git a/hw/xbox/nv2a/shaders.c b/hw/xbox/nv2a/shaders.c index 7d837b5645..7e4af1405b 100644 --- a/hw/xbox/nv2a/shaders.c +++ b/hw/xbox/nv2a/shaders.c @@ -76,7 +76,7 @@ static MString* generate_geometry_shader( enum ShaderPolygonMode polygon_back_mode, enum ShaderPrimitiveMode primitive_mode, GLenum *gl_primitive_mode, - bool shade_model_flat) + bool smooth_shading) { /* FIXME: Missing support for 2-sided-poly mode */ @@ -203,7 +203,7 @@ static MString* generate_geometry_shader( } if (polygon_mode == POLY_MODE_FILL) { *gl_primitive_mode = GL_TRIANGLE_FAN; - if (!shade_model_flat) { + if (smooth_shading) { return NULL; } layout_in = "layout(triangles) in;\n"; @@ -232,28 +232,7 @@ static MString* generate_geometry_shader( 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 { + if (smooth_shading) { mstring_append(s, STRUCT_V_VERTEX_DATA_IN_ARRAY_SMOOTH "\n" @@ -274,6 +253,27 @@ static MString* generate_geometry_shader( " vtxT3 = v_vtxT3[index];\n" " EmitVertex();\n" "}\n"); + } else { + 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"); } mstring_append(s, "\n" @@ -807,11 +807,9 @@ GLSL_DEFINE(texMat3, GLSL_C_MAT4(NV_IGRAPH_XF_XFCTX_T3MAT)) " return vec4(x, y, z, 1);\n" "}\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, state->smooth_shading ? + STRUCT_V_VERTEX_DATA_OUT_SMOOTH : + STRUCT_V_VERTEX_DATA_OUT_FLAT); mstring_append(header, "#define vtx_inv_w v_vtx_inv_w\n" "#define vtxD0 v_vtxD0\n" @@ -825,11 +823,9 @@ GLSL_DEFINE(texMat3, GLSL_C_MAT4(NV_IGRAPH_XF_XFCTX_T3MAT)) "#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, state->smooth_shading ? + STRUCT_VERTEX_DATA_OUT_SMOOTH : + STRUCT_VERTEX_DATA_OUT_FLAT); } mstring_append(header, "\n"); for (i = 0; i < NV2A_VERTEXSHADER_ATTRIBUTES; i++) { @@ -1030,7 +1026,7 @@ ShaderBinding *generate_shaders(const ShaderState *state) state->polygon_back_mode, state->primitive_mode, &gl_primitive_mode, - state->shade_model_flat); + state->smooth_shading); if (geometry_shader_code) { const char* geometry_shader_code_str = mstring_get_str(geometry_shader_code); @@ -1042,7 +1038,8 @@ ShaderBinding *generate_shaders(const ShaderState *state) } /* create the vertex shader */ - MString *vertex_shader_code = generate_vertex_shader(state, geometry_shader_code); + MString *vertex_shader_code = + generate_vertex_shader(state, geometry_shader_code != NULL); GLuint vertex_shader = create_gl_shader(GL_VERTEX_SHADER, mstring_get_str(vertex_shader_code), "vertex shader"); @@ -1051,7 +1048,8 @@ ShaderBinding *generate_shaders(const ShaderState *state) /* generate a fragment shader from register combiners */ MString *fragment_shader_code = psh_translate(state->psh); - const char *fragment_shader_code_str = mstring_get_str(fragment_shader_code); + const char *fragment_shader_code_str = + mstring_get_str(fragment_shader_code); GLuint fragment_shader = create_gl_shader(GL_FRAGMENT_SHADER, fragment_shader_code_str, "fragment shader"); @@ -1144,14 +1142,17 @@ ShaderBinding *generate_shaders(const ShaderState *state) } for (i = 0; i < NV2A_MAX_LIGHTS; i++) { snprintf(tmp, sizeof(tmp), "lightInfiniteHalfVector%d", i); - ret->light_infinite_half_vector_loc[i] = glGetUniformLocation(program, tmp); + ret->light_infinite_half_vector_loc[i] = + glGetUniformLocation(program, tmp); snprintf(tmp, sizeof(tmp), "lightInfiniteDirection%d", i); - ret->light_infinite_direction_loc[i] = glGetUniformLocation(program, tmp); + ret->light_infinite_direction_loc[i] = + glGetUniformLocation(program, tmp); snprintf(tmp, sizeof(tmp), "lightLocalPosition%d", i); ret->light_local_position_loc[i] = glGetUniformLocation(program, tmp); snprintf(tmp, sizeof(tmp), "lightLocalAttenuation%d", i); - ret->light_local_attenuation_loc[i] = glGetUniformLocation(program, tmp); + ret->light_local_attenuation_loc[i] = + glGetUniformLocation(program, tmp); } for (i = 0; i < 8; i++) { snprintf(tmp, sizeof(tmp), "clipRegion[%d]", i); @@ -1159,7 +1160,8 @@ ShaderBinding *generate_shaders(const ShaderState *state) } if (state->fixed_function) { - ret->material_alpha_loc = glGetUniformLocation(program, "material_alpha"); + ret->material_alpha_loc = + glGetUniformLocation(program, "material_alpha"); } else { ret->material_alpha_loc = -1; } diff --git a/hw/xbox/nv2a/shaders.h b/hw/xbox/nv2a/shaders.h index 01ef47258f..a1543eb69c 100644 --- a/hw/xbox/nv2a/shaders.h +++ b/hw/xbox/nv2a/shaders.h @@ -98,7 +98,7 @@ typedef struct ShaderState { float point_size; float point_params[8]; - bool shade_model_flat; + bool smooth_shading; } ShaderState; typedef struct ShaderBinding {