diff --git a/include/PICA/pica_frag_config.hpp b/include/PICA/pica_frag_config.hpp index 5338f719..89dd3420 100644 --- a/include/PICA/pica_frag_config.hpp +++ b/include/PICA/pica_frag_config.hpp @@ -73,13 +73,7 @@ namespace PICA { BitField<22, 2, u32> shadowSelector; }; - LightingLUTConfig d0{}; - LightingLUTConfig d1{}; - LightingLUTConfig sp{}; - LightingLUTConfig fr{}; - LightingLUTConfig rr{}; - LightingLUTConfig rg{}; - LightingLUTConfig rb{}; + std::array luts{}; std::array lights{}; @@ -116,19 +110,27 @@ namespace PICA { for (int i = 0; i < totalLightCount; i++) { auto& light = lights[i]; - const u32 lightConfig = regs[InternalRegs::Light0Config + 0x10 * i]; - light.num = (regs[InternalRegs::LightPermutation] >> (i * 4)) & 0x7; + + const u32 lightConfig = regs[InternalRegs::Light0Config + 0x10 * light.num]; light.directional = Helpers::getBit<0>(lightConfig); light.twoSidedDiffuse = Helpers::getBit<1>(lightConfig); light.geometricFactor0 = Helpers::getBit<2>(lightConfig); light.geometricFactor1 = Helpers::getBit<3>(lightConfig); - light.shadowEnable = ((config1 >> i) & 1) ^ 1; // This also does 0 = enabled - light.spotAttenuationEnable = ((config1 >> (8 + i)) & 1) ^ 1; // Same here - light.distanceAttenuationEnable = ((config1 >> (24 + i)) & 1) ^ 1; // Of course same here + light.shadowEnable = ((config1 >> light.num) & 1) ^ 1; // This also does 0 = enabled + light.spotAttenuationEnable = ((config1 >> (8 + light.num)) & 1) ^ 1; // Same here + light.distanceAttenuationEnable = ((config1 >> (24 + light.num)) & 1) ^ 1; // Of course same here } + LightingLUTConfig& d0 = luts[Lights::LUT_D0]; + LightingLUTConfig& d1 = luts[Lights::LUT_D1]; + LightingLUTConfig& sp = luts[spotlightLutIndex]; + LightingLUTConfig& fr = luts[Lights::LUT_FR]; + LightingLUTConfig& rb = luts[Lights::LUT_RB]; + LightingLUTConfig& rg = luts[Lights::LUT_RG]; + LightingLUTConfig& rr = luts[Lights::LUT_RR]; + d0.enable = Helpers::getBit<16>(config1) == 0; d1.enable = Helpers::getBit<17>(config1) == 0; fr.enable = Helpers::getBit<19>(config1) == 0; @@ -144,7 +146,7 @@ namespace PICA { if (d0.enable) { d0.absInput = Helpers::getBit<1>(lutAbs) == 0; - d0.type = Helpers::getBits<0, 3>(lutSelect); + d0.type = Helpers::getBits<0, 3>(lutSelect); d0.scale = scales[Helpers::getBits<0, 3>(lutScale)]; } @@ -195,7 +197,31 @@ namespace PICA { return std::memcmp(this, &config, sizeof(FragmentConfig)) == 0; } - FragmentConfig(const std::array& regs) : lighting(regs) {} + FragmentConfig(const std::array& regs) : lighting(regs) { + auto alphaTestConfig = regs[InternalRegs::AlphaTestConfig]; + auto alphaTestFunction = Helpers::getBits<4, 3>(alphaTestConfig); + + outConfig.alphaTestFunction = + (alphaTestConfig & 1) ? static_cast(alphaTestFunction) : PICA::CompareFunction::Always; + outConfig.depthMapEnable = regs[InternalRegs::DepthmapEnable] & 1; + + texConfig.texUnitConfig = regs[InternalRegs::TexUnitCfg]; + texConfig.texEnvUpdateBuffer = regs[InternalRegs::TexEnvUpdateBuffer]; + + // Set up TEV stages. Annoyingly we can't just memcpy as the TEV registers are arranged like + // {Source, Operand, Combiner, Color, Scale} and we want to skip the color register since it's uploaded via UBO +#define setupTevStage(stage) \ + std::memcpy(&texConfig.tevConfigs[stage * 4], ®s[InternalRegs::TexEnv##stage##Source], 3 * sizeof(u32)); \ + texConfig.tevConfigs[stage * 4 + 3] = regs[InternalRegs::TexEnv##stage##Source + 4]; + + setupTevStage(0); + setupTevStage(1); + setupTevStage(2); + setupTevStage(3); + setupTevStage(4); + setupTevStage(5); +#undef setupTevStage + } }; static_assert( diff --git a/include/PICA/regs.hpp b/include/PICA/regs.hpp index 4518e16a..c4d6a5fb 100644 --- a/include/PICA/regs.hpp +++ b/include/PICA/regs.hpp @@ -278,6 +278,11 @@ namespace PICA { }; } + // There's actually 8 different LUTs (SP0-SP7), one for each light with different indices (8-15) + // We use an unused LUT value for "this light source's spotlight" instead and figure out which light source to use in compileLutLookup + // This is particularly intuitive in several places, such as checking if a LUT is enabled + static constexpr int spotlightLutIndex = 2; + enum class TextureFmt : u32 { RGBA8 = 0x0, RGB8 = 0x1, diff --git a/include/PICA/shader_gen.hpp b/include/PICA/shader_gen.hpp index 8cdaadfc..6cf810a0 100644 --- a/include/PICA/shader_gen.hpp +++ b/include/PICA/shader_gen.hpp @@ -14,27 +14,24 @@ namespace PICA::ShaderGen { enum class Language { GLSL }; class FragmentGenerator { - using PICARegs = std::array; API api; Language language; - void compileTEV(std::string& shader, int stage, const PICARegs& regs); - void getSource(std::string& shader, PICA::TexEnvConfig::Source source, int index); - void getColorOperand(std::string& shader, PICA::TexEnvConfig::Source source, PICA::TexEnvConfig::ColorOperand color, int index); - void getAlphaOperand(std::string& shader, PICA::TexEnvConfig::Source source, PICA::TexEnvConfig::AlphaOperand alpha, int index); + void compileTEV(std::string& shader, int stage, const PICA::FragmentConfig& config); + void getSource(std::string& shader, PICA::TexEnvConfig::Source source, int index, const PICA::FragmentConfig& config); + void getColorOperand(std::string& shader, PICA::TexEnvConfig::Source source, PICA::TexEnvConfig::ColorOperand color, int index, const PICA::FragmentConfig& config); + void getAlphaOperand(std::string& shader, PICA::TexEnvConfig::Source source, PICA::TexEnvConfig::AlphaOperand alpha, int index, const PICA::FragmentConfig& config); void getColorOperation(std::string& shader, PICA::TexEnvConfig::Operation op); void getAlphaOperation(std::string& shader, PICA::TexEnvConfig::Operation op); - void applyAlphaTest(std::string& shader, const PICARegs& regs); - void compileLights(std::string& shader, const PICA::FragmentConfig& config, const PICARegs& regs); - void compileLUTLookup(std::string& shader, const PICA::FragmentConfig& config, const PICARegs& regs, u32 lightIndex, u32 lutID); + void applyAlphaTest(std::string& shader, const PICA::FragmentConfig& config); + void compileLights(std::string& shader, const PICA::FragmentConfig& config); + void compileLUTLookup(std::string& shader, const PICA::FragmentConfig& config, u32 lightIndex, u32 lutID); bool isSamplerEnabled(u32 environmentID, u32 lutID); - u32 textureConfig = 0; - public: FragmentGenerator(API api, Language language) : api(api), language(language) {} - std::string generate(const PICARegs& regs, const PICA::FragmentConfig& config); + std::string generate(const PICA::FragmentConfig& config); std::string getDefaultVertexShader(); void setTarget(API api, Language language) { diff --git a/src/core/PICA/shader_gen_glsl.cpp b/src/core/PICA/shader_gen_glsl.cpp index e19c459e..47df58b8 100644 --- a/src/core/PICA/shader_gen_glsl.cpp +++ b/src/core/PICA/shader_gen_glsl.cpp @@ -1,3 +1,5 @@ +#include "PICA/pica_frag_config.hpp" +#include "PICA/regs.hpp" #include "PICA/shader_gen.hpp" using namespace PICA; using namespace PICA::ShaderGen; @@ -29,11 +31,6 @@ static constexpr const char* uniformDefinition = R"( }; )"; -// There's actually 8 different LUTs (SP0-SP7), one for each light with different indices (8-15) -// We use an unused LUT value for "this light source's spotlight" instead and figure out which light source to use in compileLutLookup -// This is particularly intuitive in several places, such as checking if a LUT is enabled -static constexpr int spotlightLutIndex = 2; - std::string FragmentGenerator::getDefaultVertexShader() { std::string ret = ""; @@ -101,7 +98,7 @@ std::string FragmentGenerator::getDefaultVertexShader() { return ret; } -std::string FragmentGenerator::generate(const PICARegs& regs, const FragmentConfig& config) { +std::string FragmentGenerator::generate(const FragmentConfig& config) { std::string ret = ""; switch (api) { @@ -168,7 +165,7 @@ std::string FragmentGenerator::generate(const PICARegs& regs, const FragmentConf vec4 secondaryColor = vec4(0.0); )"; - compileLights(ret, config, regs); + compileLights(ret, config); ret += R"( vec3 colorOp1 = vec3(0.0); @@ -187,44 +184,39 @@ std::string FragmentGenerator::generate(const PICARegs& regs, const FragmentConf float depth = z_over_w * depthScale + depthOffset; )"; - if ((regs[InternalRegs::DepthmapEnable] & 1) == 0) { + if (!config.outConfig.depthMapEnable) { ret += "depth /= gl_FragCoord.w;\n"; } ret += "gl_FragDepth = depth;\n"; - textureConfig = regs[InternalRegs::TexUnitCfg]; for (int i = 0; i < 6; i++) { - compileTEV(ret, i, regs); + compileTEV(ret, i, config); } - applyAlphaTest(ret, regs); + applyAlphaTest(ret, config); ret += "fragColor = combinerOutput;\n}"; // End of main function return ret; } -void FragmentGenerator::compileTEV(std::string& shader, int stage, const PICARegs& regs) { - // Base address for each TEV stage's configuration - static constexpr std::array ioBases = { - InternalRegs::TexEnv0Source, InternalRegs::TexEnv1Source, InternalRegs::TexEnv2Source, - InternalRegs::TexEnv3Source, InternalRegs::TexEnv4Source, InternalRegs::TexEnv5Source, - }; +void FragmentGenerator::compileTEV(std::string& shader, int stage, const PICA::FragmentConfig& config) { + const u32* tevValues = config.texConfig.tevConfigs.data() + stage * 4; - const u32 ioBase = ioBases[stage]; - TexEnvConfig tev(regs[ioBase], regs[ioBase + 1], regs[ioBase + 2], regs[ioBase + 3], regs[ioBase + 4]); + // Pass a 0 to constColor here, as it doesn't matter for compilation + TexEnvConfig tev(tevValues[0], tevValues[1], tevValues[2], 0, tevValues[3]); if (!tev.isPassthroughStage()) { // Get color operands shader += "colorOp1 = "; - getColorOperand(shader, tev.colorSource1, tev.colorOperand1, stage); + getColorOperand(shader, tev.colorSource1, tev.colorOperand1, stage, config); shader += ";\ncolorOp2 = "; - getColorOperand(shader, tev.colorSource2, tev.colorOperand2, stage); + getColorOperand(shader, tev.colorSource2, tev.colorOperand2, stage, config); shader += ";\ncolorOp3 = "; - getColorOperand(shader, tev.colorSource3, tev.colorOperand3, stage); + getColorOperand(shader, tev.colorSource3, tev.colorOperand3, stage, config); shader += ";\nvec3 outputColor" + std::to_string(stage) + " = clamp("; getColorOperation(shader, tev.colorOp); @@ -236,13 +228,13 @@ void FragmentGenerator::compileTEV(std::string& shader, int stage, const PICAReg } else { // Get alpha operands shader += "alphaOp1 = "; - getAlphaOperand(shader, tev.alphaSource1, tev.alphaOperand1, stage); + getAlphaOperand(shader, tev.alphaSource1, tev.alphaOperand1, stage, config); shader += ";\nalphaOp2 = "; - getAlphaOperand(shader, tev.alphaSource2, tev.alphaOperand2, stage); + getAlphaOperand(shader, tev.alphaSource2, tev.alphaOperand2, stage, config); shader += ";\nalphaOp3 = "; - getAlphaOperand(shader, tev.alphaSource3, tev.alphaOperand3, stage); + getAlphaOperand(shader, tev.alphaSource3, tev.alphaOperand3, stage, config); shader += ";\nfloat outputAlpha" + std::to_string(stage) + " = clamp("; getAlphaOperation(shader, tev.alphaOp); @@ -258,7 +250,7 @@ void FragmentGenerator::compileTEV(std::string& shader, int stage, const PICAReg shader += "previousBuffer = tevNextPreviousBuffer;\n\n"; // Update the "next previous buffer" if necessary - const u32 textureEnvUpdateBuffer = regs[InternalRegs::TexEnvUpdateBuffer]; + const u32 textureEnvUpdateBuffer = config.texConfig.texEnvUpdateBuffer; if (stage < 4) { // Check whether to update rgb if ((textureEnvUpdateBuffer & (0x100 << stage))) { @@ -272,7 +264,7 @@ void FragmentGenerator::compileTEV(std::string& shader, int stage, const PICAReg } } -void FragmentGenerator::getColorOperand(std::string& shader, TexEnvConfig::Source source, TexEnvConfig::ColorOperand color, int index) { +void FragmentGenerator::getColorOperand(std::string& shader, TexEnvConfig::Source source, TexEnvConfig::ColorOperand color, int index, const PICA::FragmentConfig& config) { using OperandType = TexEnvConfig::ColorOperand; // For inverting operands, add the 1.0 - x subtraction @@ -284,31 +276,31 @@ void FragmentGenerator::getColorOperand(std::string& shader, TexEnvConfig::Sourc switch (color) { case OperandType::SourceColor: case OperandType::OneMinusSourceColor: - getSource(shader, source, index); + getSource(shader, source, index, config); shader += ".rgb"; break; case OperandType::SourceRed: case OperandType::OneMinusSourceRed: - getSource(shader, source, index); + getSource(shader, source, index, config); shader += ".rrr"; break; case OperandType::SourceGreen: case OperandType::OneMinusSourceGreen: - getSource(shader, source, index); + getSource(shader, source, index, config); shader += ".ggg"; break; case OperandType::SourceBlue: case OperandType::OneMinusSourceBlue: - getSource(shader, source, index); + getSource(shader, source, index, config); shader += ".bbb"; break; case OperandType::SourceAlpha: case OperandType::OneMinusSourceAlpha: - getSource(shader, source, index); + getSource(shader, source, index, config); shader += ".aaa"; break; @@ -319,7 +311,7 @@ void FragmentGenerator::getColorOperand(std::string& shader, TexEnvConfig::Sourc } } -void FragmentGenerator::getAlphaOperand(std::string& shader, TexEnvConfig::Source source, TexEnvConfig::AlphaOperand color, int index) { +void FragmentGenerator::getAlphaOperand(std::string& shader, TexEnvConfig::Source source, TexEnvConfig::AlphaOperand color, int index, const PICA::FragmentConfig& config) { using OperandType = TexEnvConfig::AlphaOperand; // For inverting operands, add the 1.0 - x subtraction @@ -331,25 +323,25 @@ void FragmentGenerator::getAlphaOperand(std::string& shader, TexEnvConfig::Sourc switch (color) { case OperandType::SourceRed: case OperandType::OneMinusSourceRed: - getSource(shader, source, index); + getSource(shader, source, index, config); shader += ".r"; break; case OperandType::SourceGreen: case OperandType::OneMinusSourceGreen: - getSource(shader, source, index); + getSource(shader, source, index, config); shader += ".g"; break; case OperandType::SourceBlue: case OperandType::OneMinusSourceBlue: - getSource(shader, source, index); + getSource(shader, source, index, config); shader += ".b"; break; case OperandType::SourceAlpha: case OperandType::OneMinusSourceAlpha: - getSource(shader, source, index); + getSource(shader, source, index, config); shader += ".a"; break; @@ -360,14 +352,14 @@ void FragmentGenerator::getAlphaOperand(std::string& shader, TexEnvConfig::Sourc } } -void FragmentGenerator::getSource(std::string& shader, TexEnvConfig::Source source, int index) { +void FragmentGenerator::getSource(std::string& shader, TexEnvConfig::Source source, int index, const PICA::FragmentConfig& config) { switch (source) { case TexEnvConfig::Source::PrimaryColor: shader += "v_colour"; break; case TexEnvConfig::Source::Texture0: shader += "texture(u_tex0, v_texcoord0.xy)"; break; case TexEnvConfig::Source::Texture1: shader += "texture(u_tex1, v_texcoord1)"; break; case TexEnvConfig::Source::Texture2: { // If bit 13 in texture config is set then we use the texcoords for texture 1, otherwise for texture 2 - if (Helpers::getBit<13>(textureConfig)) { + if (Helpers::getBit<13>(config.texConfig.texUnitConfig)) { shader += "texture(u_tex2, v_texcoord1)"; } else { shader += "texture(u_tex2, v_texcoord2)"; @@ -428,12 +420,11 @@ void FragmentGenerator::getAlphaOperation(std::string& shader, TexEnvConfig::Ope } } -void FragmentGenerator::applyAlphaTest(std::string& shader, const PICARegs& regs) { - const u32 alphaConfig = regs[InternalRegs::AlphaTestConfig]; - const auto function = static_cast(Helpers::getBits<4, 3>(alphaConfig)); +void FragmentGenerator::applyAlphaTest(std::string& shader, const PICA::FragmentConfig& config) { + const CompareFunction function = config.outConfig.alphaTestFunction; // Alpha test disabled - if (Helpers::getBit<0>(alphaConfig) == 0 || function == CompareFunction::Always) { + if (function == CompareFunction::Always) { return; } @@ -458,7 +449,7 @@ void FragmentGenerator::applyAlphaTest(std::string& shader, const PICARegs& regs shader += ") { discard; }\n"; } -void FragmentGenerator::compileLights(std::string& shader, const PICA::FragmentConfig& config, const PICARegs& regs) { +void FragmentGenerator::compileLights(std::string& shader, const PICA::FragmentConfig& config) { if (!config.lighting.enable) { return; } @@ -481,7 +472,7 @@ void FragmentGenerator::compileLights(std::string& shader, const PICA::FragmentC for (int i = 0; i < config.lighting.lightNum; i++) { lightID = config.lighting.lights[i].num; - const auto& lightConfig = config.lighting.lights[lightID]; + const auto& lightConfig = config.lighting.lights[i]; shader += "light_position = lightSources[" + std::to_string(lightID) + "].position;\n"; if (lightConfig.directional) { // Directional lighting @@ -516,27 +507,27 @@ void FragmentGenerator::compileLights(std::string& shader, const PICA::FragmentC ", int(clamp(floor(distance_att_delta * 256.0), 0.0, 255.0)));\n"; } - compileLUTLookup(shader, config, regs, lightID, spotlightLutIndex); + compileLUTLookup(shader, config, i, spotlightLutIndex); shader += "spotlight_attenuation = lut_lookup_result;\n"; - compileLUTLookup(shader, config, regs, lightID, PICA::Lights::LUT_D0); + compileLUTLookup(shader, config, i, PICA::Lights::LUT_D0); shader += "specular0_dist = lut_lookup_result;\n"; - compileLUTLookup(shader, config, regs, lightID, PICA::Lights::LUT_D1); + compileLUTLookup(shader, config, i, PICA::Lights::LUT_D1); shader += "specular1_dist = lut_lookup_result;\n"; - compileLUTLookup(shader, config, regs, lightID, PICA::Lights::LUT_RR); + compileLUTLookup(shader, config, i, PICA::Lights::LUT_RR); shader += "reflected_color.r = lut_lookup_result;\n"; if (isSamplerEnabled(config.lighting.config, PICA::Lights::LUT_RG)) { - compileLUTLookup(shader, config, regs, lightID, PICA::Lights::LUT_RG); + compileLUTLookup(shader, config, i, PICA::Lights::LUT_RG); shader += "reflected_color.g = lut_lookup_result;\n"; } else { shader += "reflected_color.g = reflected_color.r;\n"; } if (isSamplerEnabled(config.lighting.config, PICA::Lights::LUT_RB)) { - compileLUTLookup(shader, config, regs, lightID, PICA::Lights::LUT_RB); + compileLUTLookup(shader, config, i, PICA::Lights::LUT_RB); shader += "reflected_color.b = lut_lookup_result;\n"; } else { shader += "reflected_color.b = reflected_color.r;\n"; @@ -565,7 +556,7 @@ void FragmentGenerator::compileLights(std::string& shader, const PICA::FragmentC } if (config.lighting.enablePrimaryAlpha || config.lighting.enableSecondaryAlpha) { - compileLUTLookup(shader, config, regs, lightID, PICA::Lights::LUT_FR); + compileLUTLookup(shader, config, config.lighting.lightNum - 1, PICA::Lights::LUT_FR); shader += "float fresnel_factor = lut_lookup_result;\n"; } @@ -602,45 +593,40 @@ bool FragmentGenerator::isSamplerEnabled(u32 environmentID, u32 lutID) { return samplerEnabled[environmentID * 7 + lutID]; } -void FragmentGenerator::compileLUTLookup(std::string& shader, const PICA::FragmentConfig& config, const PICARegs& regs, u32 lightIndex, u32 lutID) { +void FragmentGenerator::compileLUTLookup(std::string& shader, const PICA::FragmentConfig& config, u32 lightIndex, u32 lutID) { + const LightingLUTConfig& lut = config.lighting.luts[lutID]; + uint lightID = config.lighting.lights[lightIndex].num; uint lutIndex = 0; - int bitInConfig1 = 0; + bool lutEnabled = false; if (lutID == spotlightLutIndex) { // These are the spotlight attenuation LUTs - bitInConfig1 = 8 + (lightIndex & 0x7); - lutIndex = 8u + lightIndex; + lutIndex = 8u + lightID; + lutEnabled = config.lighting.lights[lightIndex].spotAttenuationEnable; } else if (lutID <= 6) { - bitInConfig1 = 16 + lutID; lutIndex = lutID; + lutEnabled = lut.enable; } else { Helpers::warn("Shadergen: Unimplemented LUT value"); } const bool samplerEnabled = isSamplerEnabled(config.lighting.config, lutID); - const u32 config1 = regs[InternalRegs::LightConfig1]; - if (!samplerEnabled || ((config1 >> bitInConfig1) & 1)) { + if (!samplerEnabled || !lutEnabled) { shader += "lut_lookup_result = 1.0;\n"; return; } - static constexpr float scales[] = {1.0f, 2.0f, 4.0f, 8.0f, 0.0f, 0.0f, 0.25f, 0.5f}; - const u32 lutAbs = regs[InternalRegs::LightLUTAbs]; - const u32 lutSelect = regs[InternalRegs::LightLUTSelect]; - const u32 lutScale = regs[InternalRegs::LightLUTScale]; - - // The way these bitfields are encoded is so cursed - float scale = scales[(lutScale >> (4 * lutID)) & 0x7]; - uint inputID = (lutSelect >> (4 * lutID)) & 0x7; - bool absEnabled = ((lutAbs >> (4 * lutID + 1)) & 0x1) == 0; // 0 = enabled... + float scale = lut.scale; + uint inputID = lut.type; + bool absEnabled = lut.absInput; switch (inputID) { case 0: shader += "lut_lookup_delta = dot(normal, normalize(half_vector));\n"; break; case 1: shader += "lut_lookup_delta = dot(normalize(v_view), normalize(half_vector));\n"; break; case 2: shader += "lut_lookup_delta = dot(normal, normalize(v_view));\n"; break; case 3: shader += "lut_lookup_delta = dot(normal, light_vector);\n"; break; - case 4: shader += "lut_lookup_delta = dot(light_vector, lightSources[" + std ::to_string(lightIndex) + "].spotlightDirection);\n"; break; + case 4: shader += "lut_lookup_delta = dot(light_vector, lightSources[" + std ::to_string(lightID) + "].spotlightDirection);\n"; break; default: Helpers::warn("Shadergen: Unimplemented LUT select"); diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index 7fca385d..2d39f65f 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -784,37 +784,12 @@ OpenGL::Program& RendererGL::getSpecializedShader() { constexpr uint uboBlockBinding = 2; PICA::FragmentConfig fsConfig(regs); - auto& outConfig = fsConfig.outConfig; - auto& texConfig = fsConfig.texConfig; - - auto alphaTestConfig = regs[InternalRegs::AlphaTestConfig]; - auto alphaTestFunction = Helpers::getBits<4, 3>(alphaTestConfig); - - outConfig.alphaTestFunction = (alphaTestConfig & 1) ? static_cast(alphaTestFunction) : PICA::CompareFunction::Always; - outConfig.depthMapEnable = regs[InternalRegs::DepthmapEnable] & 1; - - texConfig.texUnitConfig = regs[InternalRegs::TexUnitCfg]; - texConfig.texEnvUpdateBuffer = regs[InternalRegs::TexEnvUpdateBuffer]; - - // Set up TEV stages. Annoyingly we can't just memcpy as the TEV registers are arranged like - // {Source, Operand, Combiner, Color, Scale} and we want to skip the color register since it's uploaded via UBO -#define setupTevStage(stage) \ - std::memcpy(&texConfig.tevConfigs[stage * 4], ®s[InternalRegs::TexEnv##stage##Source], 3 * sizeof(u32)); \ - texConfig.tevConfigs[stage * 4 + 3] = regs[InternalRegs::TexEnv##stage##Source + 5]; - - setupTevStage(0); - setupTevStage(1); - setupTevStage(2); - setupTevStage(3); - setupTevStage(4); - setupTevStage(5); -#undef setupTevStage CachedProgram& programEntry = shaderCache[fsConfig]; OpenGL::Program& program = programEntry.program; if (!program.exists()) { - std::string fs = fragShaderGen.generate(regs, fsConfig); + std::string fs = fragShaderGen.generate(fsConfig); OpenGL::Shader fragShader({fs.c_str(), fs.size()}, OpenGL::Fragment); program.create({defaultShadergenVs, fragShader});