Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nv2a: add new NV_PGRAPH parameters, fix W_param tests, ZMinMaxControl tests, see through and missing shadows #1895

Open
wants to merge 30 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 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
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
8 changes: 1 addition & 7 deletions hw/xbox/nv2a/pgraph/gl/draw.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ void pgraph_gl_draw_begin(NV2AState *d)
/* Clipping */
glEnable(GL_CLIP_DISTANCE0);
glEnable(GL_CLIP_DISTANCE1);
glEnable(GL_DEPTH_CLAMP);

/* Front-face select */
glFrontFace(pgraph_reg_r(pg, NV_PGRAPH_SETUPRASTER)
Expand Down Expand Up @@ -255,13 +256,6 @@ void pgraph_gl_draw_begin(NV2AState *d)
glDisable(GL_DEPTH_TEST);
}

if (GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_ZCOMPRESSOCCLUDE),
NV_PGRAPH_ZCOMPRESSOCCLUDE_ZCLAMP_EN) ==
NV_PGRAPH_ZCOMPRESSOCCLUDE_ZCLAMP_EN_CLAMP) {
glEnable(GL_DEPTH_CLAMP);
} else {
glDisable(GL_DEPTH_CLAMP);
}

if (GET_MASK(pgraph_reg_r(pg, NV_PGRAPH_CONTROL_3),
NV_PGRAPH_CONTROL_3_SHADEMODE) ==
Expand Down
1 change: 1 addition & 0 deletions hw/xbox/nv2a/pgraph/gl/renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ typedef struct ShaderBinding {

GLint surface_size_loc;
GLint clip_range_loc;
GLint zbias_loc;

GLint vsh_constant_loc[NV2A_VERTEXSHADER_CONSTANTS];
uint32_t vsh_constants[NV2A_VERTEXSHADER_CONSTANTS][4];
Expand Down
22 changes: 17 additions & 5 deletions hw/xbox/nv2a/pgraph/gl/shaders.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ static void update_shader_constant_locations(ShaderBinding *binding)
}
binding->surface_size_loc = glGetUniformLocation(binding->gl_program, "surfaceSize");
binding->clip_range_loc = glGetUniformLocation(binding->gl_program, "clipRange");
binding->zbias_loc = glGetUniformLocation(binding->gl_program, "zbias");
binding->fog_color_loc = glGetUniformLocation(binding->gl_program, "fogColor");
binding->fog_param_loc = glGetUniformLocation(binding->gl_program, "fogParam");

Expand Down Expand Up @@ -218,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 @@ -886,10 +889,21 @@ static void shader_update_constants(PGRAPHState *pg, ShaderBinding *binding,
uint32_t v[2];
v[0] = pgraph_reg_r(pg, NV_PGRAPH_ZCLIPMIN);
v[1] = pgraph_reg_r(pg, NV_PGRAPH_ZCLIPMAX);
float zclip_min = *(float*)&v[0] / zmax * 2.0 - 1.0;
float zclip_max = *(float*)&v[1] / zmax * 2.0 - 1.0;
float zclip_min = *(float*)&v[0];
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);
}

/* Clipping regions */
unsigned int max_gl_width = pg->surface_binding_dim.width;
Expand Down Expand Up @@ -1002,7 +1016,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 @@ -1042,7 +1055,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
24 changes: 14 additions & 10 deletions hw/xbox/nv2a/pgraph/glsl/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,38 +21,42 @@
#include "common.h"


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)
{
const char *flat_s = "flat";
const char *noperspective_s = "noperspective";
const char *noperspective_s = z_perspective ? "" : "noperspective";
const char *qualifier_s = smooth ? noperspective_s : flat_s;
const char *qualifiers[11] = {
noperspective_s, flat_s, qualifier_s, qualifier_s,
qualifier_s, qualifier_s, noperspective_s, noperspective_s,
const char *qualifiers[9] = {
qualifier_s, qualifier_s, qualifier_s,
qualifier_s, noperspective_s, noperspective_s,
noperspective_s, noperspective_s, noperspective_s
};

const char *in_out_s = in ? "in" : "out";

const char *float_s = "float";
const char *vec4_s = "vec4";
const char *types[11] = { float_s, float_s, vec4_s, vec4_s, vec4_s, vec4_s,
const char *types[9] = { vec4_s, vec4_s, vec4_s, vec4_s,
float_s, vec4_s, vec4_s, vec4_s, vec4_s };

const char *prefix_s = prefix ? "v_" : "";
const char *names[11] = {
"vtx_inv_w", "vtx_inv_w_flat", "vtxD0", "vtxD1", "vtxB0", "vtxB1",
"vtxFog", "vtxT0", "vtxT1", "vtxT2", "vtxT3",
const char *names[9] = {
"vtxD0", "vtxD1", "vtxB0", "vtxB1",
"vtxFog", "vtxT0", "vtxT1", "vtxT2", "vtxT3",
};
const char *suffix_s = array ? "[]" : "";

for (int i = 0; i < 11; i++) {
for (int i = 0; i < 9; i++) {
if (location) {
mstring_append_fmt(out, "layout(location = %d) ", i);
}
mstring_append_fmt(out, "%s %s %s %s%s%s;\n",
qualifiers[i], in_out_s, types[i], prefix_s, names[i], 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
13 changes: 6 additions & 7 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,18 +175,17 @@ 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"
// " 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"
" vtxD1 = v_vtxD1[index];\n"
" vtxB0 = v_vtxB0[index];\n"
Expand All @@ -202,10 +202,9 @@ 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"
// " 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"
" 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
85 changes: 65 additions & 20 deletions hw/xbox/nv2a/pgraph/glsl/psh.c
Original file line number Diff line number Diff line change
Expand Up @@ -728,11 +728,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 All @@ -742,11 +744,12 @@ static MString* psh_convert(struct PixelShader *ps)
mstring_append_fmt(preflight,
"layout(location = 0) out vec4 fragColor;\n");
}

mstring_append_fmt(preflight, "%sfloat alphaRef;\n"
"%svec4 fogColor;\n"
"%sivec4 clipRegion[8];\n",
u, u, u);
"%sivec4 clipRegion[8];\n"
"%svec4 clipRange;\n"
"%sfloat zbias;\n",
u, u, u, u, u);
for (int i = 0; i < 4; i++) {
mstring_append_fmt(preflight, "%smat2 bumpMat%d;\n"
"%sfloat bumpScale%d;\n"
Expand Down Expand Up @@ -861,28 +864,59 @@ static MString* psh_convert(struct PixelShader *ps)
"}\n");
}

/* calculate perspective-correct inputs */
MString *vars = mstring_new();
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");
/* 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 {
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");
/* 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"
);
}
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");

/* calculate perspective-correct inputs */
MString *vars = mstring_new();
mstring_append(vars, "vec4 pD0 = vtxD0;\n");
mstring_append(vars, "vec4 pD1 = vtxD1;\n");
mstring_append(vars, "vec4 pB0 = vtxB0;\n");
mstring_append(vars, "vec4 pB1 = vtxB1;\n");
mstring_append(vars, "vec4 pFog = vec4(fogColor.rgb, clamp(vtxFog, 0.0, 1.0));\n");
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");
} else {
mstring_append(vars, "vec4 pT3 = vtxT3 / vtx_inv_w;\n");
mstring_append(vars, "vec4 pT3 = vtxT3;\n");
}
mstring_append(vars, "\n");
mstring_append(vars, "vec4 v0 = pD0;\n");
Expand Down Expand Up @@ -1195,6 +1229,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
Loading