From b3fc80b3a83fa99aeb541a0c665cfb596cedd71c Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Sat, 21 Oct 2023 22:28:59 -0700 Subject: [PATCH] nv2a: Implement ZCLIP_MIN,MAX with gl_ClipDistance --- hw/xbox/nv2a/pgraph.c | 9 +++++++-- hw/xbox/nv2a/shaders.c | 9 +++++++-- hw/xbox/nv2a/vsh.c | 5 ----- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/hw/xbox/nv2a/pgraph.c b/hw/xbox/nv2a/pgraph.c index a134a2a661..fbf58fce9a 100644 --- a/hw/xbox/nv2a/pgraph.c +++ b/hw/xbox/nv2a/pgraph.c @@ -2945,6 +2945,10 @@ DEF_METHOD(NV097, SET_BEGIN_END) glDisable(GL_CULL_FACE); } + /* Clipping */ + glEnable(GL_CLIP_DISTANCE0); + glEnable(GL_CLIP_DISTANCE1); + /* Front-face select */ glFrontFace(pg->regs[NV_PGRAPH_SETUPRASTER] & NV_PGRAPH_SETUPRASTER_FRONTFACE @@ -4179,7 +4183,6 @@ static void pgraph_shader_update_constants(PGRAPHState *pg, *(float*)&pg->regs[NV_PGRAPH_FOGPARAM1]); } - /* FIXME: Handle NV_PGRAPH_ZCLIPMIN, NV_PGRAPH_ZCLIPMAX */ float zmax; switch (pg->surface_shape.zeta_format) { case NV097_SET_SURFACE_FORMAT_ZETA_Z16: @@ -4289,7 +4292,9 @@ static void pgraph_shader_update_constants(PGRAPHState *pg, } if (binding->clip_range_loc != -1) { - glUniform2f(binding->clip_range_loc, 0, zmax); + float zclip_min = *(float*)&pg->regs[NV_PGRAPH_ZCLIPMIN] / zmax * 2.0 - 1.0; + float zclip_max = *(float*)&pg->regs[NV_PGRAPH_ZCLIPMAX] / zmax * 2.0 - 1.0; + glUniform4f(binding->clip_range_loc, 0, zmax, zclip_min, zclip_max); } /* Clipping regions */ diff --git a/hw/xbox/nv2a/shaders.c b/hw/xbox/nv2a/shaders.c index d0a1c0fa7c..cafe326e93 100644 --- a/hw/xbox/nv2a/shaders.c +++ b/hw/xbox/nv2a/shaders.c @@ -267,6 +267,8 @@ static MString* generate_geometry_shader( "void emit_vertex(int index, int _unused) {\n" " gl_Position = gl_in[index].gl_Position;\n" " gl_PointSize = gl_in[index].gl_PointSize;\n" + " gl_ClipDistance[0] = gl_in[index].gl_ClipDistance[0];\n" + " gl_ClipDistance[1] = gl_in[index].gl_ClipDistance[1];\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" @@ -289,6 +291,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" + " gl_ClipDistance[0] = gl_in[index].gl_ClipDistance[0];\n" + " gl_ClipDistance[1] = gl_in[index].gl_ClipDistance[1];\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" @@ -784,7 +788,7 @@ static MString *generate_vertex_shader(const ShaderState *state, MString *header = mstring_from_str( "#version 400\n" "\n" -"uniform vec2 clipRange;\n" +"uniform vec4 clipRange;\n" "uniform vec2 surfaceSize;\n" "\n" /* All constants in 1 array declaration */ @@ -864,7 +868,6 @@ GLSL_DEFINE(texMat3, GLSL_C_MAT4(NV_IGRAPH_XF_XFCTX_T3MAT)) if (state->fixed_function) { generate_fixed_function(state, header, body); - } else if (state->vertex_program) { vsh_translate(VSH_VERSION_XVS, (uint32_t*)state->program_data, @@ -973,6 +976,8 @@ GLSL_DEFINE(texMat3, GLSL_C_MAT4(NV_IGRAPH_XF_XFCTX_T3MAT)) " vtxT3 = oT3 * vtx_inv_w;\n" " gl_Position = oPos;\n" " gl_PointSize = oPts.x;\n" + " gl_ClipDistance[0] = oPos.z - oPos.w*clipRange.z;\n" // Near + " gl_ClipDistance[1] = oPos.w*clipRange.w - oPos.z;\n" // Far "\n" "}\n", shade_model_mult, diff --git a/hw/xbox/nv2a/vsh.c b/hw/xbox/nv2a/vsh.c index 5f338e7368..0e4cf314bc 100644 --- a/hw/xbox/nv2a/vsh.c +++ b/hw/xbox/nv2a/vsh.c @@ -849,11 +849,6 @@ void vsh_translate(uint16_t version, mstring_append(body, " oPos.z = oPos.w;\n"); } mstring_append(body, - /* Map the clip range into clip space so z is clipped correctly. - * Note this makes the values in the depth buffer wrong. This should be - * handled with gl_ClipDistance instead, but that has performance issues - * on OS X. - */ " if (clipRange.y != clipRange.x) {\n" " oPos.z = (oPos.z - clipRange.x)/(0.5*(clipRange.y - clipRange.x)) - 1;\n" " }\n"