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, ZMinMaxControl tests and see through #1826

Open
wants to merge 22 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
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: 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
20 changes: 17 additions & 3 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
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
73 changes: 53 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,47 @@ 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 = 1.0/gl_FragCoord.w + 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");
}
if (ps->state.clipping) {
if (ps->state.z_perspective) {
mstring_append(clip,
"if (w < clipRange.z || clipRange.w < w) {\n"
" discard;\n"
"}\n");
} else {
mstring_append(clip,
"if (z * clipRange.y < clipRange.z || z * clipRange.y > clipRange.w) {\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 +1217,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
17 changes: 7 additions & 10 deletions hw/xbox/nv2a/pgraph/glsl/vsh-ff.c
Original file line number Diff line number Diff line change
Expand Up @@ -421,13 +421,17 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
}

mstring_append(body,
" oPos = invViewport * (tPosition * compositeMat);\n"
" oPos = tPosition * compositeMat;\n"
" if (oPos.w < 0.0) {\n"
" oPos.w = clamp(oPos.w, -1.884467e+019, -5.421011e-20);\n"
" } else {\n"
" oPos.w = clamp(oPos.w, 5.421011e-20, 1.884467e+019);\n"
" }\n"
" oPos = invViewport * oPos;\n"
);

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

/* FIXME: Testing */
Expand All @@ -446,13 +450,6 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
state->surface_scale_factor);
}

mstring_append(body,
" if (oPos.w == 0.0 || isinf(oPos.w)) {\n"
" vtx_inv_w = 1.0;\n"
" } else {\n"
" vtx_inv_w = 1.0 / oPos.w;\n"
" }\n"
" vtx_inv_w_flat = vtx_inv_w;\n");
}

static void append_skinning_code(MString* str, bool mix,
Expand Down
Loading