Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
cac29ed
See through fix
polymetal0 Dec 31, 2024
aa084b9
Use NV_PGRAPH_ZCLIP min and max
polymetal0 Jan 3, 2025
6f4a9b1
Use NV_PGRAPH_ZCLIPMIN as threshold for undoing perspective divide
polymetal0 Jan 4, 2025
97bee8d
Remove vtx_inv_w and vtx_inv_w_flat variables
polymetal0 Jan 10, 2025
1fed2a0
W_param tests fixed
polymetal0 Jan 11, 2025
63c07ea
Merge remote-tracking branch 'upstream/master'
polymetal0 Jan 11, 2025
bcb11b7
Syntax
polymetal0 Jan 11, 2025
4da74db
more syntax
polymetal0 Jan 11, 2025
687787e
Revert "more syntax"
polymetal0 Jan 11, 2025
27d6781
fix syntax
polymetal0 Jan 11, 2025
4673bb9
end fix syntax
polymetal0 Jan 11, 2025
8ac1fce
Fix dashboard menu background
polymetal0 Jan 12, 2025
480ab26
Enable depth clamp for texture perspective
polymetal0 Jan 13, 2025
475bf96
style
polymetal0 Jan 13, 2025
a5d9fa5
Fix ZCull tests also in Vulkan
polymetal0 Jan 15, 2025
465fc79
Fix ZCull (no w-buf) tests
polymetal0 Jan 15, 2025
a3747fa
Merge remote-tracking branch 'upstream/master'
polymetal0 Jan 15, 2025
ef09148
More fixes for ZMinMaxControl tests
polymetal0 Jan 19, 2025
5eb6625
Handle clipping from frag shader, w-buffer zbias
polymetal0 Jan 25, 2025
73be99d
Fix fixed function ZMinMaxControl tests
polymetal0 Jan 25, 2025
34deb92
Merge branch 'master' into master
polymetal0 Jan 26, 2025
de758b5
Merge branch 'master' into master
polymetal0 Jan 26, 2025
1c65f37
Implement custom clip planes flag
polymetal0 Jan 26, 2025
8ec4106
Fix colors in w buffered ZMinMaxControl tests
polymetal0 Jan 30, 2025
3467bf2
Add custom clip planes
polymetal0 Jan 30, 2025
1311b0a
style
polymetal0 Jan 30, 2025
19fe4a3
Merge branch 'master' into master
polymetal0 Jan 30, 2025
37dfd20
Fix regression in Splinter Cell
polymetal0 Jan 31, 2025
4eda65a
Merge branch 'master' into fix/nv2a-wparam-zminmaxcontrol
polymetal0 Feb 5, 2025
bc995bb
Do not skip setting new shader binding in OGL
polymetal0 Feb 5, 2025
44283ea
Merge branch 'master' into fix/nv2a-wparam-zminmaxcontrol
polymetal0 Feb 16, 2025
f70349a
Merge branch 'master' into fix/nv2a-wparam-zminmaxcontrol
polymetal0 Mar 10, 2025
22285cd
Merge branch 'master' into fix/nv2a-wparam-zminmaxcontrol
polymetal0 Mar 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions hw/xbox/nv2a/nv2a_regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,7 @@
# 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_TEXTURE_PERSPECTIVE_ENABLE (1 << 6)
# define NV_PGRAPH_CONTROL_3_SHADEMODE (1 << 7)
# define NV_PGRAPH_CONTROL_3_SHADEMODE_FLAT 0
# define NV_PGRAPH_CONTROL_3_SHADEMODE_SMOOTH 1
Expand Down Expand Up @@ -619,6 +620,7 @@
#define NV_PGRAPH_WINDOWCLIPY6 0x00001A7C
#define NV_PGRAPH_WINDOWCLIPY7 0x00001A80
#define NV_PGRAPH_ZCOMPRESSOCCLUDE 0x00001A84
# define NV_PGRAPH_ZCOMPRESSOCCLUDE_CULL_NEAR_FAR_EN (1 << 0)
# define NV_PGRAPH_ZCOMPRESSOCCLUDE_ZCLAMP_EN (1 << 4)
# define NV_PGRAPH_ZCOMPRESSOCCLUDE_ZCLAMP_EN_CULL 0
# define NV_PGRAPH_ZCOMPRESSOCCLUDE_ZCLAMP_EN_CLAMP 1
Expand Down Expand Up @@ -879,6 +881,7 @@
# define NV097_SET_CONTROL0_STENCIL_WRITE_ENABLE (1 << 0)
# define NV097_SET_CONTROL0_Z_FORMAT (1 << 12)
# define NV097_SET_CONTROL0_Z_PERSPECTIVE_ENABLE (1 << 16)
# define NV097_SET_CONTROL0_TEXTURE_PERSPECTIVE_ENABLE (1 << 20)
# define NV097_SET_COLOR_MATERIAL 0x00000298
# define NV097_SET_FOG_MODE 0x0000029C
# define NV097_SET_FOG_MODE_V_LINEAR 0x2601
Expand Down Expand Up @@ -1233,6 +1236,7 @@
# define NV097_SET_ZMIN_MAX_CONTROL_ZCLAMP_EN 0x000000F0
# define NV097_SET_ZMIN_MAX_CONTROL_ZCLAMP_EN_CULL 0
# define NV097_SET_ZMIN_MAX_CONTROL_ZCLAMP_EN_CLAMP 1
# define NV097_SET_ZMIN_MAX_CONTROL_CULL_NEAR_FAR_EN_TRUE (1 << 0)
# define NV097_SET_ANTI_ALIASING_CONTROL 0x00001D7C
# define NV097_SET_ANTI_ALIASING_CONTROL_ENABLE (1 << 0)
# define NV097_SET_ZSTENCIL_CLEAR_VALUE 0x00001D8C
Expand Down
17 changes: 14 additions & 3 deletions hw/xbox/nv2a/pgraph/gl/shaders.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,9 @@ static void generate_shaders(ShaderBinding *binding)
state->polygon_back_mode,
state->primitive_mode,
state->smooth_shading,
false);
false,
state->z_perspective || state->texture_perspective
);
if (geometry_shader_code) {
const char* geometry_shader_code_str =
mstring_get_str(geometry_shader_code);
Expand Down Expand Up @@ -891,6 +893,17 @@ static void shader_update_constants(PGRAPHState *pg, ShaderBinding *binding,
float zclip_max = *(float *)&v[1];
glUniform4f(binding->clip_range_loc, 0, zmax, zclip_min, zclip_max);
}
if (binding->zbias_loc != -1) {
float zbias = 0.0f;
if (pgraph_reg_r(pg, NV_PGRAPH_SETUPRASTER) &
(NV_PGRAPH_SETUPRASTER_POFFSETFILLENABLE |
NV_PGRAPH_SETUPRASTER_POFFSETLINEENABLE |
NV_PGRAPH_SETUPRASTER_POFFSETPOINTENABLE)) {
uint32_t zbias_u32 = pgraph_reg_r(pg, NV_PGRAPH_ZOFFSETBIAS);
zbias = *(float *)&zbias_u32;
}
glUniform1f(binding->zbias_loc, zbias);
}

if (binding->depth_offset_loc != -1) {
float zbias = 0.0f;
Expand Down Expand Up @@ -1029,7 +1042,6 @@ void pgraph_gl_bind_shaders(PGRAPHState *pg)
bool binding_changed = false;
if (r->shader_binding && !test_shaders_dirty(pg) && !pg->program_data_dirty) {
nv2a_profile_inc_counter(NV2A_PROF_SHADER_BIND_NOTDIRTY);
goto update_constants;
}

ShaderBinding *old_binding = r->shader_binding;
Expand Down Expand Up @@ -1069,7 +1081,6 @@ void pgraph_gl_bind_shaders(PGRAPHState *pg)

NV2A_GL_DGROUP_END();

update_constants:
assert(r->shader_binding);
assert(r->shader_binding->initialized);
shader_update_constants(pg, r->shader_binding, binding_changed);
Expand Down
4 changes: 4 additions & 0 deletions hw/xbox/nv2a/pgraph/glsl/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,9 @@ MString *pgraph_get_glsl_vtx_header(MString *out, bool location, bool smooth, bo
suffix_s);
}

if (location) {
mstring_append(out, " layout(location = 9) ");
}
mstring_append_fmt(out, "%s float %sdepthBuf%s;\n", in_out_s, prefix_s, suffix_s);
return out;
}
2 changes: 1 addition & 1 deletion hw/xbox/nv2a/pgraph/glsl/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@

#define GLSL_DEFINE(a, b) "#define " stringify(a) " " b "\n"

MString *pgraph_get_glsl_vtx_header(MString *out, bool location, bool smooth, bool in, bool prefix, bool array);
MString *pgraph_get_glsl_vtx_header(MString *out, bool location, bool smooth, bool in, bool prefix, bool array, bool z_perspective);

#endif
9 changes: 6 additions & 3 deletions hw/xbox/nv2a/pgraph/glsl/geom.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ MString *pgraph_gen_geom_glsl(enum ShaderPolygonMode polygon_front_mode,
enum ShaderPolygonMode polygon_back_mode,
enum ShaderPrimitiveMode primitive_mode,
bool smooth_shading,
bool vulkan)
bool vulkan,
bool z_perspective)
{
/* FIXME: Missing support for 2-sided-poly mode */
assert(polygon_front_mode == polygon_back_mode);
Expand Down Expand Up @@ -174,14 +175,15 @@ MString *pgraph_gen_geom_glsl(enum ShaderPolygonMode polygon_front_mode,
mstring_append(s, layout_in);
mstring_append(s, layout_out);
mstring_append(s, "\n");
pgraph_get_glsl_vtx_header(s, vulkan, smooth_shading, true, true, true);
pgraph_get_glsl_vtx_header(s, vulkan, smooth_shading, false, false, false);
pgraph_get_glsl_vtx_header(s, vulkan, smooth_shading, true, true, true, z_perspective);
pgraph_get_glsl_vtx_header(s, vulkan, smooth_shading, false, false, false, z_perspective);

if (smooth_shading) {
mstring_append(s,
"void emit_vertex(int index, int _unused) {\n"
" gl_Position = gl_in[index].gl_Position;\n"
" gl_PointSize = gl_in[index].gl_PointSize;\n"
" depthBuf = v_depthBuf[index];\n"
" vtxD0 = v_vtxD0[index];\n"
" vtxD1 = v_vtxD1[index];\n"
" vtxB0 = v_vtxB0[index];\n"
Expand All @@ -198,6 +200,7 @@ MString *pgraph_gen_geom_glsl(enum ShaderPolygonMode polygon_front_mode,
"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"
" depthBuf = v_depthBuf[index];\n"
" vtxD0 = v_vtxD0[provoking_index];\n"
" vtxD1 = v_vtxD1[provoking_index];\n"
" vtxB0 = v_vtxB0[provoking_index];\n"
Expand Down
3 changes: 2 additions & 1 deletion hw/xbox/nv2a/pgraph/glsl/geom.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ MString *pgraph_gen_geom_glsl(enum ShaderPolygonMode polygon_front_mode,
enum ShaderPolygonMode polygon_back_mode,
enum ShaderPrimitiveMode primitive_mode,
bool smooth_shading,
bool vulkan);
bool vulkan,
bool z_perspective);

#endif
59 changes: 55 additions & 4 deletions hw/xbox/nv2a/pgraph/glsl/psh.c
Original file line number Diff line number Diff line change
Expand Up @@ -733,11 +733,13 @@ static void apply_convolution_filter(const struct PixelShader *ps, MString *vars

static MString* psh_convert(struct PixelShader *ps)
{
bool z_perspective = ps->state.z_perspective;
bool tex = ps->state.texture_perspective;
const char *u = ps->state.vulkan ? "" : "uniform "; // FIXME: Remove

MString *preflight = mstring_new();
pgraph_get_glsl_vtx_header(preflight, ps->state.vulkan,
ps->state.smooth_shading, true, false, false);
ps->state.smooth_shading, true, false, false, tex || z_perspective);

if (ps->state.vulkan) {
mstring_append_fmt(preflight,
Expand Down Expand Up @@ -869,6 +871,43 @@ static MString* psh_convert(struct PixelShader *ps)
}

/* Depth clipping */
/* OGL/VK zbias is applied to z coord, so we need to apply it
* to w coord manually when w-buffering is enabled */
mstring_append(clip, "float w = depthBuf + zbias;\n");
if (ps->state.vulkan) {
mstring_append(clip, "float z = gl_FragCoord.z;\n");
} else {
/* Changing clipping range to [-1, 1] here
* prevents floating point precission loss in OGL */
mstring_append(clip, "float z = gl_FragCoord.z * 2.0 - 1.0;\n");
}

const char *z = ps->state.z_perspective ? "w" : "z * clipRange.y";
if (ps->state.clipping) {
mstring_append_fmt(clip,
"if (%s < clipRange.z || clipRange.w < %s) {\n"
" discard;\n"
"}\n", z, z
);
}
if (ps->state.near_far) {
/* FIXME: set correct custom clip planes
* (see pgraph ZMinMaxControl tests)*/
mstring_append(clip,
// near plane
"if (z * clipRange.y < clipRange.z*2.0/3.0) {\n"
" discard;\n"
"}\n"
// z=n->f far plane
//"if (z * clipRange.y > clipRange.w*1.2) {\n"
// z=inc far plane
"if (z * clipRange.y > clipRange.w + 2.0*(clipRange.w + clipRange.z)/(clipRange.w - clipRange.z) - 1) {\n"
" discard;\n"
"}\n"
);
}

/* calculate perspective-correct inputs
if (ps->state.depth_clipping) {
if (ps->state.z_perspective) {
mstring_append(
Expand All @@ -877,7 +916,7 @@ static MString* psh_convert(struct PixelShader *ps)
" discard;\n"
"}\n");
} else {
/* Take care of floating point precision problems. MS dashboard
Take care of floating point precision problems. MS dashboard
* outputs exactly 0.0 z-coordinates and then our fixed function
* vertex shader outputs -w as the z-coordinate when OpenGL is
* used. Since -w/w = -1, this should give us exactly 0.0 as
Expand All @@ -893,7 +932,7 @@ static MString* psh_convert(struct PixelShader *ps)
* depth buffer.) Radeon OpenGL problem could also be fixed by using
* glClipControl(), but it requires OpenGL 4.5.
* Above is based on experiments with Linux and Mesa.
*/

if (ps->state.vulkan) {
mstring_append(
clip, "if (gl_FragCoord.z*clipRange.y < clipRange.z ||\n"
Expand All @@ -908,7 +947,7 @@ static MString* psh_convert(struct PixelShader *ps)
"}\n");
}
}
}
} */

MString *vars = mstring_new();
mstring_append(vars, "vec4 pD0 = vtxD0;\n");
Expand All @@ -919,6 +958,7 @@ static MString* psh_convert(struct PixelShader *ps)
mstring_append(vars, "vec4 pT0 = vtxT0;\n");
mstring_append(vars, "vec4 pT1 = vtxT1;\n");
mstring_append(vars, "vec4 pT2 = vtxT2;\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");
Expand Down Expand Up @@ -1245,6 +1285,17 @@ static MString* psh_convert(struct PixelShader *ps)
}
}

/* NV097_SET_CONTROL0_Z_PERSPECTIVE_ENABLE enables w-buffering
* not only gl_Position gets divided by the homogeneous coordinate,
* but also all other interpolated variables, which requires
* the division to be after the rasterization */
if (z_perspective) {
mstring_append(ps->code, "gl_FragDepth = w / clipRange.y;\n");
}
else if (!ps->state.vulkan) {
mstring_append(ps->code, "gl_FragDepth = z;\n");
}

for (int i = 0; i < ps->num_var_refs; i++) {
mstring_append_fmt(vars, "vec4 %s = vec4(0);\n", ps->var_refs[i]);
if (strcmp(ps->var_refs[i], "r0") == 0) {
Expand Down
10 changes: 10 additions & 0 deletions hw/xbox/nv2a/pgraph/glsl/vsh-ff.c
Original file line number Diff line number Diff line change
Expand Up @@ -423,9 +423,19 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
mstring_append(body,
" oPos = tPosition * compositeMat;\n"
" oPos.w = clampAwayZeroInf(oPos.w);\n"
" depthBuf = (invViewport * vec4(oPos.xyz/oPos.w, oPos.w)).w;\n"
" oPos = invViewport * oPos;\n"
);

if (!state->texture_perspective) {
mstring_append(body,
" if (oPos.w >= 0.0) {\n"
" oPos.xyz /= oPos.w;\n"
" oPos.w = 1.0;\n"
" }\n"
);
}
mstring_append(body," oPos = invViewport * oPos;\n");
if (state->vulkan) {
mstring_append(body, " oPos.y *= -1;\n");
}
Expand Down
10 changes: 7 additions & 3 deletions hw/xbox/nv2a/pgraph/glsl/vsh-prog.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <assert.h>

#include "hw/xbox/nv2a/pgraph/vsh.h"
#include "hw/xbox/nv2a/pgraph/shaders.h"
#include "common.h"
#include "vsh-prog.h"

Expand Down Expand Up @@ -790,11 +791,13 @@ static const char* vsh_header =
"}\n";

void pgraph_gen_vsh_prog_glsl(uint16_t version,
const uint32_t *tokens,
unsigned int length,
bool vulkan,
const ShaderState *state,
MString *header, MString *body)
{
const uint32_t *tokens = (uint32_t *)state->program_data;
unsigned int length = state->program_length;
bool texture = state->texture_perspective;
bool vulkan = state->vulkan;

mstring_append(header, vsh_header);

Expand Down Expand Up @@ -837,6 +840,7 @@ void pgraph_gen_vsh_prog_glsl(uint16_t version,
}

mstring_append(body,
" depthBuf = oPos.w;\n"
" oPos.z = oPos.z / clipRange.y;\n"
" oPos.w = clampAwayZeroInf(oPos.w);\n"

Expand Down
5 changes: 2 additions & 3 deletions hw/xbox/nv2a/pgraph/glsl/vsh-prog.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@
#ifndef HW_XBOX_NV2A_PGRAPH_GLSL_VSH_PROG_H
#define HW_XBOX_NV2A_PGRAPH_GLSL_VSH_PROG_H

void pgraph_gen_vsh_prog_glsl(uint16_t version, const uint32_t *tokens,
unsigned int length,
bool vulkan, MString *header, MString *body);
void pgraph_gen_vsh_prog_glsl(uint16_t version, const ShaderState *state,
MString *header, MString *body);

#endif
24 changes: 7 additions & 17 deletions hw/xbox/nv2a/pgraph/glsl/vsh.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,11 @@ MString *pgraph_gen_vsh_glsl(const ShaderState *state, bool prefix_outputs)
"}\n");

pgraph_get_glsl_vtx_header(header, state->vulkan, state->smooth_shading,
false, prefix_outputs, false);
false, prefix_outputs, false, state->texture_perspective || state->z_perspective);

if (prefix_outputs) {
mstring_append(header,
"#define depthBuf v_depthBuf\n"
"#define vtxD0 v_vtxD0\n"
"#define vtxD1 v_vtxD1\n"
"#define vtxB0 v_vtxB0\n"
Expand Down Expand Up @@ -148,10 +149,8 @@ MString *pgraph_gen_vsh_glsl(const ShaderState *state, bool prefix_outputs)
if (state->fixed_function) {
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);
pgraph_gen_vsh_prog_glsl(VSH_VERSION_XVS, state, header, body);

} else {
assert(false);
}
Expand Down Expand Up @@ -241,6 +240,7 @@ MString *pgraph_gen_vsh_glsl(const ShaderState *state, bool prefix_outputs)
}

/* Set outputs */

mstring_append(body, "\n"
" vtxD0 = clamp(oD0, 0.0, 1.0);\n"
" vtxD1 = clamp(oD1, 0.0, 1.0);\n"
Expand All @@ -252,19 +252,9 @@ MString *pgraph_gen_vsh_glsl(const ShaderState *state, bool prefix_outputs)
" vtxT2 = oT2;\n"
" vtxT3 = oT3;\n"
" gl_PointSize = oPts.x;\n"
);

if (state->vulkan) {
mstring_append(body,
" gl_Position = oPos;\n"
);
} else {
mstring_append(body,
" gl_Position = vec4(oPos.x, oPos.y, 2.0*oPos.z - oPos.w, oPos.w);\n"
);
}

mstring_append(body, "}\n");
"}\n"
);

/* Return combined header + source */
if (state->vulkan) {
Expand Down
8 changes: 8 additions & 0 deletions hw/xbox/nv2a/pgraph/pgraph.c
Original file line number Diff line number Diff line change
Expand Up @@ -1073,6 +1073,12 @@ DEF_METHOD(NV097, SET_CONTROL0)
PG_SET_MASK(NV_PGRAPH_CONTROL_0,
NV_PGRAPH_CONTROL_0_Z_PERSPECTIVE_ENABLE,
z_perspective);

bool texture_perspective =
parameter & NV097_SET_CONTROL0_TEXTURE_PERSPECTIVE_ENABLE;
PG_SET_MASK(NV_PGRAPH_CONTROL_3,
NV_PGRAPH_CONTROL_3_TEXTURE_PERSPECTIVE_ENABLE,
texture_perspective);
}

DEF_METHOD(NV097, SET_COLOR_MATERIAL)
Expand Down Expand Up @@ -2683,6 +2689,8 @@ DEF_METHOD(NV097, SET_ZMIN_MAX_CONTROL)
assert(!"Invalid zclamp value");
break;
}
PG_SET_MASK(NV_PGRAPH_ZCOMPRESSOCCLUDE, NV_PGRAPH_ZCOMPRESSOCCLUDE_CULL_NEAR_FAR_EN,
GET_MASK(parameter, NV097_SET_ZMIN_MAX_CONTROL_CULL_NEAR_FAR_EN_TRUE));
}

DEF_METHOD(NV097, SET_ANTI_ALIASING_CONTROL)
Expand Down
Loading