mirror of
https://github.com/Lime3DS/Lime3DS.git
synced 2026-05-12 15:49:39 -06:00
Fix Graphical Glitches
This commit is contained in:
parent
671188ad6d
commit
241b630262
@ -2,6 +2,8 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include "common/common_types.h"
|
||||
#include "video_core/pica/regs_texturing.h"
|
||||
#include "video_core/shader/generator/glsl_fs_shader_gen.h"
|
||||
@ -14,6 +16,8 @@ using ProcTexCombiner = TexturingRegs::ProcTexCombiner;
|
||||
using ProcTexFilter = TexturingRegs::ProcTexFilter;
|
||||
using TextureType = Pica::TexturingRegs::TextureConfig::TextureType;
|
||||
|
||||
static bool IsPassThroughTevStage(const Pica::TexturingRegs::TevStageConfig& stage);
|
||||
|
||||
constexpr static std::size_t RESERVE_SIZE = 8 * 1024 * 1024;
|
||||
|
||||
enum class Semantic : u32 {
|
||||
@ -113,6 +117,8 @@ FragmentModule::FragmentModule(const FSConfig& config_, const Profile& profile_)
|
||||
|
||||
FragmentModule::~FragmentModule() = default;
|
||||
|
||||
static int debug_frame_counter = 0;
|
||||
|
||||
std::string FragmentModule::Generate() {
|
||||
// We round the interpolated primary color to the nearest 1/255th
|
||||
// This maintains the PICA's 8 bits of precision
|
||||
@ -149,9 +155,18 @@ vec4 secondary_fragment_color = vec4(0.0);
|
||||
"float alpha_results_3 = 0.0;\n";
|
||||
|
||||
// Write shader source to emulate PICA TEV stages
|
||||
bool tev_stage_processed = false;
|
||||
for (u32 index = 0; index < config.texture.tev_stages.size(); index++) {
|
||||
const TexturingRegs::TevStageConfig stage = config.texture.tev_stages[index];
|
||||
if (IsPassThroughTevStage(stage)) {
|
||||
continue;
|
||||
}
|
||||
tev_stage_processed = true;
|
||||
WriteTevStage(index);
|
||||
}
|
||||
if (!tev_stage_processed) {
|
||||
out += "combiner_output = rounded_primary_color;\n";
|
||||
}
|
||||
|
||||
// Append the alpha test condition
|
||||
WriteAlphaTestCondition(config.framebuffer.alpha_test_func);
|
||||
@ -175,12 +190,35 @@ vec4 secondary_fragment_color = vec4(0.0);
|
||||
// Round the final fragment color to maintain the PICA's 8 bits of precision
|
||||
out += "combiner_output = byteround(combiner_output);\n";
|
||||
WriteBlending();
|
||||
out += "color = combiner_output;\n";
|
||||
out += "color = combiner_output;\n return;\n";
|
||||
}
|
||||
|
||||
WriteLogicOp();
|
||||
|
||||
out += '}';
|
||||
|
||||
// Debug logging: only for the first 10 frames
|
||||
if (debug_frame_counter < 10) {
|
||||
std::ofstream log("azahar_tev_debug.txt", std::ios::app);
|
||||
log << "Frame " << debug_frame_counter << ":\n";
|
||||
for (u32 index = 0; index < config.texture.tev_stages.size(); index++) {
|
||||
const TexturingRegs::TevStageConfig& stage = config.texture.tev_stages[index];
|
||||
log << " TEV Stage " << index << ": ";
|
||||
log << "color_op=" << static_cast<int>(stage.color_op.Value()) << ", ";
|
||||
log << "alpha_op=" << static_cast<int>(stage.alpha_op.Value()) << ", ";
|
||||
log << "color_source1=" << static_cast<int>(stage.color_source1.Value()) << ", ";
|
||||
log << "alpha_source1=" << static_cast<int>(stage.alpha_source1.Value()) << ", ";
|
||||
log << "color_modifier1=" << static_cast<int>(stage.color_modifier1.Value()) << ", ";
|
||||
log << "alpha_modifier1=" << static_cast<int>(stage.alpha_modifier1.Value()) << ", ";
|
||||
log << "GetColorMultiplier=" << stage.GetColorMultiplier() << ", ";
|
||||
log << "GetAlphaMultiplier=" << stage.GetAlphaMultiplier() << std::endl;
|
||||
}
|
||||
log << std::setprecision(3) << std::fixed;
|
||||
log << " combiner_output: (unknown at this point, see shader output)\n";
|
||||
log.close();
|
||||
debug_frame_counter++;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
@ -427,13 +465,24 @@ void FragmentModule::WriteAlphaTestCondition(FramebufferRegs::CompareFunc func)
|
||||
// Helper to detect passthrough TEV stages for optimization
|
||||
static bool IsPassThroughTevStage(const Pica::TexturingRegs::TevStageConfig& stage) {
|
||||
using TevStageConfig = Pica::TexturingRegs::TevStageConfig;
|
||||
|
||||
// Never skip Dot3_RGBA stages
|
||||
if (stage.color_op == TevStageConfig::Operation::Dot3_RGBA) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only consider it passthrough if it's a simple replace operation with no modifications
|
||||
return (stage.color_op == TevStageConfig::Operation::Replace &&
|
||||
stage.alpha_op == TevStageConfig::Operation::Replace &&
|
||||
stage.color_source1 == TevStageConfig::Source::Previous &&
|
||||
stage.alpha_source1 == TevStageConfig::Source::Previous &&
|
||||
stage.color_modifier1 == TevStageConfig::ColorModifier::SourceColor &&
|
||||
stage.alpha_modifier1 == TevStageConfig::AlphaModifier::SourceAlpha &&
|
||||
stage.GetColorMultiplier() == 1 && stage.GetAlphaMultiplier() == 1);
|
||||
stage.GetColorMultiplier() == 1 && stage.GetAlphaMultiplier() == 1 &&
|
||||
stage.color_source2 == TevStageConfig::Source::Previous &&
|
||||
stage.alpha_source2 == TevStageConfig::Source::Previous &&
|
||||
stage.color_source3 == TevStageConfig::Source::Previous &&
|
||||
stage.alpha_source3 == TevStageConfig::Source::Previous);
|
||||
}
|
||||
|
||||
void FragmentModule::WriteTevStage(u32 index) {
|
||||
|
||||
@ -17,6 +17,9 @@ using TextureType = TexturingRegs::TextureConfig::TextureType;
|
||||
|
||||
constexpr u32 SPIRV_VERSION_1_3 = 0x00010300;
|
||||
|
||||
// Forward declaration
|
||||
static bool IsPassThroughTevStage(const TexturingRegs::TevStageConfig& stage);
|
||||
|
||||
FragmentModule::FragmentModule(const FSConfig& config_, const Profile& profile_)
|
||||
: Sirit::Module{SPIRV_VERSION_1_3}, config{config_}, profile{profile_},
|
||||
use_fragment_shader_barycentric{profile.has_fragment_shader_barycentric &&
|
||||
@ -58,9 +61,18 @@ void FragmentModule::Generate() {
|
||||
combiner_output = ConstF32(0.f, 0.f, 0.f, 0.f);
|
||||
|
||||
// Write shader bytecode to emulate PICA TEV stages
|
||||
bool tev_stage_processed = false;
|
||||
for (u32 index = 0; index < config.texture.tev_stages.size(); ++index) {
|
||||
const TexturingRegs::TevStageConfig stage = config.texture.tev_stages[index];
|
||||
if (IsPassThroughTevStage(stage)) {
|
||||
continue;
|
||||
}
|
||||
tev_stage_processed = true;
|
||||
WriteTevStage(index);
|
||||
}
|
||||
if (!tev_stage_processed) {
|
||||
combiner_output = ConstF32(1.f, 0.f, 1.f, 1.f); // Debug color: magenta
|
||||
}
|
||||
|
||||
WriteAlphaTestCondition(config.framebuffer.alpha_test_func);
|
||||
|
||||
@ -320,10 +332,19 @@ void FragmentModule::WriteLighting() {
|
||||
|
||||
Id shadow{ConstF32(1.f, 1.f, 1.f, 1.f)};
|
||||
if (lighting.enable_shadow) {
|
||||
shadow = OpFunctionCall(vec_ids.Get(4), sample_tex_unit_func[lighting.shadow_selector]);
|
||||
const Id shadow_texture = OpFunctionCall(vec_ids.Get(4), sample_tex_unit_func[lighting.shadow_selector]);
|
||||
if (lighting.shadow_invert) {
|
||||
shadow = OpFSub(vec_ids.Get(4), ConstF32(1.f, 1.f, 1.f, 1.f), shadow);
|
||||
shadow = OpFSub(vec_ids.Get(4), ConstF32(1.f, 1.f, 1.f, 1.f), shadow_texture);
|
||||
} else {
|
||||
shadow = shadow_texture;
|
||||
}
|
||||
// Debug: Output shadow value directly
|
||||
OpStore(color_id, shadow);
|
||||
OpReturn();
|
||||
OpFunctionEnd();
|
||||
return;
|
||||
} else {
|
||||
shadow = ConstF32(1.f, 1.f, 1.f, 1.f);
|
||||
}
|
||||
|
||||
const auto lookup_lighting_lut_unsigned = [this](Id lut_index, Id pos) -> Id {
|
||||
@ -1598,4 +1619,27 @@ std::vector<u32> GenerateFragmentShader(const FSConfig& config, const Profile& p
|
||||
return module.Assemble();
|
||||
}
|
||||
|
||||
// Helper to detect passthrough TEV stages for optimization
|
||||
static bool IsPassThroughTevStage(const TexturingRegs::TevStageConfig& stage) {
|
||||
using TevStageConfig = TexturingRegs::TevStageConfig;
|
||||
|
||||
// Never skip Dot3_RGBA stages
|
||||
if (stage.color_op == TevStageConfig::Operation::Dot3_RGBA) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only consider it passthrough if it's a simple replace operation with no modifications
|
||||
return (stage.color_op == TevStageConfig::Operation::Replace &&
|
||||
stage.alpha_op == TevStageConfig::Operation::Replace &&
|
||||
stage.color_source1 == TevStageConfig::Source::Previous &&
|
||||
stage.alpha_source1 == TevStageConfig::Source::Previous &&
|
||||
stage.color_modifier1 == TevStageConfig::ColorModifier::SourceColor &&
|
||||
stage.alpha_modifier1 == TevStageConfig::AlphaModifier::SourceAlpha &&
|
||||
stage.GetColorMultiplier() == 1 && stage.GetAlphaMultiplier() == 1 &&
|
||||
stage.color_source2 == TevStageConfig::Source::Previous &&
|
||||
stage.alpha_source2 == TevStageConfig::Source::Previous &&
|
||||
stage.color_source3 == TevStageConfig::Source::Previous &&
|
||||
stage.alpha_source3 == TevStageConfig::Source::Previous);
|
||||
}
|
||||
|
||||
} // namespace Pica::Shader::Generator::SPIRV
|
||||
|
||||
Loading…
Reference in New Issue
Block a user