From 7a4a873e5b6c152688522e8d6c25be2c3a5e5250 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 13 Aug 2018 20:05:47 +0200 Subject: [PATCH 01/17] psh: Rename c0 and c1 uniforms --- hw/xbox/nv2a/nv2a_pgraph.c | 2 +- hw/xbox/nv2a/nv2a_psh.c | 13 ++++++------- hw/xbox/nv2a/nv2a_shaders.c | 6 +++--- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/hw/xbox/nv2a/nv2a_pgraph.c b/hw/xbox/nv2a/nv2a_pgraph.c index c3c20889b6..bcadfd8247 100644 --- a/hw/xbox/nv2a/nv2a_pgraph.c +++ b/hw/xbox/nv2a/nv2a_pgraph.c @@ -2742,7 +2742,7 @@ static void pgraph_shader_update_constants(PGRAPHState *pg, int i, j; /* update combiner constants */ - for (i = 0; i<= 8; i++) { + for (i = 0; i < 9; i++) { uint32_t constant[2]; if (i == 8) { /* final combiner */ diff --git a/hw/xbox/nv2a/nv2a_psh.c b/hw/xbox/nv2a/nv2a_psh.c index e31533d1b1..c60460eb96 100644 --- a/hw/xbox/nv2a/nv2a_psh.c +++ b/hw/xbox/nv2a/nv2a_psh.c @@ -245,9 +245,8 @@ static QString* get_var(struct PixelShader *ps, int reg, bool is_dest) } break; case PS_REGISTER_C0: - /* TODO: should the final stage really always be unique? */ if (ps->flags & PS_COMBINERCOUNT_UNIQUE_C0 || ps->cur_stage == 8) { - QString *reg = qstring_from_fmt("c_%d_%d", ps->cur_stage, 0); + QString *reg = qstring_from_fmt("c0_%d", ps->cur_stage); add_const_ref(ps, qstring_get_str(reg)); if (ps->cur_stage == 8) { ps->final_input.c0_used = true; @@ -256,14 +255,14 @@ static QString* get_var(struct PixelShader *ps, int reg, bool is_dest) } return reg; } else { // Same c0 - add_const_ref(ps, "c_0_0"); + add_const_ref(ps, "c0_0"); ps->stage[0].c0_used = true; - return qstring_from_str("c_0_0"); + return qstring_from_str("c0_0"); } break; case PS_REGISTER_C1: if (ps->flags & PS_COMBINERCOUNT_UNIQUE_C1 || ps->cur_stage == 8) { - QString *reg = qstring_from_fmt("c_%d_%d", ps->cur_stage, 1); + QString *reg = qstring_from_fmt("c1_%d", ps->cur_stage); add_const_ref(ps, qstring_get_str(reg)); if (ps->cur_stage == 8) { ps->final_input.c1_used = true; @@ -272,9 +271,9 @@ static QString* get_var(struct PixelShader *ps, int reg, bool is_dest) } return reg; } else { // Same c1 - add_const_ref(ps, "c_0_1"); + add_const_ref(ps, "c1_0"); ps->stage[0].c1_used = true; - return qstring_from_str("c_0_1"); + return qstring_from_str("c1_0"); } break; case PS_REGISTER_FOG: diff --git a/hw/xbox/nv2a/nv2a_shaders.c b/hw/xbox/nv2a/nv2a_shaders.c index e0e4f26466..25615d6acd 100644 --- a/hw/xbox/nv2a/nv2a_shaders.c +++ b/hw/xbox/nv2a/nv2a_shaders.c @@ -934,9 +934,9 @@ ShaderBinding* generate_shaders(const ShaderState state) ret->gl_primitive_mode = gl_primitive_mode; /* lookup fragment shader uniforms */ - for (i=0; i<=8; i++) { - for (j=0; j<2; j++) { - snprintf(tmp, sizeof(tmp), "c_%d_%d", i, j); + for (i = 0; i < 9; i++) { + for (j = 0; j < 2; j++) { + snprintf(tmp, sizeof(tmp), "c%d_%d", j, i); ret->psh_constant_loc[i][j] = glGetUniformLocation(program, tmp); } } From 0c7fdf7484656923cac18b38a39b95a1c1bfe2b9 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 13 Aug 2018 20:06:04 +0200 Subject: [PATCH 02/17] psh: Cleanup and dead code removal --- hw/xbox/nv2a/nv2a_psh.c | 28 +--------------------------- 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/hw/xbox/nv2a/nv2a_psh.c b/hw/xbox/nv2a/nv2a_psh.c index c60460eb96..6126dcd6c3 100644 --- a/hw/xbox/nv2a/nv2a_psh.c +++ b/hw/xbox/nv2a/nv2a_psh.c @@ -167,7 +167,6 @@ enum PS_FINALCOMBINERSETTING struct InputInfo { int reg, mod, chan; - bool invert; }; struct InputVarInfo { @@ -176,9 +175,6 @@ struct InputVarInfo { struct FCInputInfo { struct InputInfo a, b, c, d, e, f, g; - int c0, c1; - //uint32_t c0_value, c1_value; - bool c0_used, c1_used; bool v1r0_sum, clamp_sum, inv_v1, inv_r0, enabled; }; @@ -191,8 +187,6 @@ struct PSStageInfo { struct InputVarInfo rgb_input, alpha_input; struct OutputInfo rgb_output, alpha_output; int c0, c1; - //uint32_t c0_value, c1_value; - bool c0_used, c1_used; }; struct PixelShader { @@ -248,15 +242,9 @@ static QString* get_var(struct PixelShader *ps, int reg, bool is_dest) if (ps->flags & PS_COMBINERCOUNT_UNIQUE_C0 || ps->cur_stage == 8) { QString *reg = qstring_from_fmt("c0_%d", ps->cur_stage); add_const_ref(ps, qstring_get_str(reg)); - if (ps->cur_stage == 8) { - ps->final_input.c0_used = true; - } else { - ps->stage[ps->cur_stage].c0_used = true; - } return reg; } else { // Same c0 add_const_ref(ps, "c0_0"); - ps->stage[0].c0_used = true; return qstring_from_str("c0_0"); } break; @@ -264,15 +252,9 @@ static QString* get_var(struct PixelShader *ps, int reg, bool is_dest) if (ps->flags & PS_COMBINERCOUNT_UNIQUE_C1 || ps->cur_stage == 8) { QString *reg = qstring_from_fmt("c1_%d", ps->cur_stage); add_const_ref(ps, qstring_get_str(reg)); - if (ps->cur_stage == 8) { - ps->final_input.c1_used = true; - } else { - ps->stage[ps->cur_stage].c1_used = true; - } return reg; } else { // Same c1 add_const_ref(ps, "c1_0"); - ps->stage[0].c1_used = true; return qstring_from_str("c1_0"); } break; @@ -398,7 +380,7 @@ static QString* get_output(QString *reg, int mapping) return res; } -// Add the HLSL code for a stage +// Add the GLSL code for a stage static void add_stage_code(struct PixelShader *ps, struct InputVarInfo input, struct OutputInfo output, const char *write_mask, bool is_alpha) @@ -854,10 +836,6 @@ QString *psh_translate(const PshState state) parse_combiner_output(state.rgb_outputs[i], &ps.stage[i].rgb_output); parse_combiner_output(state.alpha_outputs[i], &ps.stage[i].alpha_output); - //ps.stage[i].c0 = (pDef->PSC0Mapping >> (i * 4)) & 0xF; - //ps.stage[i].c1 = (pDef->PSC1Mapping >> (i * 4)) & 0xF; - //ps.stage[i].c0_value = constant_0[i]; - //ps.stage[i].c1_value = constant_1[i]; } struct InputInfo blank; @@ -873,10 +851,6 @@ QString *psh_translate(const PshState state) ps.final_input.clamp_sum = flags & PS_FINALCOMBINERSETTING_CLAMP_SUM; ps.final_input.inv_v1 = flags & PS_FINALCOMBINERSETTING_COMPLEMENT_V1; ps.final_input.inv_r0 = flags & PS_FINALCOMBINERSETTING_COMPLEMENT_R0; - //ps.final_input.c0 = (pDef->PSFinalCombinerConstants >> 0) & 0xF; - //ps.final_input.c1 = (pDef->PSFinalCombinerConstants >> 4) & 0xF; - //ps.final_input.c0_value = final_constant_0; - //ps.final_input.c1_value = final_constant_1; } From 75eb05de5dda9d16c20fc17b32e85fb14f2b5f1d Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Tue, 14 Aug 2018 03:03:46 +0200 Subject: [PATCH 03/17] planned fixup for cleanup --- hw/xbox/nv2a/nv2a_psh.c | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/hw/xbox/nv2a/nv2a_psh.c b/hw/xbox/nv2a/nv2a_psh.c index 6126dcd6c3..8e3b59673e 100644 --- a/hw/xbox/nv2a/nv2a_psh.c +++ b/hw/xbox/nv2a/nv2a_psh.c @@ -487,12 +487,11 @@ static void add_final_stage_code(struct PixelShader *ps, struct FCInputInfo fina QString *d = get_input_var(ps, final.d, false); QString *g = get_input_var(ps, final.g, false); - add_var_ref(ps, "r0"); - qstring_append_fmt(ps->code, "r0.rgb = %s + mix(vec3(%s), vec3(%s), vec3(%s));\n", + qstring_append_fmt(ps->code, "fragColor.rgb = %s + mix(vec3(%s), vec3(%s), vec3(%s));\n", qstring_get_str(d), qstring_get_str(c), qstring_get_str(b), qstring_get_str(a)); /* FIXME: Is .x correctly here? */ - qstring_append_fmt(ps->code, "r0.a = vec3(%s).x;\n", qstring_get_str(g)); + qstring_append_fmt(ps->code, "fragColor.a = vec3(%s).x;\n", qstring_get_str(g)); QDECREF(a); QDECREF(b); @@ -723,20 +722,6 @@ static QString* psh_convert(struct PixelShader *ps) add_final_stage_code(ps, ps->final_input); } - for (i = 0; i < ps->num_var_refs; i++) { - qstring_append_fmt(vars, "vec4 %s;\n", ps->var_refs[i]); - if (strcmp(ps->var_refs[i], "r0") == 0) { - if (ps->tex_modes[0] != PS_TEXTUREMODES_NONE) { - qstring_append(vars, "r0.a = t0.a;\n"); - } else { - qstring_append(vars, "r0.a = 1.0;\n"); - } - } - } - for (i = 0; i < ps->num_const_refs; i++) { - qstring_append_fmt(preflight, "uniform vec4 %s;\n", ps->const_refs[i]); - } - if (ps->state.alpha_test && ps->state.alpha_func != ALPHA_FUNC_ALWAYS) { qstring_append_fmt(preflight, "uniform float alphaRef;\n"); if (ps->state.alpha_func == ALPHA_FUNC_NEVER) { @@ -754,11 +739,26 @@ static QString* psh_convert(struct PixelShader *ps) assert(false); break; } - qstring_append_fmt(ps->code, "if (!(r0.a %s alphaRef)) discard;\n", + qstring_append_fmt(ps->code, "if (!(fragColor.a %s alphaRef)) discard;\n", alpha_op); } } + for (i = 0; i < ps->num_const_refs; i++) { + qstring_append_fmt(preflight, "uniform vec4 %s;\n", ps->const_refs[i]); + } + + for (i = 0; i < ps->num_var_refs; i++) { + qstring_append_fmt(vars, "vec4 %s;\n", ps->var_refs[i]); + if (strcmp(ps->var_refs[i], "r0") == 0) { + if (ps->tex_modes[0] != PS_TEXTUREMODES_NONE) { + qstring_append(vars, "r0.a = t0.a;\n"); + } else { + qstring_append(vars, "r0.a = 1.0;\n"); + } + } + } + QString *final = qstring_new(); qstring_append(final, "#version 330\n\n"); qstring_append(final, qstring_get_str(preflight)); @@ -766,7 +766,6 @@ static QString* psh_convert(struct PixelShader *ps) qstring_append(final, qstring_get_str(clip)); qstring_append(final, qstring_get_str(vars)); qstring_append(final, qstring_get_str(ps->code)); - qstring_append(final, "fragColor = r0;\n"); qstring_append(final, "}\n"); QDECREF(preflight); From fb8f52dec5aea96b6c23d3860efc9fd36ef34b1f Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 13 Aug 2018 19:33:02 +0200 Subject: [PATCH 04/17] psh: Refactor register combiner code --- hw/xbox/nv2a/nv2a_psh.c | 75 ++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 38 deletions(-) diff --git a/hw/xbox/nv2a/nv2a_psh.c b/hw/xbox/nv2a/nv2a_psh.c index 8e3b59673e..68fb5be8cc 100644 --- a/hw/xbox/nv2a/nv2a_psh.c +++ b/hw/xbox/nv2a/nv2a_psh.c @@ -413,51 +413,57 @@ static void add_stage_code(struct PixelShader *ps, qstring_get_str(c), qstring_get_str(d)); } - QString *ab_mapping = get_output(ab, output.mapping); - QString *cd_mapping = get_output(cd, output.mapping); - QString *ab_dest = get_var(ps, output.ab, true); - QString *cd_dest = get_var(ps, output.cd, true); - QString *sum_dest = get_var(ps, output.muxsum, true); + if (output.ab != PS_REGISTER_DISCARD) { + QString *ab_dest = get_var(ps, output.ab, true); + QString *ab_mapping = get_output(ab, output.mapping); - if (qstring_get_length(ab_dest)) { qstring_append_fmt(ps->code, "%s.%s = %s(%s);\n", qstring_get_str(ab_dest), write_mask, caster, qstring_get_str(ab_mapping)); - } else { + + /* FIXME: Will these still write rgb? */ + if (!is_alpha && output.flags & PS_COMBINEROUTPUT_AB_BLUE_TO_ALPHA) { + qstring_append_fmt(ps->code, "%s.a = %s.b;\n", + qstring_get_str(ab_dest), qstring_get_str(ab_dest)); + } + + QDECREF(ab_mapping); QDECREF(ab_dest); - QINCREF(ab_mapping); - ab_dest = ab_mapping; } - if (qstring_get_length(cd_dest)) { + if (output.cd != PS_REGISTER_DISCARD) { + QString *cd_dest = get_var(ps, output.cd, true); + QString *cd_mapping = get_output(cd, output.mapping); + qstring_append_fmt(ps->code, "%s.%s = %s(%s);\n", qstring_get_str(cd_dest), write_mask, caster, qstring_get_str(cd_mapping)); - } else { - QDECREF(cd_dest); - QINCREF(cd_mapping); - cd_dest = cd_mapping; - } - if (!is_alpha && output.flags & PS_COMBINEROUTPUT_AB_BLUE_TO_ALPHA) { - qstring_append_fmt(ps->code, "%s.a = %s.b;\n", - qstring_get_str(ab_dest), qstring_get_str(ab_dest)); - } - if (!is_alpha && output.flags & PS_COMBINEROUTPUT_CD_BLUE_TO_ALPHA) { - qstring_append_fmt(ps->code, "%s.a = %s.b;\n", - qstring_get_str(cd_dest), qstring_get_str(cd_dest)); - } + /* FIXME: Will these still write rgb? */ + if (!is_alpha && output.flags & PS_COMBINEROUTPUT_CD_BLUE_TO_ALPHA) { + qstring_append_fmt(ps->code, "%s.a = %s.b;\n", + qstring_get_str(cd_dest), qstring_get_str(cd_dest)); + } - QString *sum; - if (output.muxsum_op == PS_COMBINEROUTPUT_AB_CD_SUM) { - sum = qstring_from_fmt("(%s + %s)", qstring_get_str(ab), qstring_get_str(cd)); - } else { - sum = qstring_from_fmt("((r0.a >= 0.5) ? %s : %s)", - qstring_get_str(cd), qstring_get_str(ab)); + QDECREF(cd_mapping); + QDECREF(cd_dest); } - QString *sum_mapping = get_output(sum, output.mapping); - if (qstring_get_length(sum_dest)) { + if (output.muxsum != PS_REGISTER_DISCARD) { + QString *sum_dest = get_var(ps, output.muxsum, true); + QString *sum; + if (output.muxsum_op == PS_COMBINEROUTPUT_AB_CD_SUM) { + sum = qstring_from_fmt("(%s + %s)", qstring_get_str(ab), qstring_get_str(cd)); + } else { + sum = qstring_from_fmt("((r0.a >= 0.5) ? %s : %s)", + qstring_get_str(cd), qstring_get_str(ab)); + } + QString *sum_mapping = get_output(sum, output.mapping); + qstring_append_fmt(ps->code, "%s.%s = %s(%s);\n", qstring_get_str(sum_dest), write_mask, caster, qstring_get_str(sum_mapping)); + + QDECREF(sum); + QDECREF(sum_mapping); + QDECREF(sum_dest); } QDECREF(a); @@ -466,13 +472,6 @@ static void add_stage_code(struct PixelShader *ps, QDECREF(d); QDECREF(ab); QDECREF(cd); - QDECREF(ab_mapping); - QDECREF(cd_mapping); - QDECREF(ab_dest); - QDECREF(cd_dest); - QDECREF(sum_dest); - QDECREF(sum); - QDECREF(sum_mapping); } // Add code for the final combiner stage From 8bdd9387ca4bdb04a82756445b5dcd7fde1c0b6d Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 13 Aug 2018 13:54:10 +0200 Subject: [PATCH 05/17] psh: Fix GLSL error in MUX and assert that MSB is used --- hw/xbox/nv2a/nv2a_psh.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/xbox/nv2a/nv2a_psh.c b/hw/xbox/nv2a/nv2a_psh.c index 68fb5be8cc..62c8e25ad3 100644 --- a/hw/xbox/nv2a/nv2a_psh.c +++ b/hw/xbox/nv2a/nv2a_psh.c @@ -453,8 +453,9 @@ static void add_stage_code(struct PixelShader *ps, if (output.muxsum_op == PS_COMBINEROUTPUT_AB_CD_SUM) { sum = qstring_from_fmt("(%s + %s)", qstring_get_str(ab), qstring_get_str(cd)); } else { - sum = qstring_from_fmt("((r0.a >= 0.5) ? %s : %s)", - qstring_get_str(cd), qstring_get_str(ab)); + assert(ps->flags & PS_COMBINERCOUNT_MUX_MSB); + sum = qstring_from_fmt("mix(%s, %s, r0.a < 0.5)", + qstring_get_str(ab), qstring_get_str(cd)); } QString *sum_mapping = get_output(sum, output.mapping); From 5047175e8e39043f9ae4a429bc06eefed713585b Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 13 Aug 2018 13:17:09 +0200 Subject: [PATCH 06/17] psh: Use input mapping from NV_register_combiners GL extension --- hw/xbox/nv2a/nv2a_psh.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/hw/xbox/nv2a/nv2a_psh.c b/hw/xbox/nv2a/nv2a_psh.c index 62c8e25ad3..074ef8e41e 100644 --- a/hw/xbox/nv2a/nv2a_psh.c +++ b/hw/xbox/nv2a/nv2a_psh.c @@ -317,25 +317,27 @@ static QString* get_input_var(struct PixelShader *ps, struct InputInfo in, bool QString *res; switch (in.mod) { - case PS_INPUTMAPPING_SIGNED_IDENTITY: case PS_INPUTMAPPING_UNSIGNED_IDENTITY: - QINCREF(reg); - res = reg; + res = qstring_from_fmt("max(%s, 0.0)", qstring_get_str(reg)); break; case PS_INPUTMAPPING_UNSIGNED_INVERT: - res = qstring_from_fmt("(1.0 - %s)", qstring_get_str(reg)); + res = qstring_from_fmt("(1.0 - clamp(%s, 0.0, 1.0))", qstring_get_str(reg)); break; - case PS_INPUTMAPPING_EXPAND_NORMAL: // TODO: Change to max(0, x)?? - res = qstring_from_fmt("(2.0 * %s - 1.0)", qstring_get_str(reg)); + case PS_INPUTMAPPING_EXPAND_NORMAL: + res = qstring_from_fmt("(2.0 * max(%s, 0.0) - 1.0)", qstring_get_str(reg)); break; case PS_INPUTMAPPING_EXPAND_NEGATE: - res = qstring_from_fmt("(1.0 - 2.0 * %s)", qstring_get_str(reg)); + res = qstring_from_fmt("(-2.0 * max(%s, 0.0) + 1.0)", qstring_get_str(reg)); break; case PS_INPUTMAPPING_HALFBIAS_NORMAL: - res = qstring_from_fmt("(%s - 0.5)", qstring_get_str(reg)); + res = qstring_from_fmt("(max(%s, 0.0) - 0.5)", qstring_get_str(reg)); break; case PS_INPUTMAPPING_HALFBIAS_NEGATE: - res = qstring_from_fmt("(0.5 - %s)", qstring_get_str(reg)); + res = qstring_from_fmt("(-max(%s, 0.0) + 0.5)", qstring_get_str(reg)); + break; + case PS_INPUTMAPPING_SIGNED_IDENTITY: + QINCREF(reg); + res = reg; break; case PS_INPUTMAPPING_SIGNED_NEGATE: res = qstring_from_fmt("-%s", qstring_get_str(reg)); From 6a12008d3c130ed8ea0545cb71b948fd1de28b14 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 13 Aug 2018 19:19:29 +0200 Subject: [PATCH 07/17] psh: Use output clamping from NV_register_combiners GL extension --- hw/xbox/nv2a/nv2a_psh.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/xbox/nv2a/nv2a_psh.c b/hw/xbox/nv2a/nv2a_psh.c index 074ef8e41e..21c42738d0 100644 --- a/hw/xbox/nv2a/nv2a_psh.c +++ b/hw/xbox/nv2a/nv2a_psh.c @@ -419,7 +419,7 @@ static void add_stage_code(struct PixelShader *ps, QString *ab_dest = get_var(ps, output.ab, true); QString *ab_mapping = get_output(ab, output.mapping); - qstring_append_fmt(ps->code, "%s.%s = %s(%s);\n", + qstring_append_fmt(ps->code, "%s.%s = clamp(%s(%s), -1.0, 1.0);\n", qstring_get_str(ab_dest), write_mask, caster, qstring_get_str(ab_mapping)); /* FIXME: Will these still write rgb? */ @@ -436,7 +436,7 @@ static void add_stage_code(struct PixelShader *ps, QString *cd_dest = get_var(ps, output.cd, true); QString *cd_mapping = get_output(cd, output.mapping); - qstring_append_fmt(ps->code, "%s.%s = %s(%s);\n", + qstring_append_fmt(ps->code, "%s.%s = clamp(%s(%s), -1.0, 1.0);\n", qstring_get_str(cd_dest), write_mask, caster, qstring_get_str(cd_mapping)); /* FIXME: Will these still write rgb? */ @@ -461,7 +461,7 @@ static void add_stage_code(struct PixelShader *ps, } QString *sum_mapping = get_output(sum, output.mapping); - qstring_append_fmt(ps->code, "%s.%s = %s(%s);\n", + qstring_append_fmt(ps->code, "%s.%s = clamp(%s(%s), -1.0, 1.0);\n", qstring_get_str(sum_dest), write_mask, caster, qstring_get_str(sum_mapping)); QDECREF(sum); From 7ddacf2d2087b18841b9c85e9cf96d9dcb568c20 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 13 Aug 2018 13:18:24 +0200 Subject: [PATCH 08/17] psh: Use G as alpha in final combiner --- hw/xbox/nv2a/nv2a_psh.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/hw/xbox/nv2a/nv2a_psh.c b/hw/xbox/nv2a/nv2a_psh.c index 21c42738d0..48fc61d9dd 100644 --- a/hw/xbox/nv2a/nv2a_psh.c +++ b/hw/xbox/nv2a/nv2a_psh.c @@ -487,13 +487,12 @@ static void add_final_stage_code(struct PixelShader *ps, struct FCInputInfo fina QString *b = get_input_var(ps, final.b, false); QString *c = get_input_var(ps, final.c, false); QString *d = get_input_var(ps, final.d, false); - QString *g = get_input_var(ps, final.g, false); + QString *g = get_input_var(ps, final.g, true); qstring_append_fmt(ps->code, "fragColor.rgb = %s + mix(vec3(%s), vec3(%s), vec3(%s));\n", qstring_get_str(d), qstring_get_str(c), qstring_get_str(b), qstring_get_str(a)); - /* FIXME: Is .x correctly here? */ - qstring_append_fmt(ps->code, "fragColor.a = vec3(%s).x;\n", qstring_get_str(g)); + qstring_append_fmt(ps->code, "fragColor.a = %s;\n", qstring_get_str(g)); QDECREF(a); QDECREF(b); From 0e9f94704ac9d23826664239ed529d1651eecefd Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 13 Aug 2018 13:16:12 +0200 Subject: [PATCH 09/17] psh: Use vec3 for rgb, float for alpha and vec4 for registers --- hw/xbox/nv2a/nv2a_psh.c | 99 +++++++++++++++++++++++++++-------------- 1 file changed, 66 insertions(+), 33 deletions(-) diff --git a/hw/xbox/nv2a/nv2a_psh.c b/hw/xbox/nv2a/nv2a_psh.c index 48fc61d9dd..0ca2296aad 100644 --- a/hw/xbox/nv2a/nv2a_psh.c +++ b/hw/xbox/nv2a/nv2a_psh.c @@ -209,6 +209,8 @@ struct PixelShader { char const_refs[32][32]; }; + static QString* get_input_var(struct PixelShader *ps, struct InputInfo in, bool is_alpha); + static void add_var_ref(struct PixelShader *ps, const char *var) { int i; @@ -228,16 +230,9 @@ static void add_const_ref(struct PixelShader *ps, const char *var) } // Get the code for a variable used in the program -static QString* get_var(struct PixelShader *ps, int reg, bool is_dest) +static QString* get_var(struct PixelShader *ps, int reg) { switch (reg) { - case PS_REGISTER_DISCARD: - if (is_dest) { - return qstring_from_str(""); - } else { - return qstring_from_str("0.0"); - } - break; case PS_REGISTER_C0: if (ps->flags & PS_COMBINERCOUNT_UNIQUE_C0 || ps->cur_stage == 8) { QString *reg = qstring_from_fmt("c0_%d", ps->cur_stage); @@ -280,7 +275,35 @@ static QString* get_var(struct PixelShader *ps, int reg, bool is_dest) return qstring_from_str("r1"); case PS_REGISTER_V1R0_SUM: add_var_ref(ps, "r0"); - return qstring_from_str("(v1 + r0)"); + + struct InputInfo v1_info; + v1_info.reg = PS_REGISTER_V1; + if (ps->final_input.inv_v1) { + v1_info.mod = PS_INPUTMAPPING_UNSIGNED_INVERT; + } else { + v1_info.mod = PS_INPUTMAPPING_UNSIGNED_IDENTITY; + } + v1_info.chan = PS_CHANNEL_RGB; + QString *v1 = get_input_var(ps, v1_info, false); + + struct InputInfo r0_info; + r0_info.reg = PS_REGISTER_R0; + if (ps->final_input.inv_r0) { + r0_info.mod = PS_INPUTMAPPING_UNSIGNED_INVERT; + } else { + r0_info.mod = PS_INPUTMAPPING_UNSIGNED_IDENTITY; + } + r0_info.chan = PS_CHANNEL_RGB; + QString *r0 = get_input_var(ps, r0_info, false); + + QString *reg = qstring_from_fmt(ps->final_input.clamp_sum ? + "vec4(clamp(%s + %s, 0.0, 1.0), 0.0)" : + "vec4(%s + %s, 0.0)", + qstring_get_str(v1), + qstring_get_str(r0)); + QDECREF(v1); + QDECREF(r0); + return reg; case PS_REGISTER_EF_PROD: return qstring_from_fmt("(%s * %s)", qstring_get_str(ps->varE), qstring_get_str(ps->varF)); @@ -293,11 +316,17 @@ static QString* get_var(struct PixelShader *ps, int reg, bool is_dest) // Get input variable code static QString* get_input_var(struct PixelShader *ps, struct InputInfo in, bool is_alpha) { - QString *reg = get_var(ps, in.reg, false); - if (strcmp(qstring_get_str(reg), "0.0") != 0 - && (in.reg != PS_REGISTER_EF_PROD - || strstr(qstring_get_str(reg), ".a") == NULL)) { + QString *reg; + if (in.reg == PS_REGISTER_ZERO) { + if (is_alpha) { + reg = qstring_from_str("0.0"); + } else { + reg = qstring_from_str("vec3(0.0)"); + } + } else { + reg = get_var(ps, in.reg); + switch (in.chan) { case PS_CHANNEL_RGB: if (is_alpha) { @@ -307,7 +336,11 @@ static QString* get_input_var(struct PixelShader *ps, struct InputInfo in, bool } break; case PS_CHANNEL_ALPHA: - qstring_append(reg, ".a"); + if (is_alpha) { + qstring_append(reg, ".a"); + } else { + qstring_append(reg, ".aaa"); + } break; default: assert(false); @@ -385,21 +418,20 @@ static QString* get_output(QString *reg, int mapping) // Add the GLSL code for a stage static void add_stage_code(struct PixelShader *ps, struct InputVarInfo input, struct OutputInfo output, - const char *write_mask, bool is_alpha) + bool is_alpha) { + const char *write_mask = is_alpha ? "a" : "rgb"; + QString *a = get_input_var(ps, input.a, is_alpha); QString *b = get_input_var(ps, input.b, is_alpha); QString *c = get_input_var(ps, input.c, is_alpha); QString *d = get_input_var(ps, input.d, is_alpha); - const char *caster = ""; - if (strlen(write_mask) == 3) { - caster = "vec3"; - } QString *ab; if (output.ab_op == PS_COMBINEROUTPUT_AB_DOT_PRODUCT) { - ab = qstring_from_fmt("dot(%s, %s)", + assert(!is_alpha); + ab = qstring_from_fmt("vec3(dot(%s, %s))", qstring_get_str(a), qstring_get_str(b)); } else { ab = qstring_from_fmt("(%s * %s)", @@ -408,7 +440,8 @@ static void add_stage_code(struct PixelShader *ps, QString *cd; if (output.cd_op == PS_COMBINEROUTPUT_CD_DOT_PRODUCT) { - cd = qstring_from_fmt("dot(%s, %s)", + assert(!is_alpha); + cd = qstring_from_fmt("vec3(dot(%s, %s))", qstring_get_str(c), qstring_get_str(d)); } else { cd = qstring_from_fmt("(%s * %s)", @@ -416,11 +449,11 @@ static void add_stage_code(struct PixelShader *ps, } if (output.ab != PS_REGISTER_DISCARD) { - QString *ab_dest = get_var(ps, output.ab, true); + QString *ab_dest = get_var(ps, output.ab); QString *ab_mapping = get_output(ab, output.mapping); - qstring_append_fmt(ps->code, "%s.%s = clamp(%s(%s), -1.0, 1.0);\n", - qstring_get_str(ab_dest), write_mask, caster, qstring_get_str(ab_mapping)); + qstring_append_fmt(ps->code, "%s.%s = clamp(%s, -1.0, 1.0);\n", + qstring_get_str(ab_dest), write_mask, qstring_get_str(ab_mapping)); /* FIXME: Will these still write rgb? */ if (!is_alpha && output.flags & PS_COMBINEROUTPUT_AB_BLUE_TO_ALPHA) { @@ -433,11 +466,11 @@ static void add_stage_code(struct PixelShader *ps, } if (output.cd != PS_REGISTER_DISCARD) { - QString *cd_dest = get_var(ps, output.cd, true); + QString *cd_dest = get_var(ps, output.cd); QString *cd_mapping = get_output(cd, output.mapping); - qstring_append_fmt(ps->code, "%s.%s = clamp(%s(%s), -1.0, 1.0);\n", - qstring_get_str(cd_dest), write_mask, caster, qstring_get_str(cd_mapping)); + qstring_append_fmt(ps->code, "%s.%s = clamp(%s, -1.0, 1.0);\n", + qstring_get_str(cd_dest), write_mask, qstring_get_str(cd_mapping)); /* FIXME: Will these still write rgb? */ if (!is_alpha && output.flags & PS_COMBINEROUTPUT_CD_BLUE_TO_ALPHA) { @@ -450,7 +483,7 @@ static void add_stage_code(struct PixelShader *ps, } if (output.muxsum != PS_REGISTER_DISCARD) { - QString *sum_dest = get_var(ps, output.muxsum, true); + QString *sum_dest = get_var(ps, output.muxsum); QString *sum; if (output.muxsum_op == PS_COMBINEROUTPUT_AB_CD_SUM) { sum = qstring_from_fmt("(%s + %s)", qstring_get_str(ab), qstring_get_str(cd)); @@ -461,8 +494,8 @@ static void add_stage_code(struct PixelShader *ps, } QString *sum_mapping = get_output(sum, output.mapping); - qstring_append_fmt(ps->code, "%s.%s = clamp(%s(%s), -1.0, 1.0);\n", - qstring_get_str(sum_dest), write_mask, caster, qstring_get_str(sum_mapping)); + qstring_append_fmt(ps->code, "%s.%s = clamp(%s, -1.0, 1.0);\n", + qstring_get_str(sum_dest), write_mask, qstring_get_str(sum_mapping)); QDECREF(sum); QDECREF(sum_mapping); @@ -489,7 +522,7 @@ static void add_final_stage_code(struct PixelShader *ps, struct FCInputInfo fina QString *d = get_input_var(ps, final.d, false); QString *g = get_input_var(ps, final.g, true); - qstring_append_fmt(ps->code, "fragColor.rgb = %s + mix(vec3(%s), vec3(%s), vec3(%s));\n", + qstring_append_fmt(ps->code, "fragColor.rgb = %s + mix(%s, %s, %s);\n", qstring_get_str(d), qstring_get_str(c), qstring_get_str(b), qstring_get_str(a)); qstring_append_fmt(ps->code, "fragColor.a = %s;\n", qstring_get_str(g)); @@ -713,8 +746,8 @@ static QString* psh_convert(struct PixelShader *ps) for (i = 0; i < ps->num_stages; i++) { ps->cur_stage = i; qstring_append_fmt(ps->code, "// Stage %d\n", i); - add_stage_code(ps, ps->stage[i].rgb_input, ps->stage[i].rgb_output, "rgb", false); - add_stage_code(ps, ps->stage[i].alpha_input, ps->stage[i].alpha_output, "a", true); + add_stage_code(ps, ps->stage[i].rgb_input, ps->stage[i].rgb_output, false); + add_stage_code(ps, ps->stage[i].alpha_input, ps->stage[i].alpha_output, true); } if (ps->final_input.enabled) { From f75161971a5dda89af3ef092fe7086aa1757a1a3 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 13 Aug 2018 21:12:19 +0200 Subject: [PATCH 10/17] Experimental use of GL vars --- hw/xbox/nv2a/nv2a_psh.c | 104 ++++++++++++++++++++++++++-------------- 1 file changed, 67 insertions(+), 37 deletions(-) diff --git a/hw/xbox/nv2a/nv2a_psh.c b/hw/xbox/nv2a/nv2a_psh.c index 0ca2296aad..d8c115d0ec 100644 --- a/hw/xbox/nv2a/nv2a_psh.c +++ b/hw/xbox/nv2a/nv2a_psh.c @@ -415,7 +415,7 @@ static QString* get_output(QString *reg, int mapping) return res; } -// Add the GLSL code for a stage +// Add the GLSL code for a stage which does operation static void add_stage_code(struct PixelShader *ps, struct InputVarInfo input, struct OutputInfo output, bool is_alpha) @@ -428,86 +428,106 @@ static void add_stage_code(struct PixelShader *ps, QString *d = get_input_var(ps, input.d, is_alpha); - QString *ab; if (output.ab_op == PS_COMBINEROUTPUT_AB_DOT_PRODUCT) { assert(!is_alpha); - ab = qstring_from_fmt("vec3(dot(%s, %s))", - qstring_get_str(a), qstring_get_str(b)); + qstring_append_fmt(ps->code, "ab_in.%s = vec3(dot(%s, %s));\n", + write_mask, qstring_get_str(a), qstring_get_str(b)); } else { - ab = qstring_from_fmt("(%s * %s)", - qstring_get_str(a), qstring_get_str(b)); + qstring_append_fmt(ps->code, "ab_in.%s = (%s * %s);\n", + write_mask, qstring_get_str(a), qstring_get_str(b)); } - QString *cd; if (output.cd_op == PS_COMBINEROUTPUT_CD_DOT_PRODUCT) { assert(!is_alpha); - cd = qstring_from_fmt("vec3(dot(%s, %s))", - qstring_get_str(c), qstring_get_str(d)); + qstring_append_fmt(ps->code, "cd_in.%s = vec3(dot(%s, %s));\n", + write_mask, qstring_get_str(c), qstring_get_str(d)); } else { - cd = qstring_from_fmt("(%s * %s)", - qstring_get_str(c), qstring_get_str(d)); + qstring_append_fmt(ps->code, "cd_in.%s = (%s * %s);\n", + write_mask, qstring_get_str(c), qstring_get_str(d)); } if (output.ab != PS_REGISTER_DISCARD) { - QString *ab_dest = get_var(ps, output.ab); - QString *ab_mapping = get_output(ab, output.mapping); + QString* ab_reg = qstring_from_fmt("ab_in.%s", write_mask); + QString *ab_mapping = get_output(ab_reg, output.mapping); - qstring_append_fmt(ps->code, "%s.%s = clamp(%s, -1.0, 1.0);\n", - qstring_get_str(ab_dest), write_mask, qstring_get_str(ab_mapping)); + qstring_append_fmt(ps->code, "ab_out.%s = clamp(%s, -1.0, 1.0);\n", + write_mask, qstring_get_str(ab_mapping)); /* FIXME: Will these still write rgb? */ if (!is_alpha && output.flags & PS_COMBINEROUTPUT_AB_BLUE_TO_ALPHA) { - qstring_append_fmt(ps->code, "%s.a = %s.b;\n", - qstring_get_str(ab_dest), qstring_get_str(ab_dest)); + qstring_append_fmt(ps->code, "ab_out.a = ab_out.b;\n"); } QDECREF(ab_mapping); - QDECREF(ab_dest); + QDECREF(ab_reg); } if (output.cd != PS_REGISTER_DISCARD) { - QString *cd_dest = get_var(ps, output.cd); - QString *cd_mapping = get_output(cd, output.mapping); + QString* cd_reg = qstring_from_fmt("cd_in.%s", write_mask); + QString *cd_mapping = get_output(cd_reg, output.mapping); - qstring_append_fmt(ps->code, "%s.%s = clamp(%s, -1.0, 1.0);\n", - qstring_get_str(cd_dest), write_mask, qstring_get_str(cd_mapping)); + qstring_append_fmt(ps->code, "cd_out.%s = clamp(%s, -1.0, 1.0);\n", + write_mask, qstring_get_str(cd_mapping)); /* FIXME: Will these still write rgb? */ if (!is_alpha && output.flags & PS_COMBINEROUTPUT_CD_BLUE_TO_ALPHA) { - qstring_append_fmt(ps->code, "%s.a = %s.b;\n", - qstring_get_str(cd_dest), qstring_get_str(cd_dest)); + qstring_append_fmt(ps->code, "cd_out.a = cd_out.b;\n"); } QDECREF(cd_mapping); - QDECREF(cd_dest); + QDECREF(cd_reg); } if (output.muxsum != PS_REGISTER_DISCARD) { - QString *sum_dest = get_var(ps, output.muxsum); - QString *sum; if (output.muxsum_op == PS_COMBINEROUTPUT_AB_CD_SUM) { - sum = qstring_from_fmt("(%s + %s)", qstring_get_str(ab), qstring_get_str(cd)); + qstring_append_fmt(ps->code, "sum_in.%s = (ab_in.%s + cd_in.%s);\n", + write_mask, write_mask, write_mask); } else { assert(ps->flags & PS_COMBINERCOUNT_MUX_MSB); - sum = qstring_from_fmt("mix(%s, %s, r0.a < 0.5)", - qstring_get_str(ab), qstring_get_str(cd)); + qstring_append_fmt(ps->code, "sum_in.%s = mix(ab_in.%s, cd_in.%s, r0.a < 0.5);\n", + write_mask, write_mask, write_mask); } - QString *sum_mapping = get_output(sum, output.mapping); - qstring_append_fmt(ps->code, "%s.%s = clamp(%s, -1.0, 1.0);\n", - qstring_get_str(sum_dest), write_mask, qstring_get_str(sum_mapping)); + QString* sum_reg = qstring_from_fmt("sum_in.%s", write_mask); + QString *sum_mapping = get_output(sum_reg, output.mapping); + + qstring_append_fmt(ps->code, "sum_out.%s = clamp(%s, -1.0, 1.0);\n", + write_mask, qstring_get_str(sum_mapping)); - QDECREF(sum); QDECREF(sum_mapping); - QDECREF(sum_dest); + QDECREF(sum_reg); } QDECREF(a); QDECREF(b); QDECREF(c); QDECREF(d); - QDECREF(ab); - QDECREF(cd); +} + +// Add the GLSL code for a stage which does writeback +static void add_stage_code_writeback(struct PixelShader *ps, + struct OutputInfo output, + bool is_alpha) +{ + const char *write_mask = is_alpha ? "a" : "rgb"; + + if (output.ab != PS_REGISTER_DISCARD) { + QString *ab_dest = get_var(ps, output.ab); + qstring_append_fmt(ps->code, "%s.%s = ab_out.%s;\n", qstring_get_str(ab_dest), write_mask, write_mask); + QDECREF(ab_dest); + } + + if (output.cd != PS_REGISTER_DISCARD) { + QString *cd_dest = get_var(ps, output.cd); + qstring_append_fmt(ps->code, "%s.%s = cd_out.%s;\n", qstring_get_str(cd_dest), write_mask, write_mask); + QDECREF(cd_dest); + } + + if (output.muxsum != PS_REGISTER_DISCARD) { + QString *sum_dest = get_var(ps, output.muxsum); + qstring_append_fmt(ps->code, "%s.%s = sum_out.%s;\n", qstring_get_str(sum_dest), write_mask, write_mask); + QDECREF(sum_dest); + } } // Add code for the final combiner stage @@ -603,6 +623,14 @@ static QString* psh_convert(struct PixelShader *ps) qstring_append(vars, "\n"); qstring_append(vars, "vec4 v0 = pD0;\n"); qstring_append(vars, "vec4 v1 = pD1;\n"); + qstring_append(vars, "\n"); + qstring_append(vars, "vec4 ab_in;\n"); + qstring_append(vars, "vec4 ab_out;\n"); + qstring_append(vars, "vec4 cd_in;\n"); + qstring_append(vars, "vec4 cd_out;\n"); + qstring_append(vars, "vec4 sum_in;\n"); + qstring_append(vars, "vec4 sum_out;\n"); + ps->code = qstring_new(); @@ -748,6 +776,8 @@ static QString* psh_convert(struct PixelShader *ps) qstring_append_fmt(ps->code, "// Stage %d\n", i); add_stage_code(ps, ps->stage[i].rgb_input, ps->stage[i].rgb_output, false); add_stage_code(ps, ps->stage[i].alpha_input, ps->stage[i].alpha_output, true); + add_stage_code_writeback(ps, ps->stage[i].rgb_output, false); + add_stage_code_writeback(ps, ps->stage[i].alpha_output, true); } if (ps->final_input.enabled) { From 82202d48dc0a8173b74b00f329c37bf64329bd7a Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Tue, 14 Aug 2018 00:28:31 +0200 Subject: [PATCH 11/17] fixup GLSL bool-mix --- hw/xbox/nv2a/nv2a_psh.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/xbox/nv2a/nv2a_psh.c b/hw/xbox/nv2a/nv2a_psh.c index d8c115d0ec..cff7de2ebd 100644 --- a/hw/xbox/nv2a/nv2a_psh.c +++ b/hw/xbox/nv2a/nv2a_psh.c @@ -484,8 +484,9 @@ static void add_stage_code(struct PixelShader *ps, write_mask, write_mask, write_mask); } else { assert(ps->flags & PS_COMBINERCOUNT_MUX_MSB); - qstring_append_fmt(ps->code, "sum_in.%s = mix(ab_in.%s, cd_in.%s, r0.a < 0.5);\n", - write_mask, write_mask, write_mask); + qstring_append_fmt(ps->code, "sum_in.%s = mix(ab_in.%s, cd_in.%s, %s(r0.a < 0.5));\n", + write_mask, write_mask, write_mask, + is_alpha ? "bool" : "bvec3"); } QString* sum_reg = qstring_from_fmt("sum_in.%s", write_mask); From 25577eab17eed81b1380977748efcc41ec1b87f3 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Tue, 14 Aug 2018 01:12:39 +0200 Subject: [PATCH 12/17] assert muxsum only happens if no dot was done --- hw/xbox/nv2a/nv2a_psh.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hw/xbox/nv2a/nv2a_psh.c b/hw/xbox/nv2a/nv2a_psh.c index cff7de2ebd..3a06f39d26 100644 --- a/hw/xbox/nv2a/nv2a_psh.c +++ b/hw/xbox/nv2a/nv2a_psh.c @@ -479,6 +479,10 @@ static void add_stage_code(struct PixelShader *ps, } if (output.muxsum != PS_REGISTER_DISCARD) { + + assert(output.ab_op != PS_COMBINEROUTPUT_AB_DOT_PRODUCT); + assert(output.cd_op != PS_COMBINEROUTPUT_CD_DOT_PRODUCT); + if (output.muxsum_op == PS_COMBINEROUTPUT_AB_CD_SUM) { qstring_append_fmt(ps->code, "sum_in.%s = (ab_in.%s + cd_in.%s);\n", write_mask, write_mask, write_mask); From c847a7eee0bae457ecc6496fdef0fc5f5cda6d5f Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Tue, 14 Aug 2018 14:28:29 +0200 Subject: [PATCH 13/17] pgraph: Also re-upload surfaces if the address or pitch has changed --- hw/xbox/nv2a/nv2a_pgraph.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/hw/xbox/nv2a/nv2a_pgraph.c b/hw/xbox/nv2a/nv2a_pgraph.c index bcadfd8247..4fdc7a1244 100644 --- a/hw/xbox/nv2a/nv2a_pgraph.c +++ b/hw/xbox/nv2a/nv2a_pgraph.c @@ -741,16 +741,21 @@ void pgraph_method(NV2AState *d, GET_MASK(parameter, NV097_SET_SURFACE_PITCH_COLOR); pg->surface_zeta.pitch = GET_MASK(parameter, NV097_SET_SURFACE_PITCH_ZETA); + + pg->surface_color.buffer_dirty = true; + pg->surface_zeta.buffer_dirty = true; break; case NV097_SET_SURFACE_COLOR_OFFSET: pgraph_update_surface(d, false, true, true); pg->surface_color.offset = parameter; + pg->surface_color.buffer_dirty = true; break; case NV097_SET_SURFACE_ZETA_OFFSET: pgraph_update_surface(d, false, true, true); pg->surface_zeta.offset = parameter; + pg->surface_zeta.buffer_dirty = true; break; case NV097_SET_COMBINER_ALPHA_ICW ... @@ -3370,9 +3375,9 @@ static void pgraph_update_surface_part(NV2AState *d, bool upload, bool color) { } surface->buffer_dirty = false; -#ifdef DEBUG_NV2A + uint8_t *out = data + surface->offset + 64; - NV2A_DPRINTF("upload_surface %s 0x%" HWADDR_PRIx " - 0x%" HWADDR_PRIx ", " + NV2A_GL_DPRINTF(true, "upload_surface %s 0x%" HWADDR_PRIx " - 0x%" HWADDR_PRIx ", " "(0x%" HWADDR_PRIx " - 0x%" HWADDR_PRIx ", " "%d %d, %d %d, %d) - %x %x %x %x\n", color ? "color" : "zeta", @@ -3384,7 +3389,7 @@ static void pgraph_update_surface_part(NV2AState *d, bool upload, bool color) { pg->surface_shape.clip_height, surface->pitch, out[0], out[1], out[2], out[3]); -#endif + } if (!upload && surface->draw_dirty) { @@ -3416,9 +3421,8 @@ static void pgraph_update_surface_part(NV2AState *d, bool upload, bool color) { surface->draw_dirty = false; surface->write_enabled_cache = false; -#ifdef DEBUG_NV2A uint8_t *out = data + surface->offset + 64; - NV2A_DPRINTF("read_surface %s 0x%" HWADDR_PRIx " - 0x%" HWADDR_PRIx ", " + NV2A_GL_DPRINTF(true, "read_surface %s 0x%" HWADDR_PRIx " - 0x%" HWADDR_PRIx ", " "(0x%" HWADDR_PRIx " - 0x%" HWADDR_PRIx ", " "%d %d, %d %d, %d) - %x %x %x %x\n", color ? "color" : "zeta", @@ -3429,7 +3433,6 @@ static void pgraph_update_surface_part(NV2AState *d, bool upload, bool color) { pg->surface_shape.clip_width, pg->surface_shape.clip_height, surface->pitch, out[0], out[1], out[2], out[3]); -#endif } if (swizzle) { From e6f1a22bf295e00f7a550120ac86e151aff1c79a Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Tue, 14 Aug 2018 22:03:46 +0200 Subject: [PATCH 14/17] Add code for debugging an issue --- hw/xbox/nv2a/nv2a_psh.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/xbox/nv2a/nv2a_psh.c b/hw/xbox/nv2a/nv2a_psh.c index 3a06f39d26..918cd6e4fe 100644 --- a/hw/xbox/nv2a/nv2a_psh.c +++ b/hw/xbox/nv2a/nv2a_psh.c @@ -789,6 +789,7 @@ static QString* psh_convert(struct PixelShader *ps) ps->cur_stage = 8; qstring_append(ps->code, "// Final Combiner\n"); add_final_stage_code(ps, ps->final_input); +// qstring_append(ps->code, "fragColor.rgba = vec4(pFog.aaa,1.0);\n"); } if (ps->state.alpha_test && ps->state.alpha_func != ALPHA_FUNC_ALWAYS) { From b1a455fef2c8317397e9337810ea752d211ecf85 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Tue, 14 Aug 2018 22:04:26 +0200 Subject: [PATCH 15/17] non-thaw hack: nan seems to disable fog? but what fog distance is used? --- hw/xbox/nv2a/nv2a_shaders.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/xbox/nv2a/nv2a_shaders.c b/hw/xbox/nv2a/nv2a_shaders.c index 25615d6acd..72f52a5554 100644 --- a/hw/xbox/nv2a/nv2a_shaders.c +++ b/hw/xbox/nv2a/nv2a_shaders.c @@ -715,6 +715,8 @@ STRUCT_VERTEX_DATA); qstring_append(body, " float fogDistance = oFog.x;\n"); } + qstring_append(body, " if (isnan(fogDistance)) { fogDistance = 1.0; }\n"); + /* FIXME: Do this per pixel? */ switch (state.fog_mode) { From c60d11d051c6cf3fe57179704513f6a7d93d30a4 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Tue, 14 Aug 2018 22:05:13 +0200 Subject: [PATCH 16/17] Make sure that fogDistance is positive, is this correct? --- hw/xbox/nv2a/nv2a_shaders.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/xbox/nv2a/nv2a_shaders.c b/hw/xbox/nv2a/nv2a_shaders.c index 72f52a5554..2b9aad4155 100644 --- a/hw/xbox/nv2a/nv2a_shaders.c +++ b/hw/xbox/nv2a/nv2a_shaders.c @@ -719,6 +719,8 @@ STRUCT_VERTEX_DATA); /* FIXME: Do this per pixel? */ + qstring_append(body, " fogDistance = max(fogDistance, 0.0);\n"); + switch (state.fog_mode) { case FOG_MODE_LINEAR: case FOG_MODE_LINEAR_ABS: From ae8b040d5ea6f549d8b36c837d63a74b48a083ac Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Tue, 14 Aug 2018 22:37:13 +0200 Subject: [PATCH 17/17] Use value which seem to be used in D3D fog calc --- hw/xbox/nv2a/nv2a_shaders.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/xbox/nv2a/nv2a_shaders.c b/hw/xbox/nv2a/nv2a_shaders.c index 2b9aad4155..a8afb4a4e1 100644 --- a/hw/xbox/nv2a/nv2a_shaders.c +++ b/hw/xbox/nv2a/nv2a_shaders.c @@ -715,11 +715,12 @@ STRUCT_VERTEX_DATA); qstring_append(body, " float fogDistance = oFog.x;\n"); } - qstring_append(body, " if (isnan(fogDistance)) { fogDistance = 1.0; }\n"); + /* FIXME: Microsoft just decided to use 13 bits, but hardware should have 14?! */ + qstring_append(body, " if (isnan(fogDistance)) { fogDistance = 8192.0; }\n"); /* FIXME: Do this per pixel? */ - qstring_append(body, " fogDistance = max(fogDistance, 0.0);\n"); + qstring_append(body, " fogDistance = clamp(fogDistance, 0.0, 8192.0);\n"); switch (state.fog_mode) { case FOG_MODE_LINEAR: