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 NV_PGRAPH_CONTROL_3_TEXTURE_PERSPECTIVE_ENABLE, fix W_param tests and see through #1826

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
2 changes: 2 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 @@ -879,6 +880,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
8 changes: 5 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 ShaderBinding *generate_shaders(const ShaderState *state)
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 @@ -897,8 +899,8 @@ 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];// / zmax * 2.0 - 1.0;
polymetal0 marked this conversation as resolved.
Show resolved Hide resolved
float zclip_max = *(float*)&v[1];// / zmax * 2.0 - 1.0;
glUniform4f(binding->clip_range_loc, 0, zmax, zclip_min, zclip_max);
}

Expand Down
20 changes: 10 additions & 10 deletions hw/xbox/nv2a/pgraph/glsl/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,32 +21,32 @@
#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);
}
Expand Down
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
11 changes: 4 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,8 +175,8 @@ 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,
Expand All @@ -184,8 +185,6 @@ MString *pgraph_gen_geom_glsl(enum ShaderPolygonMode polygon_front_mode,
" 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"
" vtxD1 = v_vtxD1[index];\n"
" vtxB0 = v_vtxB0[index];\n"
Expand All @@ -204,8 +203,6 @@ MString *pgraph_gen_geom_glsl(enum ShaderPolygonMode polygon_front_mode,
" 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"
" 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
48 changes: 28 additions & 20 deletions hw/xbox/nv2a/pgraph/glsl/psh.c
Original file line number Diff line number Diff line change
Expand Up @@ -726,15 +726,17 @@ static void apply_convolution_filter(const struct PixelShader *ps, MString *vars
"}\n", tex, tex, tex, tex, tex_remap, tex);
}

static MString* psh_convert(struct PixelShader *ps)
static MString *psh_convert(struct PixelShader *ps)
{
int i;

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 @@ -744,7 +746,11 @@ static MString* psh_convert(struct PixelShader *ps)
mstring_append_fmt(preflight,
"layout(location = 0) out vec4 fragColor;\n");
}

if (z_perspective) {
mstring_append_fmt(preflight,
"%svec4 clipRange;\n",
u);
}
mstring_append_fmt(preflight, "%sfloat alphaRef;\n"
"%svec4 fogColor;\n"
"%sivec4 clipRegion[8];\n",
Expand Down Expand Up @@ -865,26 +871,20 @@ static MString* psh_convert(struct PixelShader *ps)

/* 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");
} 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");
}
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");
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 @@ -1198,7 +1198,15 @@ static MString* psh_convert(struct PixelShader *ps)
}
}

for (i = 0; i < ps->num_var_refs; i++) {
/* 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 = 1.0/(gl_FragCoord.w * clipRange.y);\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) {
if (ps->tex_modes[0] != PS_TEXTUREMODES_NONE) {
Expand Down
9 changes: 4 additions & 5 deletions hw/xbox/nv2a/pgraph/glsl/vsh-ff.c
Original file line number Diff line number Diff line change
Expand Up @@ -447,12 +447,11 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
}

mstring_append(body,
" if (oPos.w == 0.0 || isinf(oPos.w)) {\n"
" vtx_inv_w = 1.0;\n"
" if (oPos.w < 0.0) {\n"
" oPos.w = clamp(oPos.w, -1.884467e+019, -5.421011e-20);\n"
" } else {\n"
" vtx_inv_w = 1.0 / oPos.w;\n"
" }\n"
" vtx_inv_w_flat = vtx_inv_w;\n");
" oPos.w = clamp(oPos.w, 5.421011e-20, 1.884467e+019);\n"
" }\n");
}

static void append_skinning_code(MString* str, bool mix,
Expand Down
41 changes: 29 additions & 12 deletions hw/xbox/nv2a/pgraph/glsl/vsh-prog.c
Original file line number Diff line number Diff line change
Expand Up @@ -799,6 +799,7 @@ void pgraph_gen_vsh_prog_glsl(uint16_t version,
const uint32_t *tokens,
unsigned int length,
bool z_perspective,
bool texture,
bool vulkan,
MString *header, MString *body)
{
Expand Down Expand Up @@ -831,12 +832,11 @@ void pgraph_gen_vsh_prog_glsl(uint16_t version,
* interpolation manually. OpenGL can't, since we give it a W of 1 to work
* around the perspective divide */
mstring_append(body,
" if (oPos.w == 0.0 || isinf(oPos.w)) {\n"
" vtx_inv_w = 1.0;\n"
" if (oPos.w < 0.0) {\n"
" oPos.w = clamp(oPos.w, -1.884467e+019, -5.421011e-20);\n"
" } else {\n"
" vtx_inv_w = 1.0 / oPos.w;\n"
" oPos.w = clamp(oPos.w, 5.421011e-20, 1.884467e+019);\n"
" }\n"
" vtx_inv_w_flat = vtx_inv_w;\n"
);

mstring_append(body,
Expand All @@ -861,15 +861,32 @@ void pgraph_gen_vsh_prog_glsl(uint16_t version,

mstring_append(body,
" if (clipRange.y != clipRange.x) {\n");
if (vulkan) {
mstring_append(body, " oPos.z /= clipRange.y;\n");
if (texture || z_perspective) {
if (vulkan) {
mstring_append(body, " oPos.z = (oPos.z - clipRange.z)/(clipRange.w - clipRange.z);\n");
} else {
mstring_append(body,
" oPos.z = (oPos.z - clipRange.z)/(0.5*(clipRange.w "
"- clipRange.z)) - 1;\n");
}
mstring_append(body,
" }\n"
);

mstring_append(body, " oPos.xyz *= oPos.w;\n");
} else {
if (vulkan) {
mstring_append(body, " oPos.z = (oPos.z - clipRange.x)/(clipRange.y - clipRange.x);\n");
} else {
mstring_append(body,
" oPos.z = (oPos.z - clipRange.x)/(0.5*(clipRange.y "
"- clipRange.x)) - 1;\n");
}
mstring_append(body,
polymetal0 marked this conversation as resolved.
Show resolved Hide resolved
" oPos.z = (oPos.z - clipRange.x)/(0.5*(clipRange.y "
"- clipRange.x)) - 1;\n");
}
mstring_append(body,
" }\n"
" }\n"
);
mstring_append(
body,

/* Correct for the perspective divide */
" if (oPos.w < 0.0) {\n"
Expand All @@ -882,5 +899,5 @@ void pgraph_gen_vsh_prog_glsl(uint16_t version,
" oPos.w = 1.0;\n"
" }\n"
);

}
}
2 changes: 1 addition & 1 deletion hw/xbox/nv2a/pgraph/glsl/vsh-prog.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
#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 z_perspective,
unsigned int length, bool z_perspective, bool texture,
bool vulkan, MString *header, MString *body);

#endif
46 changes: 20 additions & 26 deletions hw/xbox/nv2a/pgraph/glsl/vsh.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,10 @@ 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 vtx_inv_w v_vtx_inv_w\n"
"#define vtx_inv_w_flat v_vtx_inv_w_flat\n"
"#define vtxD0 v_vtxD0\n"
"#define vtxD1 v_vtxD1\n"
"#define vtxB0 v_vtxB0\n"
Expand Down Expand Up @@ -142,7 +140,7 @@ MString *pgraph_gen_vsh_glsl(const ShaderState *state, bool prefix_outputs)
} else if (state->vertex_program) {
pgraph_gen_vsh_prog_glsl(VSH_VERSION_XVS,
(uint32_t *)state->program_data,
state->program_length, state->z_perspective,
state->program_length, state->z_perspective, state->texture_perspective,
state->vulkan, header, body);
} else {
assert(false);
Expand Down Expand Up @@ -233,28 +231,24 @@ MString *pgraph_gen_vsh_glsl(const ShaderState *state, bool prefix_outputs)
}

/* Set outputs */
const char *shade_model_mult = state->smooth_shading ? "vtx_inv_w" : "vtx_inv_w_flat";
mstring_append_fmt(body, "\n"
" vtxD0 = clamp(oD0, 0.0, 1.0) * %s;\n"
" vtxD1 = clamp(oD1, 0.0, 1.0) * %s;\n"
" vtxB0 = clamp(oB0, 0.0, 1.0) * %s;\n"
" vtxB1 = clamp(oB1, 0.0, 1.0) * %s;\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"
// " 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,
shade_model_mult,
shade_model_mult,
shade_model_mult);

mstring_append_fmt(
body, "\n"
" vtxD0 = clamp(oD0, 0.0, 1.0);\n"
" vtxD1 = clamp(oD1, 0.0, 1.0);\n"
" vtxB0 = clamp(oB0, 0.0, 1.0);\n"
" vtxB1 = clamp(oB1, 0.0, 1.0);\n"
" vtxFog = oFog.x;\n"
" vtxT0 = oT0;\n"
" vtxT1 = oT1;\n"
" vtxT2 = oT2;\n"
" vtxT3 = oT3;\n"
" gl_Position = oPos;\n"
" gl_PointSize = oPts.x;\n"
//" gl_ClipDistance[0] = oPos.w - clipRange.z;\n" // Near
//" gl_ClipDistance[1] = clipRange.w - oPos.w;\n" // Far
"\n"
"}\n"
);
/* Return combined header + source */
if (state->vulkan) {
// FIXME: Optimize uniforms
Expand Down
Loading