video_core: Use source3 when GPU_PREVIOUS is used in first stage

This commit is contained in:
GPUCode 2024-02-01 17:29:01 +02:00
parent 7a4854c519
commit 5bb89d6973
7 changed files with 83 additions and 101 deletions

View File

@ -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()};

View File

@ -695,7 +695,7 @@ Common::Vec4<u8> RasterizerSoftware::WriteTevConfig(
* with some basic arithmetic. Alpha combiners can be configured separately but work
* 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> next_combiner_buffer =
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
* 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 = {
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<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"
"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:

View File

@ -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,

View File

@ -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,

View File

@ -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<const TexturingRegs::TevStageConfig>(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<float>(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:

View File

@ -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{};