video_core: Use source3 when GPU_PREVIOUS is used in first stage (#7411)

This commit is contained in:
GPUCode 2024-02-05 19:53:54 +02:00 committed by GitHub
parent d5a1bd07f3
commit 106364e01e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 83 additions and 101 deletions

View file

@ -846,7 +846,7 @@ void RasterizerAccelerated::SyncTextureBorderColor(int tex_index) {
} }
void RasterizerAccelerated::SyncClipPlane() { 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 auto raw_clip_coef = regs.rasterizer.GetClipCoef();
const Common::Vec4f new_clip_coef = {raw_clip_coef.x.ToFloat32(), raw_clip_coef.y.ToFloat32(), 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()}; raw_clip_coef.z.ToFloat32(), raw_clip_coef.w.ToFloat32()};

View file

@ -695,7 +695,7 @@ Common::Vec4<u8> RasterizerSoftware::WriteTevConfig(
* with some basic arithmetic. Alpha combiners can be configured separately but work * with some basic arithmetic. Alpha combiners can be configured separately but work
* analogously. * analogously.
**/ **/
Common::Vec4<u8> combiner_output = primary_color; Common::Vec4<u8> combiner_output = {0, 0, 0, 0};
Common::Vec4<u8> combiner_buffer = {0, 0, 0, 0}; Common::Vec4<u8> combiner_buffer = {0, 0, 0, 0};
Common::Vec4<u8> next_combiner_buffer = Common::Vec4<u8> next_combiner_buffer =
Common::MakeVec(regs.texturing.tev_combiner_buffer_color.r.Value(), Common::MakeVec(regs.texturing.tev_combiner_buffer_color.r.Value(),
@ -746,9 +746,15 @@ Common::Vec4<u8> RasterizerSoftware::WriteTevConfig(
* combiner_output.rgb(), but instead store it in a temporary variable until * combiner_output.rgb(), but instead store it in a temporary variable until
* alpha combining has been done. * 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<Common::Vec3<u8>, 3> color_result = { const std::array<Common::Vec3<u8>, 3> color_result = {
GetColorModifier(tev_stage.color_modifier1, get_source(tev_stage.color_source1)), GetColorModifier(tev_stage.color_modifier1, get_source(source1)),
GetColorModifier(tev_stage.color_modifier2, get_source(tev_stage.color_source2)), GetColorModifier(tev_stage.color_modifier2, get_source(source2)),
GetColorModifier(tev_stage.color_modifier3, get_source(tev_stage.color_source3)), GetColorModifier(tev_stage.color_modifier3, get_source(tev_stage.color_source3)),
}; };
const Common::Vec3<u8> color_output = ColorCombine(tev_stage.color_op, color_result); const Common::Vec3<u8> color_output = ColorCombine(tev_stage.color_op, color_result);

View file

@ -143,7 +143,7 @@ vec4 secondary_fragment_color = vec4(0.0);
out += "vec4 combiner_buffer = vec4(0.0);\n" out += "vec4 combiner_buffer = vec4(0.0);\n"
"vec4 next_combiner_buffer = tev_combiner_buffer_color;\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" out += "vec3 color_results_1 = vec3(0.0);\n"
"vec3 color_results_2 = 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"; "gl_FragCoord.y < float(scissor_y2))) discard;\n";
} }
void FragmentModule::AppendSource(Pica::TexturingRegs::TevStageConfig::Source source, std::string FragmentModule::GetSource(Pica::TexturingRegs::TevStageConfig::Source source,
u32 tev_index) { u32 tev_index) {
using Source = Pica::TexturingRegs::TevStageConfig::Source; using Source = Pica::TexturingRegs::TevStageConfig::Source;
switch (source) { switch (source) {
case Source::PrimaryColor: case Source::PrimaryColor:
out += "rounded_primary_color"; return "rounded_primary_color";
break;
case Source::PrimaryFragmentColor: case Source::PrimaryFragmentColor:
out += "primary_fragment_color"; return "primary_fragment_color";
break;
case Source::SecondaryFragmentColor: case Source::SecondaryFragmentColor:
out += "secondary_fragment_color"; return "secondary_fragment_color";
break;
case Source::Texture0: case Source::Texture0:
out += "sampleTexUnit0()"; return "sampleTexUnit0()";
break;
case Source::Texture1: case Source::Texture1:
out += "sampleTexUnit1()"; return "sampleTexUnit1()";
break;
case Source::Texture2: case Source::Texture2:
out += "sampleTexUnit2()"; return "sampleTexUnit2()";
break;
case Source::Texture3: case Source::Texture3:
out += "sampleTexUnit3()"; return "sampleTexUnit3()";
break;
case Source::PreviousBuffer: case Source::PreviousBuffer:
out += "combiner_buffer"; return "combiner_buffer";
break;
case Source::Constant: case Source::Constant:
out += fmt::format("const_color[{}]", tev_index); return fmt::format("const_color[{}]", tev_index);
break;
case Source::Previous: case Source::Previous:
out += "combiner_output"; return "combiner_output";
break;
default: default:
out += "vec4(0.0)";
LOG_CRITICAL(Render, "Unknown source op {}", source); LOG_CRITICAL(Render, "Unknown source op {}", source);
break; return "vec4(0.0)";
} }
} }
void FragmentModule::AppendColorModifier( void FragmentModule::AppendColorModifier(
Pica::TexturingRegs::TevStageConfig::ColorModifier modifier, Pica::TexturingRegs::TevStageConfig::ColorModifier modifier,
Pica::TexturingRegs::TevStageConfig::Source source, u32 tev_index) { Pica::TexturingRegs::TevStageConfig::Source source, u32 tev_index) {
using Source = Pica::TexturingRegs::TevStageConfig::Source;
using ColorModifier = Pica::TexturingRegs::TevStageConfig::ColorModifier; 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) { switch (modifier) {
case ColorModifier::SourceColor: case ColorModifier::SourceColor:
AppendSource(source, tev_index); out += fmt::format("{}.rgb", color_source);
out += ".rgb";
break; break;
case ColorModifier::OneMinusSourceColor: case ColorModifier::OneMinusSourceColor:
out += "vec3(1.0) - "; out += fmt::format("vec3(1.0) - {}.rgb", color_source);
AppendSource(source, tev_index);
out += ".rgb";
break; break;
case ColorModifier::SourceAlpha: case ColorModifier::SourceAlpha:
AppendSource(source, tev_index); out += fmt::format("{}.aaa", color_source);
out += ".aaa";
break; break;
case ColorModifier::OneMinusSourceAlpha: case ColorModifier::OneMinusSourceAlpha:
out += "vec3(1.0) - "; out += fmt::format("vec3(1.0) - {}.aaa", color_source);
AppendSource(source, tev_index);
out += ".aaa";
break; break;
case ColorModifier::SourceRed: case ColorModifier::SourceRed:
AppendSource(source, tev_index); out += fmt::format("{}.rrr", color_source);
out += ".rrr";
break; break;
case ColorModifier::OneMinusSourceRed: case ColorModifier::OneMinusSourceRed:
out += "vec3(1.0) - "; out += fmt::format("vec3(1.0) - {}.rrr", color_source);
AppendSource(source, tev_index);
out += ".rrr";
break; break;
case ColorModifier::SourceGreen: case ColorModifier::SourceGreen:
AppendSource(source, tev_index); out += fmt::format("{}.ggg", color_source);
out += ".ggg";
break; break;
case ColorModifier::OneMinusSourceGreen: case ColorModifier::OneMinusSourceGreen:
out += "vec3(1.0) - "; out += fmt::format("vec3(1.0) - {}.ggg", color_source);
AppendSource(source, tev_index);
out += ".ggg";
break; break;
case ColorModifier::SourceBlue: case ColorModifier::SourceBlue:
AppendSource(source, tev_index); out += fmt::format("{}.bbb", color_source);
out += ".bbb";
break; break;
case ColorModifier::OneMinusSourceBlue: case ColorModifier::OneMinusSourceBlue:
out += "vec3(1.0) - "; out += fmt::format("vec3(1.0) - {}.bbb", color_source);
AppendSource(source, tev_index);
out += ".bbb";
break; break;
default: default:
out += "vec3(0.0)"; out += "vec3(0.0)";
@ -326,43 +305,36 @@ void FragmentModule::AppendColorModifier(
void FragmentModule::AppendAlphaModifier( void FragmentModule::AppendAlphaModifier(
Pica::TexturingRegs::TevStageConfig::AlphaModifier modifier, Pica::TexturingRegs::TevStageConfig::AlphaModifier modifier,
Pica::TexturingRegs::TevStageConfig::Source source, u32 tev_index) { Pica::TexturingRegs::TevStageConfig::Source source, u32 tev_index) {
using Source = Pica::TexturingRegs::TevStageConfig::Source;
using AlphaModifier = Pica::TexturingRegs::TevStageConfig::AlphaModifier; 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) { switch (modifier) {
case AlphaModifier::SourceAlpha: case AlphaModifier::SourceAlpha:
AppendSource(source, tev_index); out += fmt::format("{}.a", alpha_source);
out += ".a";
break; break;
case AlphaModifier::OneMinusSourceAlpha: case AlphaModifier::OneMinusSourceAlpha:
out += "1.0 - "; out += fmt::format("1.0 - {}.a", alpha_source);
AppendSource(source, tev_index);
out += ".a";
break; break;
case AlphaModifier::SourceRed: case AlphaModifier::SourceRed:
AppendSource(source, tev_index); out += fmt::format("{}.r", alpha_source);
out += ".r";
break; break;
case AlphaModifier::OneMinusSourceRed: case AlphaModifier::OneMinusSourceRed:
out += "1.0 - "; out += fmt::format("1.0 - {}.r", alpha_source);
AppendSource(source, tev_index);
out += ".r";
break; break;
case AlphaModifier::SourceGreen: case AlphaModifier::SourceGreen:
AppendSource(source, tev_index); out += fmt::format("{}.g", alpha_source);
out += ".g";
break; break;
case AlphaModifier::OneMinusSourceGreen: case AlphaModifier::OneMinusSourceGreen:
out += "1.0 - "; out += fmt::format("1.0 - {}.g", alpha_source);
AppendSource(source, tev_index);
out += ".g";
break; break;
case AlphaModifier::SourceBlue: case AlphaModifier::SourceBlue:
AppendSource(source, tev_index); out += fmt::format("{}.b", alpha_source);
out += ".b";
break; break;
case AlphaModifier::OneMinusSourceBlue: case AlphaModifier::OneMinusSourceBlue:
out += "1.0 - "; out += fmt::format("1.0 - {}.b", alpha_source);
AppendSource(source, tev_index);
out += ".b";
break; break;
default: default:
out += "0.0"; out += "0.0";
@ -384,12 +356,11 @@ void FragmentModule::AppendColorCombiner(Pica::TexturingRegs::TevStageConfig::Op
case Operation::AddSigned: case Operation::AddSigned:
return "color_results_1 + color_results_2 - vec3(0.5)"; return "color_results_1 + color_results_2 - vec3(0.5)";
case Operation::Lerp: case Operation::Lerp:
return "color_results_1 * color_results_3 + color_results_2 * (vec3(1.0) - " return "mix(color_results_2, color_results_1, color_results_3)";
"color_results_3)";
case Operation::Subtract: case Operation::Subtract:
return "color_results_1 - color_results_2"; return "color_results_1 - color_results_2";
case Operation::MultiplyThenAdd: 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: case Operation::AddThenMultiply:
return "min(color_results_1 + color_results_2, vec3(1.0)) * color_results_3"; return "min(color_results_1 + color_results_2, vec3(1.0)) * color_results_3";
case Operation::Dot3_RGB: case Operation::Dot3_RGB:
@ -416,11 +387,11 @@ void FragmentModule::AppendAlphaCombiner(Pica::TexturingRegs::TevStageConfig::Op
case Operation::AddSigned: case Operation::AddSigned:
return "alpha_results_1 + alpha_results_2 - 0.5"; return "alpha_results_1 + alpha_results_2 - 0.5";
case Operation::Lerp: 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: case Operation::Subtract:
return "alpha_results_1 - alpha_results_2"; return "alpha_results_1 - alpha_results_2";
case Operation::MultiplyThenAdd: 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: case Operation::AddThenMultiply:
return "min(alpha_results_1 + alpha_results_2, 1.0) * alpha_results_3"; return "min(alpha_results_1 + alpha_results_2, 1.0) * alpha_results_3";
default: default:

View file

@ -41,8 +41,8 @@ private:
/// Writes the code to emulate PICA min/max blending factors /// Writes the code to emulate PICA min/max blending factors
void WriteBlending(); void WriteBlending();
/// Writes the specified TEV stage source component(s) /// Returns the specified TEV stage source component(s)
void AppendSource(Pica::TexturingRegs::TevStageConfig::Source source, u32 tev_index); std::string GetSource(Pica::TexturingRegs::TevStageConfig::Source source, u32 tev_index);
/// Writes the color components to use for the specified TEV stage color modifier /// Writes the color components to use for the specified TEV stage color modifier
void AppendColorModifier(Pica::TexturingRegs::TevStageConfig::ColorModifier modifier, void AppendColorModifier(Pica::TexturingRegs::TevStageConfig::ColorModifier modifier,

View file

@ -86,7 +86,7 @@ struct PicaUniformsData {
}; };
struct VSUniformData { struct VSUniformData {
bool enable_clip1; u32 enable_clip1;
alignas(16) Common::Vec4f clip_coef; alignas(16) Common::Vec4f clip_coef;
}; };
static_assert(sizeof(VSUniformData) == 32, static_assert(sizeof(VSUniformData) == 32,

View file

@ -55,7 +55,7 @@ void FragmentModule::Generate() {
combiner_buffer = ConstF32(0.f, 0.f, 0.f, 0.f); combiner_buffer = ConstF32(0.f, 0.f, 0.f, 0.f);
next_combiner_buffer = GetShaderDataMember(vec_ids.Get(4), ConstS32(26)); 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 // Write shader bytecode to emulate PICA TEV stages
for (u32 index = 0; index < config.texture.tev_stages.size(); ++index) { for (u32 index = 0; index < config.texture.tev_stages.size(); ++index) {
@ -76,7 +76,7 @@ void FragmentModule::Generate() {
break; break;
} }
Id color{Byteround(last_tex_env_out, 4)}; Id color{Byteround(combiner_output, 4)};
switch (config.framebuffer.logic_op) { switch (config.framebuffer.logic_op) {
case FramebufferRegs::LogicOp::Clear: case FramebufferRegs::LogicOp::Clear:
color = ConstF32(0.f, 0.f, 0.f, 0.f); color = ConstF32(0.f, 0.f, 0.f, 0.f);
@ -184,12 +184,12 @@ void FragmentModule::WriteFog() {
// Blend the fog // Blend the fog
const Id tex_env_rgb{ 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_color{GetShaderDataMember(vec_ids.Get(3), ConstS32(19))};
const Id fog_factor_rgb{ const Id fog_factor_rgb{
OpCompositeConstruct(vec_ids.Get(3), fog_factor, fog_factor, fog_factor)}; 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)}; 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() { void FragmentModule::WriteGas() {
@ -630,8 +630,7 @@ void FragmentModule::WriteLighting() {
} }
void FragmentModule::WriteTevStage(s32 index) { void FragmentModule::WriteTevStage(s32 index) {
const TexturingRegs::TevStageConfig stage = const TexturingRegs::TevStageConfig stage = config.texture.tev_stages[index];
static_cast<const TexturingRegs::TevStageConfig>(config.texture.tev_stages[index]);
// Detects if a TEV stage is configured to be skipped (to avoid generating unnecessary code) // Detects if a TEV stage is configured to be skipped (to avoid generating unnecessary code)
const auto is_passthrough_tev_stage = [](const TevStageConfig& stage) { const auto is_passthrough_tev_stage = [](const TevStageConfig& stage) {
@ -674,18 +673,18 @@ void FragmentModule::WriteTevStage(s32 index) {
alpha_output = alpha_output =
OpFMul(f32_id, alpha_output, ConstF32(static_cast<float>(stage.GetAlphaMultiplier()))); OpFMul(f32_id, alpha_output, ConstF32(static_cast<float>(stage.GetAlphaMultiplier())));
alpha_output = OpFClamp(f32_id, alpha_output, ConstF32(0.f), ConstF32(1.f)); 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; combiner_buffer = next_combiner_buffer;
if (config.TevStageUpdatesCombinerBufferColor(index)) { if (config.TevStageUpdatesCombinerBufferColor(index)) {
next_combiner_buffer = 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)) { if (config.TevStageUpdatesCombinerBufferAlpha(index)) {
next_combiner_buffer = 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::GreaterThan:
case CompareFunc::GreaterThanOrEqual: { case CompareFunc::GreaterThanOrEqual: {
const Id alpha_scaled{ 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 alpha_int{OpConvertFToS(i32_id, alpha_scaled)};
const Id alphatest_ref{GetShaderDataMember(i32_id, ConstS32(1))}; const Id alphatest_ref{GetShaderDataMember(i32_id, ConstS32(1))};
const Id alpha_comp_ref{compare(alpha_int, alphatest_ref)}; 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); 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; using Source = TevStageConfig::Source;
switch (source) { switch (source) {
case Source::PrimaryColor: case Source::PrimaryColor:
@ -1302,7 +1301,7 @@ Id FragmentModule::AppendSource(TevStageConfig::Source source, s32 index) {
case Source::Constant: case Source::Constant:
return GetShaderDataMember(vec_ids.Get(4), ConstS32(25), ConstS32(index)); return GetShaderDataMember(vec_ids.Get(4), ConstS32(25), ConstS32(index));
case Source::Previous: case Source::Previous:
return last_tex_env_out; return combiner_output;
default: default:
LOG_CRITICAL(Render, "Unknown source op {}", source); LOG_CRITICAL(Render, "Unknown source op {}", source);
return ConstF32(0.f, 0.f, 0.f, 0.f); 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, Id FragmentModule::AppendColorModifier(TevStageConfig::ColorModifier modifier,
TevStageConfig::Source source, s32 index) { TevStageConfig::Source source, s32 index) {
using Source = TevStageConfig::Source;
using ColorModifier = TevStageConfig::ColorModifier; 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 Id one_vec{ConstF32(1.f, 1.f, 1.f)};
const auto shuffle = [&](s32 r, s32 g, s32 b) -> Id { 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, Id FragmentModule::AppendAlphaModifier(TevStageConfig::AlphaModifier modifier,
TevStageConfig::Source source, s32 index) { TevStageConfig::Source source, s32 index) {
using Source = TevStageConfig::Source;
using AlphaModifier = TevStageConfig::AlphaModifier; 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 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) { switch (modifier) {
case AlphaModifier::SourceAlpha: case AlphaModifier::SourceAlpha:

View file

@ -99,13 +99,13 @@ private:
/// Lookups the lighting LUT at the provided lut_index /// Lookups the lighting LUT at the provided lut_index
[[nodiscard]] Id LookupLightingLUT(Id lut_index, Id index, Id delta); [[nodiscard]] Id LookupLightingLUT(Id lut_index, Id index, Id delta);
/// Writes the specified TEV stage source component(s) /// Returns the specified TEV stage source component(s)
[[nodiscard]] Id AppendSource(Pica::TexturingRegs::TevStageConfig::Source source, s32 index); [[nodiscard]] Id GetSource(Pica::TexturingRegs::TevStageConfig::Source source, s32 index);
/// Writes the color components to use for the specified TEV stage color modifier /// Writes the color components to use for the specified TEV stage color modifier
[[nodiscard]] Id AppendColorModifier( [[nodiscard]] Id AppendColorModifier(
Pica::TexturingRegs::TevStageConfig::ColorModifier modifier, 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 /// Writes the alpha component to use for the specified TEV stage alpha modifier
[[nodiscard]] Id AppendAlphaModifier( [[nodiscard]] Id AppendAlphaModifier(
@ -272,7 +272,7 @@ private:
Id secondary_fragment_color{}; Id secondary_fragment_color{};
Id combiner_buffer{}; Id combiner_buffer{};
Id next_combiner_buffer{}; Id next_combiner_buffer{};
Id last_tex_env_out{}; Id combiner_output{};
Id color_results_1{}; Id color_results_1{};
Id color_results_2{}; Id color_results_2{};