From 106364e01eb3a51190593b99b45504c5fac29072 Mon Sep 17 00:00:00 2001 From: GPUCode <47210458+GPUCode@users.noreply.github.com> Date: Mon, 5 Feb 2024 19:53:54 +0200 Subject: [PATCH] video_core: Use source3 when GPU_PREVIOUS is used in first stage (#7411) --- src/video_core/rasterizer_accelerated.cpp | 2 +- .../renderer_software/sw_rasterizer.cpp | 12 +- .../shader/generator/glsl_fs_shader_gen.cpp | 121 +++++++----------- .../shader/generator/glsl_fs_shader_gen.h | 4 +- .../shader/generator/shader_uniforms.h | 2 +- .../shader/generator/spv_fs_shader_gen.cpp | 35 ++--- .../shader/generator/spv_fs_shader_gen.h | 8 +- 7 files changed, 83 insertions(+), 101 deletions(-) diff --git a/src/video_core/rasterizer_accelerated.cpp b/src/video_core/rasterizer_accelerated.cpp index 6c97f25ba..d44c23014 100644 --- a/src/video_core/rasterizer_accelerated.cpp +++ b/src/video_core/rasterizer_accelerated.cpp @@ -846,7 +846,7 @@ void RasterizerAccelerated::SyncTextureBorderColor(int tex_index) { } void RasterizerAccelerated::SyncClipPlane() { - const bool enable_clip1 = regs.rasterizer.clip_enable != 0; + const u32 enable_clip1 = regs.rasterizer.clip_enable != 0; const auto raw_clip_coef = regs.rasterizer.GetClipCoef(); const Common::Vec4f new_clip_coef = {raw_clip_coef.x.ToFloat32(), raw_clip_coef.y.ToFloat32(), raw_clip_coef.z.ToFloat32(), raw_clip_coef.w.ToFloat32()}; diff --git a/src/video_core/renderer_software/sw_rasterizer.cpp b/src/video_core/renderer_software/sw_rasterizer.cpp index f0f290ebe..36aa2b03b 100644 --- a/src/video_core/renderer_software/sw_rasterizer.cpp +++ b/src/video_core/renderer_software/sw_rasterizer.cpp @@ -695,7 +695,7 @@ Common::Vec4 RasterizerSoftware::WriteTevConfig( * with some basic arithmetic. Alpha combiners can be configured separately but work * analogously. **/ - Common::Vec4 combiner_output = primary_color; + Common::Vec4 combiner_output = {0, 0, 0, 0}; Common::Vec4 combiner_buffer = {0, 0, 0, 0}; Common::Vec4 next_combiner_buffer = Common::MakeVec(regs.texturing.tev_combiner_buffer_color.r.Value(), @@ -746,9 +746,15 @@ Common::Vec4 RasterizerSoftware::WriteTevConfig( * combiner_output.rgb(), but instead store it in a temporary variable until * alpha combining has been done. **/ + const auto source1 = tev_stage_index == 0 && tev_stage.color_source1 == Source::Previous + ? tev_stage.color_source3.Value() + : tev_stage.color_source1.Value(); + const auto source2 = tev_stage_index == 0 && tev_stage.color_source2 == Source::Previous + ? tev_stage.color_source3.Value() + : tev_stage.color_source2.Value(); const std::array, 3> color_result = { - GetColorModifier(tev_stage.color_modifier1, get_source(tev_stage.color_source1)), - GetColorModifier(tev_stage.color_modifier2, get_source(tev_stage.color_source2)), + GetColorModifier(tev_stage.color_modifier1, get_source(source1)), + GetColorModifier(tev_stage.color_modifier2, get_source(source2)), GetColorModifier(tev_stage.color_modifier3, get_source(tev_stage.color_source3)), }; const Common::Vec3 color_output = ColorCombine(tev_stage.color_op, color_result); diff --git a/src/video_core/shader/generator/glsl_fs_shader_gen.cpp b/src/video_core/shader/generator/glsl_fs_shader_gen.cpp index c5847ab99..852f6eed8 100644 --- a/src/video_core/shader/generator/glsl_fs_shader_gen.cpp +++ b/src/video_core/shader/generator/glsl_fs_shader_gen.cpp @@ -143,7 +143,7 @@ vec4 secondary_fragment_color = vec4(0.0); out += "vec4 combiner_buffer = vec4(0.0);\n" "vec4 next_combiner_buffer = tev_combiner_buffer_color;\n" - "vec4 combiner_output = rounded_primary_color;\n"; + "vec4 combiner_output = vec4(0.0);\n"; out += "vec3 color_results_1 = vec3(0.0);\n" "vec3 color_results_2 = vec3(0.0);\n" @@ -225,96 +225,75 @@ void FragmentModule::WriteScissor() { "gl_FragCoord.y < float(scissor_y2))) discard;\n"; } -void FragmentModule::AppendSource(Pica::TexturingRegs::TevStageConfig::Source source, - u32 tev_index) { +std::string FragmentModule::GetSource(Pica::TexturingRegs::TevStageConfig::Source source, + u32 tev_index) { using Source = Pica::TexturingRegs::TevStageConfig::Source; switch (source) { case Source::PrimaryColor: - out += "rounded_primary_color"; - break; + return "rounded_primary_color"; case Source::PrimaryFragmentColor: - out += "primary_fragment_color"; - break; + return "primary_fragment_color"; case Source::SecondaryFragmentColor: - out += "secondary_fragment_color"; - break; + return "secondary_fragment_color"; case Source::Texture0: - out += "sampleTexUnit0()"; - break; + return "sampleTexUnit0()"; case Source::Texture1: - out += "sampleTexUnit1()"; - break; + return "sampleTexUnit1()"; case Source::Texture2: - out += "sampleTexUnit2()"; - break; + return "sampleTexUnit2()"; case Source::Texture3: - out += "sampleTexUnit3()"; - break; + return "sampleTexUnit3()"; case Source::PreviousBuffer: - out += "combiner_buffer"; - break; + return "combiner_buffer"; case Source::Constant: - out += fmt::format("const_color[{}]", tev_index); - break; + return fmt::format("const_color[{}]", tev_index); case Source::Previous: - out += "combiner_output"; - break; + return "combiner_output"; default: - out += "vec4(0.0)"; LOG_CRITICAL(Render, "Unknown source op {}", source); - break; + return "vec4(0.0)"; } } void FragmentModule::AppendColorModifier( Pica::TexturingRegs::TevStageConfig::ColorModifier modifier, Pica::TexturingRegs::TevStageConfig::Source source, u32 tev_index) { + using Source = Pica::TexturingRegs::TevStageConfig::Source; using ColorModifier = Pica::TexturingRegs::TevStageConfig::ColorModifier; + const TexturingRegs::TevStageConfig stage = config.texture.tev_stages[tev_index]; + const bool force_source3 = tev_index == 0 && source == Source::Previous; + const auto color_source = + GetSource(force_source3 ? stage.color_source3.Value() : source, tev_index); switch (modifier) { case ColorModifier::SourceColor: - AppendSource(source, tev_index); - out += ".rgb"; + out += fmt::format("{}.rgb", color_source); break; case ColorModifier::OneMinusSourceColor: - out += "vec3(1.0) - "; - AppendSource(source, tev_index); - out += ".rgb"; + out += fmt::format("vec3(1.0) - {}.rgb", color_source); break; case ColorModifier::SourceAlpha: - AppendSource(source, tev_index); - out += ".aaa"; + out += fmt::format("{}.aaa", color_source); break; case ColorModifier::OneMinusSourceAlpha: - out += "vec3(1.0) - "; - AppendSource(source, tev_index); - out += ".aaa"; + out += fmt::format("vec3(1.0) - {}.aaa", color_source); break; case ColorModifier::SourceRed: - AppendSource(source, tev_index); - out += ".rrr"; + out += fmt::format("{}.rrr", color_source); break; case ColorModifier::OneMinusSourceRed: - out += "vec3(1.0) - "; - AppendSource(source, tev_index); - out += ".rrr"; + out += fmt::format("vec3(1.0) - {}.rrr", color_source); break; case ColorModifier::SourceGreen: - AppendSource(source, tev_index); - out += ".ggg"; + out += fmt::format("{}.ggg", color_source); break; case ColorModifier::OneMinusSourceGreen: - out += "vec3(1.0) - "; - AppendSource(source, tev_index); - out += ".ggg"; + out += fmt::format("vec3(1.0) - {}.ggg", color_source); break; case ColorModifier::SourceBlue: - AppendSource(source, tev_index); - out += ".bbb"; + out += fmt::format("{}.bbb", color_source); break; case ColorModifier::OneMinusSourceBlue: - out += "vec3(1.0) - "; - AppendSource(source, tev_index); - out += ".bbb"; + out += fmt::format("vec3(1.0) - {}.bbb", color_source); break; default: out += "vec3(0.0)"; @@ -326,43 +305,36 @@ void FragmentModule::AppendColorModifier( void FragmentModule::AppendAlphaModifier( Pica::TexturingRegs::TevStageConfig::AlphaModifier modifier, Pica::TexturingRegs::TevStageConfig::Source source, u32 tev_index) { + using Source = Pica::TexturingRegs::TevStageConfig::Source; using AlphaModifier = Pica::TexturingRegs::TevStageConfig::AlphaModifier; + const TexturingRegs::TevStageConfig stage = config.texture.tev_stages[tev_index]; + const bool force_source3 = tev_index == 0 && source == Source::Previous; + const auto alpha_source = + GetSource(force_source3 ? stage.alpha_source3.Value() : source, tev_index); switch (modifier) { case AlphaModifier::SourceAlpha: - AppendSource(source, tev_index); - out += ".a"; + out += fmt::format("{}.a", alpha_source); break; case AlphaModifier::OneMinusSourceAlpha: - out += "1.0 - "; - AppendSource(source, tev_index); - out += ".a"; + out += fmt::format("1.0 - {}.a", alpha_source); break; case AlphaModifier::SourceRed: - AppendSource(source, tev_index); - out += ".r"; + out += fmt::format("{}.r", alpha_source); break; case AlphaModifier::OneMinusSourceRed: - out += "1.0 - "; - AppendSource(source, tev_index); - out += ".r"; + out += fmt::format("1.0 - {}.r", alpha_source); break; case AlphaModifier::SourceGreen: - AppendSource(source, tev_index); - out += ".g"; + out += fmt::format("{}.g", alpha_source); break; case AlphaModifier::OneMinusSourceGreen: - out += "1.0 - "; - AppendSource(source, tev_index); - out += ".g"; + out += fmt::format("1.0 - {}.g", alpha_source); break; case AlphaModifier::SourceBlue: - AppendSource(source, tev_index); - out += ".b"; + out += fmt::format("{}.b", alpha_source); break; case AlphaModifier::OneMinusSourceBlue: - out += "1.0 - "; - AppendSource(source, tev_index); - out += ".b"; + out += fmt::format("1.0 - {}.b", alpha_source); break; default: out += "0.0"; @@ -384,12 +356,11 @@ void FragmentModule::AppendColorCombiner(Pica::TexturingRegs::TevStageConfig::Op case Operation::AddSigned: return "color_results_1 + color_results_2 - vec3(0.5)"; case Operation::Lerp: - return "color_results_1 * color_results_3 + color_results_2 * (vec3(1.0) - " - "color_results_3)"; + return "mix(color_results_2, color_results_1, color_results_3)"; case Operation::Subtract: return "color_results_1 - color_results_2"; case Operation::MultiplyThenAdd: - return "color_results_1 * color_results_2 + color_results_3"; + return "fma(color_results_1, color_results_2, color_results_3)"; case Operation::AddThenMultiply: return "min(color_results_1 + color_results_2, vec3(1.0)) * color_results_3"; case Operation::Dot3_RGB: @@ -416,11 +387,11 @@ void FragmentModule::AppendAlphaCombiner(Pica::TexturingRegs::TevStageConfig::Op case Operation::AddSigned: return "alpha_results_1 + alpha_results_2 - 0.5"; case Operation::Lerp: - return "alpha_results_1 * alpha_results_3 + alpha_results_2 * (1.0 - alpha_results_3)"; + return "mix(alpha_results_2, alpha_results_1, alpha_results_3)"; case Operation::Subtract: return "alpha_results_1 - alpha_results_2"; case Operation::MultiplyThenAdd: - return "alpha_results_1 * alpha_results_2 + alpha_results_3"; + return "fma(alpha_results_1, alpha_results_2, alpha_results_3)"; case Operation::AddThenMultiply: return "min(alpha_results_1 + alpha_results_2, 1.0) * alpha_results_3"; default: diff --git a/src/video_core/shader/generator/glsl_fs_shader_gen.h b/src/video_core/shader/generator/glsl_fs_shader_gen.h index f8541f1fe..a7eff4c44 100644 --- a/src/video_core/shader/generator/glsl_fs_shader_gen.h +++ b/src/video_core/shader/generator/glsl_fs_shader_gen.h @@ -41,8 +41,8 @@ private: /// Writes the code to emulate PICA min/max blending factors void WriteBlending(); - /// Writes the specified TEV stage source component(s) - void AppendSource(Pica::TexturingRegs::TevStageConfig::Source source, u32 tev_index); + /// Returns the specified TEV stage source component(s) + std::string GetSource(Pica::TexturingRegs::TevStageConfig::Source source, u32 tev_index); /// Writes the color components to use for the specified TEV stage color modifier void AppendColorModifier(Pica::TexturingRegs::TevStageConfig::ColorModifier modifier, diff --git a/src/video_core/shader/generator/shader_uniforms.h b/src/video_core/shader/generator/shader_uniforms.h index e5cc9ba0a..6c79180e7 100644 --- a/src/video_core/shader/generator/shader_uniforms.h +++ b/src/video_core/shader/generator/shader_uniforms.h @@ -86,7 +86,7 @@ struct PicaUniformsData { }; struct VSUniformData { - bool enable_clip1; + u32 enable_clip1; alignas(16) Common::Vec4f clip_coef; }; static_assert(sizeof(VSUniformData) == 32, diff --git a/src/video_core/shader/generator/spv_fs_shader_gen.cpp b/src/video_core/shader/generator/spv_fs_shader_gen.cpp index 1703ce8dd..5f3158a73 100644 --- a/src/video_core/shader/generator/spv_fs_shader_gen.cpp +++ b/src/video_core/shader/generator/spv_fs_shader_gen.cpp @@ -55,7 +55,7 @@ void FragmentModule::Generate() { combiner_buffer = ConstF32(0.f, 0.f, 0.f, 0.f); next_combiner_buffer = GetShaderDataMember(vec_ids.Get(4), ConstS32(26)); - last_tex_env_out = rounded_primary_color; + combiner_output = ConstF32(0.f, 0.f, 0.f, 0.f); // Write shader bytecode to emulate PICA TEV stages for (u32 index = 0; index < config.texture.tev_stages.size(); ++index) { @@ -76,7 +76,7 @@ void FragmentModule::Generate() { break; } - Id color{Byteround(last_tex_env_out, 4)}; + Id color{Byteround(combiner_output, 4)}; switch (config.framebuffer.logic_op) { case FramebufferRegs::LogicOp::Clear: color = ConstF32(0.f, 0.f, 0.f, 0.f); @@ -184,12 +184,12 @@ void FragmentModule::WriteFog() { // Blend the fog const Id tex_env_rgb{ - OpVectorShuffle(vec_ids.Get(3), last_tex_env_out, last_tex_env_out, 0, 1, 2)}; + OpVectorShuffle(vec_ids.Get(3), combiner_output, combiner_output, 0, 1, 2)}; const Id fog_color{GetShaderDataMember(vec_ids.Get(3), ConstS32(19))}; const Id fog_factor_rgb{ OpCompositeConstruct(vec_ids.Get(3), fog_factor, fog_factor, fog_factor)}; const Id fog_result{OpFMix(vec_ids.Get(3), fog_color, tex_env_rgb, fog_factor_rgb)}; - last_tex_env_out = OpVectorShuffle(vec_ids.Get(4), fog_result, last_tex_env_out, 0, 1, 2, 6); + combiner_output = OpVectorShuffle(vec_ids.Get(4), fog_result, combiner_output, 0, 1, 2, 6); } void FragmentModule::WriteGas() { @@ -630,8 +630,7 @@ void FragmentModule::WriteLighting() { } void FragmentModule::WriteTevStage(s32 index) { - const TexturingRegs::TevStageConfig stage = - static_cast(config.texture.tev_stages[index]); + const TexturingRegs::TevStageConfig stage = config.texture.tev_stages[index]; // Detects if a TEV stage is configured to be skipped (to avoid generating unnecessary code) const auto is_passthrough_tev_stage = [](const TevStageConfig& stage) { @@ -674,18 +673,18 @@ void FragmentModule::WriteTevStage(s32 index) { alpha_output = OpFMul(f32_id, alpha_output, ConstF32(static_cast(stage.GetAlphaMultiplier()))); alpha_output = OpFClamp(f32_id, alpha_output, ConstF32(0.f), ConstF32(1.f)); - last_tex_env_out = OpCompositeConstruct(vec_ids.Get(4), color_output, alpha_output); + combiner_output = OpCompositeConstruct(vec_ids.Get(4), color_output, alpha_output); } combiner_buffer = next_combiner_buffer; if (config.TevStageUpdatesCombinerBufferColor(index)) { next_combiner_buffer = - OpVectorShuffle(vec_ids.Get(4), last_tex_env_out, next_combiner_buffer, 0, 1, 2, 7); + OpVectorShuffle(vec_ids.Get(4), combiner_output, next_combiner_buffer, 0, 1, 2, 7); } if (config.TevStageUpdatesCombinerBufferAlpha(index)) { next_combiner_buffer = - OpVectorShuffle(vec_ids.Get(4), next_combiner_buffer, last_tex_env_out, 0, 1, 2, 7); + OpVectorShuffle(vec_ids.Get(4), next_combiner_buffer, combiner_output, 0, 1, 2, 7); } } @@ -728,7 +727,7 @@ void FragmentModule::WriteAlphaTestCondition(FramebufferRegs::CompareFunc func) case CompareFunc::GreaterThan: case CompareFunc::GreaterThanOrEqual: { const Id alpha_scaled{ - OpFMul(f32_id, OpCompositeExtract(f32_id, last_tex_env_out, 3), ConstF32(255.f))}; + OpFMul(f32_id, OpCompositeExtract(f32_id, combiner_output, 3), ConstF32(255.f))}; const Id alpha_int{OpConvertFToS(i32_id, alpha_scaled)}; const Id alphatest_ref{GetShaderDataMember(i32_id, ConstS32(1))}; const Id alpha_comp_ref{compare(alpha_int, alphatest_ref)}; @@ -1280,7 +1279,7 @@ Id FragmentModule::LookupLightingLUT(Id lut_index, Id index, Id delta) { return OpFma(f32_id, entry_g, delta, entry_r); } -Id FragmentModule::AppendSource(TevStageConfig::Source source, s32 index) { +Id FragmentModule::GetSource(TevStageConfig::Source source, s32 index) { using Source = TevStageConfig::Source; switch (source) { case Source::PrimaryColor: @@ -1302,7 +1301,7 @@ Id FragmentModule::AppendSource(TevStageConfig::Source source, s32 index) { case Source::Constant: return GetShaderDataMember(vec_ids.Get(4), ConstS32(25), ConstS32(index)); case Source::Previous: - return last_tex_env_out; + return combiner_output; default: LOG_CRITICAL(Render, "Unknown source op {}", source); return ConstF32(0.f, 0.f, 0.f, 0.f); @@ -1311,8 +1310,11 @@ Id FragmentModule::AppendSource(TevStageConfig::Source source, s32 index) { Id FragmentModule::AppendColorModifier(TevStageConfig::ColorModifier modifier, TevStageConfig::Source source, s32 index) { + using Source = TevStageConfig::Source; using ColorModifier = TevStageConfig::ColorModifier; - const Id source_color{AppendSource(source, index)}; + const TexturingRegs::TevStageConfig stage = config.texture.tev_stages[index]; + const bool force_source3 = index == 0 && source == Source::Previous; + const Id source_color{GetSource(force_source3 ? stage.color_source3.Value() : source, index)}; const Id one_vec{ConstF32(1.f, 1.f, 1.f)}; const auto shuffle = [&](s32 r, s32 g, s32 b) -> Id { @@ -1348,11 +1350,14 @@ Id FragmentModule::AppendColorModifier(TevStageConfig::ColorModifier modifier, Id FragmentModule::AppendAlphaModifier(TevStageConfig::AlphaModifier modifier, TevStageConfig::Source source, s32 index) { + using Source = TevStageConfig::Source; using AlphaModifier = TevStageConfig::AlphaModifier; - const Id source_color{AppendSource(source, index)}; + const TexturingRegs::TevStageConfig stage = config.texture.tev_stages[index]; + const bool force_source3 = index == 0 && source == Source::Previous; + const Id source_alpha{GetSource(force_source3 ? stage.alpha_source3.Value() : source, index)}; const Id one_f32{ConstF32(1.f)}; - const auto component = [&](s32 c) -> Id { return OpCompositeExtract(f32_id, source_color, c); }; + const auto component = [&](s32 c) -> Id { return OpCompositeExtract(f32_id, source_alpha, c); }; switch (modifier) { case AlphaModifier::SourceAlpha: diff --git a/src/video_core/shader/generator/spv_fs_shader_gen.h b/src/video_core/shader/generator/spv_fs_shader_gen.h index 875ac33bf..cbbede01f 100644 --- a/src/video_core/shader/generator/spv_fs_shader_gen.h +++ b/src/video_core/shader/generator/spv_fs_shader_gen.h @@ -99,13 +99,13 @@ private: /// Lookups the lighting LUT at the provided lut_index [[nodiscard]] Id LookupLightingLUT(Id lut_index, Id index, Id delta); - /// Writes the specified TEV stage source component(s) - [[nodiscard]] Id AppendSource(Pica::TexturingRegs::TevStageConfig::Source source, s32 index); + /// Returns the specified TEV stage source component(s) + [[nodiscard]] Id GetSource(Pica::TexturingRegs::TevStageConfig::Source source, s32 index); /// Writes the color components to use for the specified TEV stage color modifier [[nodiscard]] Id AppendColorModifier( Pica::TexturingRegs::TevStageConfig::ColorModifier modifier, - Pica::TexturingRegs::TevStageConfig::Source source, s32 index); + Pica::TexturingRegs::TevStageConfig::Source source, s32 tev_index); /// Writes the alpha component to use for the specified TEV stage alpha modifier [[nodiscard]] Id AppendAlphaModifier( @@ -272,7 +272,7 @@ private: Id secondary_fragment_color{}; Id combiner_buffer{}; Id next_combiner_buffer{}; - Id last_tex_env_out{}; + Id combiner_output{}; Id color_results_1{}; Id color_results_2{};