From 20264b1df89fb4240dd65ac4ff9baa84834d2157 Mon Sep 17 00:00:00 2001 From: espes Date: Wed, 21 Oct 2015 03:45:45 +1100 Subject: [PATCH] quick support for w buffers --- hw/xbox/nv2a.c | 14 +++++++++++--- hw/xbox/nv2a_shaders.c | 1 + hw/xbox/nv2a_shaders.h | 1 + hw/xbox/nv2a_vsh.c | 21 ++++++++++++++++----- hw/xbox/nv2a_vsh.h | 1 + 5 files changed, 30 insertions(+), 8 deletions(-) diff --git a/hw/xbox/nv2a.c b/hw/xbox/nv2a.c index 48661faade..d1e3db51eb 100644 --- a/hw/xbox/nv2a.c +++ b/hw/xbox/nv2a.c @@ -394,6 +394,7 @@ # define NV_PGRAPH_CONTROL_0_ZFUNC_GEQUAL 6 # define NV_PGRAPH_CONTROL_0_ZFUNC_ALWAYS 7 # define NV_PGRAPH_CONTROL_0_DITHERENABLE (1 << 22) +# define NV_PGRAPH_CONTROL_0_Z_PERSPECTIVE_ENABLE (1 << 23) # define NV_PGRAPH_CONTROL_0_ZWRITEENABLE (1 << 24) # define NV_PGRAPH_CONTROL_0_STENCIL_WRITE_ENABLE (1 << 25) # define NV_PGRAPH_CONTROL_0_ALPHA_WRITE_ENABLE (1 << 26) @@ -765,6 +766,7 @@ # define NV097_SET_CONTROL0 0x00970290 # 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_FOG_MODE 0x0097029C # define NV097_SET_FOG_MODE_V_LINEAR 0x2601 # define NV097_SET_FOG_MODE_V_EXP 0x800 @@ -2943,20 +2945,20 @@ static void pgraph_bind_shaders(PGRAPHState *pg) NV_PGRAPH_CONTROL_0_ALPHAFUNC), }, + /* fixed function stuff */ .skinning = GET_MASK(pg->regs[NV_PGRAPH_CSV0_D], NV_PGRAPH_CSV0_D_SKIN), - .lighting = GET_MASK(pg->regs[NV_PGRAPH_CSV0_C], NV_PGRAPH_CSV0_C_LIGHTING), - .normalization = pg->regs[NV_PGRAPH_CSV0_C] & NV_PGRAPH_CSV0_C_NORMALIZATION_ENABLE, - /* fixed function stuff */ .fixed_function = fixed_function, /* vertex program stuff */ .vertex_program = vertex_program, + .z_perspective = pg->regs[NV_PGRAPH_CONTROL_0] + & NV_PGRAPH_CONTROL_0_Z_PERSPECTIVE_ENABLE, /* geometry shader stuff */ .primitive_mode = pg->primitive_mode, @@ -4297,6 +4299,12 @@ static void pgraph_method(NV2AState *d, uint32_t z_format = GET_MASK(parameter, NV097_SET_CONTROL0_Z_FORMAT); SET_MASK(pg->regs[NV_PGRAPH_SETUPRASTER], NV_PGRAPH_SETUPRASTER_Z_FORMAT, z_format); + + bool z_perspective = + parameter & NV097_SET_CONTROL0_Z_PERSPECTIVE_ENABLE; + SET_MASK(pg->regs[NV_PGRAPH_CONTROL_0], + NV_PGRAPH_CONTROL_0_Z_PERSPECTIVE_ENABLE, + z_perspective); break; } diff --git a/hw/xbox/nv2a_shaders.c b/hw/xbox/nv2a_shaders.c index 8a053a3184..982c32ba5c 100644 --- a/hw/xbox/nv2a_shaders.c +++ b/hw/xbox/nv2a_shaders.c @@ -628,6 +628,7 @@ static QString *generate_vertex_shader(const ShaderState state, vsh_translate(VSH_VERSION_XVS, (uint32_t*)state.program_data, state.program_length, + state.z_perspective, header, body); } else { assert(false); diff --git a/hw/xbox/nv2a_shaders.h b/hw/xbox/nv2a_shaders.h index d4ad63466a..3c487f3838 100644 --- a/hw/xbox/nv2a_shaders.h +++ b/hw/xbox/nv2a_shaders.h @@ -74,6 +74,7 @@ typedef struct ShaderState { bool vertex_program; uint32_t program_data[NV2A_MAX_TRANSFORM_PROGRAM_LENGTH][VSH_TOKEN_SIZE]; int program_length; + bool z_perspective; /* primitive format for geometry shader */ enum ShaderPolygonMode polygon_front_mode; diff --git a/hw/xbox/nv2a_vsh.c b/hw/xbox/nv2a_vsh.c index c11bd18cf7..38de2a4263 100644 --- a/hw/xbox/nv2a_vsh.c +++ b/hw/xbox/nv2a_vsh.c @@ -690,9 +690,10 @@ static const char* vsh_header = "}\n"; void vsh_translate(uint16_t version, - const uint32_t *tokens, - unsigned int length, - QString *header, QString *body) + const uint32_t *tokens, + unsigned int length, + bool z_perspective, + QString *header, QString *body) { @@ -732,7 +733,8 @@ void vsh_translate(uint16_t version, " vtx.inv_w = 1.0;\n" " } else {\n" " vtx.inv_w = 1.0 / oPos.w;\n" - " }\n"); + " }\n" + ); qstring_append(body, /* the shaders leave the result in screen space, while @@ -741,6 +743,16 @@ void vsh_translate(uint16_t version, */ " oPos.x = 2.0 * (oPos.x - surfaceSize.x * 0.5) / surfaceSize.x;\n" " oPos.y = -2.0 * (oPos.y - surfaceSize.y * 0.5) / surfaceSize.y;\n" + ); + if (z_perspective) { + qstring_append(body, " oPos.z = oPos.w;\n"); + } + qstring_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 - 0.5 * (clipRange.x + clipRange.y)) / (0.5 * (clipRange.y - clipRange.x));\n" " }\n" @@ -755,7 +767,6 @@ void vsh_translate(uint16_t version, * can't multiply by W because it could be meaningless here */ " oPos.w = 1.0;\n" " }\n" - ); } diff --git a/hw/xbox/nv2a_vsh.h b/hw/xbox/nv2a_vsh.h index 5c3b81cfd5..7ebfdb10cd 100644 --- a/hw/xbox/nv2a_vsh.h +++ b/hw/xbox/nv2a_vsh.h @@ -134,6 +134,7 @@ uint8_t vsh_get_field(const uint32_t *shader_token, VshFieldName field_name); void vsh_translate(uint16_t version, const uint32_t *tokens, unsigned int length, + bool z_perspective, QString *header, QString *body);