Remove dependency of PICA regs in fragment config

This commit is contained in:
offtkp 2024-07-19 23:44:26 +03:00
parent eb7e02fbc2
commit ce4146f9ba
4 changed files with 90 additions and 90 deletions

View file

@ -81,6 +81,11 @@ namespace PICA {
LightingLUTConfig rg{}; LightingLUTConfig rg{};
LightingLUTConfig rb{}; LightingLUTConfig rb{};
u32 config1;
u32 lutAbs;
u32 lutScale;
u32 lutSelect;
std::array<Light, 8> lights{}; std::array<Light, 8> lights{};
LightingConfig(const std::array<u32, 0x300>& regs) { LightingConfig(const std::array<u32, 0x300>& regs) {
@ -90,9 +95,13 @@ namespace PICA {
} }
const u32 config0 = regs[InternalRegs::LightConfig0]; const u32 config0 = regs[InternalRegs::LightConfig0];
const u32 config1 = regs[InternalRegs::LightConfig1];
const u32 totalLightCount = Helpers::getBits<0, 3>(regs[InternalRegs::LightNumber]) + 1; const u32 totalLightCount = Helpers::getBits<0, 3>(regs[InternalRegs::LightNumber]) + 1;
config1 = regs[InternalRegs::LightConfig1];
lutAbs = regs[InternalRegs::LightLUTAbs];
lutScale = regs[InternalRegs::LightLUTScale];
lutSelect = regs[InternalRegs::LightLUTSelect];
enable = 1; enable = 1;
lightNum = totalLightCount; lightNum = totalLightCount;
@ -195,7 +204,31 @@ namespace PICA {
return std::memcmp(this, &config, sizeof(FragmentConfig)) == 0; return std::memcmp(this, &config, sizeof(FragmentConfig)) == 0;
} }
FragmentConfig(const std::array<u32, 0x300>& regs) : lighting(regs) {} FragmentConfig(const std::array<u32, 0x300>& regs) : lighting(regs)
{
auto alphaTestConfig = regs[InternalRegs::AlphaTestConfig];
auto alphaTestFunction = Helpers::getBits<4, 3>(alphaTestConfig);
outConfig.alphaTestFunction = (alphaTestConfig & 1) ? static_cast<PICA::CompareFunction>(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], &regs[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
}
}; };
static_assert( static_assert(

View file

@ -14,27 +14,24 @@ namespace PICA::ShaderGen {
enum class Language { GLSL }; enum class Language { GLSL };
class FragmentGenerator { class FragmentGenerator {
using PICARegs = std::array<u32, 0x300>;
API api; API api;
Language language; Language language;
void compileTEV(std::string& shader, int stage, const PICARegs& regs); void compileTEV(std::string& shader, int stage, const PICA::FragmentConfig& config);
void getSource(std::string& shader, PICA::TexEnvConfig::Source source, int index); 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); 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); 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 getColorOperation(std::string& shader, PICA::TexEnvConfig::Operation op);
void getAlphaOperation(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 applyAlphaTest(std::string& shader, const PICA::FragmentConfig& config);
void compileLights(std::string& shader, const PICA::FragmentConfig& config, const PICARegs& regs); void compileLights(std::string& shader, const PICA::FragmentConfig& config);
void compileLUTLookup(std::string& shader, const PICA::FragmentConfig& config, const PICARegs& regs, u32 lightIndex, u32 lutID); void compileLUTLookup(std::string& shader, const PICA::FragmentConfig& config, u32 lightIndex, u32 lutID);
bool isSamplerEnabled(u32 environmentID, u32 lutID); bool isSamplerEnabled(u32 environmentID, u32 lutID);
u32 textureConfig = 0;
public: public:
FragmentGenerator(API api, Language language) : api(api), language(language) {} 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(); std::string getDefaultVertexShader();
void setTarget(API api, Language language) { void setTarget(API api, Language language) {

View file

@ -1,3 +1,4 @@
#include "PICA/regs.hpp"
#include "PICA/shader_gen.hpp" #include "PICA/shader_gen.hpp"
using namespace PICA; using namespace PICA;
using namespace PICA::ShaderGen; using namespace PICA::ShaderGen;
@ -101,7 +102,7 @@ std::string FragmentGenerator::getDefaultVertexShader() {
return ret; return ret;
} }
std::string FragmentGenerator::generate(const PICARegs& regs, const FragmentConfig& config) { std::string FragmentGenerator::generate(const FragmentConfig& config) {
std::string ret = ""; std::string ret = "";
switch (api) { switch (api) {
@ -168,7 +169,7 @@ std::string FragmentGenerator::generate(const PICARegs& regs, const FragmentConf
vec4 secondaryColor = vec4(0.0); vec4 secondaryColor = vec4(0.0);
)"; )";
compileLights(ret, config, regs); compileLights(ret, config);
ret += R"( ret += R"(
vec3 colorOp1 = vec3(0.0); vec3 colorOp1 = vec3(0.0);
@ -187,44 +188,39 @@ std::string FragmentGenerator::generate(const PICARegs& regs, const FragmentConf
float depth = z_over_w * depthScale + depthOffset; float depth = z_over_w * depthScale + depthOffset;
)"; )";
if ((regs[InternalRegs::DepthmapEnable] & 1) == 0) { if (!config.outConfig.depthMapEnable) {
ret += "depth /= gl_FragCoord.w;\n"; ret += "depth /= gl_FragCoord.w;\n";
} }
ret += "gl_FragDepth = depth;\n"; ret += "gl_FragDepth = depth;\n";
textureConfig = regs[InternalRegs::TexUnitCfg];
for (int i = 0; i < 6; i++) { 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 ret += "fragColor = combinerOutput;\n}"; // End of main function
return ret; return ret;
} }
void FragmentGenerator::compileTEV(std::string& shader, int stage, const PICARegs& regs) { void FragmentGenerator::compileTEV(std::string& shader, int stage, const PICA::FragmentConfig& config) {
// Base address for each TEV stage's configuration const u32* tevValues = config.texConfig.tevConfigs.data() + stage * 4;
static constexpr std::array<u32, 6> ioBases = {
InternalRegs::TexEnv0Source, InternalRegs::TexEnv1Source, InternalRegs::TexEnv2Source,
InternalRegs::TexEnv3Source, InternalRegs::TexEnv4Source, InternalRegs::TexEnv5Source,
};
const u32 ioBase = ioBases[stage]; // Pass a 0 to constColor here, as it doesn't matter for compilation
TexEnvConfig tev(regs[ioBase], regs[ioBase + 1], regs[ioBase + 2], regs[ioBase + 3], regs[ioBase + 4]); TexEnvConfig tev(tevValues[0], tevValues[1], tevValues[2], 0, tevValues[3]);
if (!tev.isPassthroughStage()) { if (!tev.isPassthroughStage()) {
// Get color operands // Get color operands
shader += "colorOp1 = "; shader += "colorOp1 = ";
getColorOperand(shader, tev.colorSource1, tev.colorOperand1, stage); getColorOperand(shader, tev.colorSource1, tev.colorOperand1, stage, config);
shader += ";\ncolorOp2 = "; shader += ";\ncolorOp2 = ";
getColorOperand(shader, tev.colorSource2, tev.colorOperand2, stage); getColorOperand(shader, tev.colorSource2, tev.colorOperand2, stage, config);
shader += ";\ncolorOp3 = "; 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("; shader += ";\nvec3 outputColor" + std::to_string(stage) + " = clamp(";
getColorOperation(shader, tev.colorOp); getColorOperation(shader, tev.colorOp);
@ -236,13 +232,13 @@ void FragmentGenerator::compileTEV(std::string& shader, int stage, const PICAReg
} else { } else {
// Get alpha operands // Get alpha operands
shader += "alphaOp1 = "; shader += "alphaOp1 = ";
getAlphaOperand(shader, tev.alphaSource1, tev.alphaOperand1, stage); getAlphaOperand(shader, tev.alphaSource1, tev.alphaOperand1, stage, config);
shader += ";\nalphaOp2 = "; shader += ";\nalphaOp2 = ";
getAlphaOperand(shader, tev.alphaSource2, tev.alphaOperand2, stage); getAlphaOperand(shader, tev.alphaSource2, tev.alphaOperand2, stage, config);
shader += ";\nalphaOp3 = "; 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("; shader += ";\nfloat outputAlpha" + std::to_string(stage) + " = clamp(";
getAlphaOperation(shader, tev.alphaOp); getAlphaOperation(shader, tev.alphaOp);
@ -258,7 +254,7 @@ void FragmentGenerator::compileTEV(std::string& shader, int stage, const PICAReg
shader += "previousBuffer = tevNextPreviousBuffer;\n\n"; shader += "previousBuffer = tevNextPreviousBuffer;\n\n";
// Update the "next previous buffer" if necessary // Update the "next previous buffer" if necessary
const u32 textureEnvUpdateBuffer = regs[InternalRegs::TexEnvUpdateBuffer]; const u32 textureEnvUpdateBuffer = config.texConfig.texEnvUpdateBuffer;
if (stage < 4) { if (stage < 4) {
// Check whether to update rgb // Check whether to update rgb
if ((textureEnvUpdateBuffer & (0x100 << stage))) { if ((textureEnvUpdateBuffer & (0x100 << stage))) {
@ -272,7 +268,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; using OperandType = TexEnvConfig::ColorOperand;
// For inverting operands, add the 1.0 - x subtraction // For inverting operands, add the 1.0 - x subtraction
@ -284,31 +280,31 @@ void FragmentGenerator::getColorOperand(std::string& shader, TexEnvConfig::Sourc
switch (color) { switch (color) {
case OperandType::SourceColor: case OperandType::SourceColor:
case OperandType::OneMinusSourceColor: case OperandType::OneMinusSourceColor:
getSource(shader, source, index); getSource(shader, source, index, config);
shader += ".rgb"; shader += ".rgb";
break; break;
case OperandType::SourceRed: case OperandType::SourceRed:
case OperandType::OneMinusSourceRed: case OperandType::OneMinusSourceRed:
getSource(shader, source, index); getSource(shader, source, index, config);
shader += ".rrr"; shader += ".rrr";
break; break;
case OperandType::SourceGreen: case OperandType::SourceGreen:
case OperandType::OneMinusSourceGreen: case OperandType::OneMinusSourceGreen:
getSource(shader, source, index); getSource(shader, source, index, config);
shader += ".ggg"; shader += ".ggg";
break; break;
case OperandType::SourceBlue: case OperandType::SourceBlue:
case OperandType::OneMinusSourceBlue: case OperandType::OneMinusSourceBlue:
getSource(shader, source, index); getSource(shader, source, index, config);
shader += ".bbb"; shader += ".bbb";
break; break;
case OperandType::SourceAlpha: case OperandType::SourceAlpha:
case OperandType::OneMinusSourceAlpha: case OperandType::OneMinusSourceAlpha:
getSource(shader, source, index); getSource(shader, source, index, config);
shader += ".aaa"; shader += ".aaa";
break; break;
@ -319,7 +315,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; using OperandType = TexEnvConfig::AlphaOperand;
// For inverting operands, add the 1.0 - x subtraction // For inverting operands, add the 1.0 - x subtraction
@ -331,25 +327,25 @@ void FragmentGenerator::getAlphaOperand(std::string& shader, TexEnvConfig::Sourc
switch (color) { switch (color) {
case OperandType::SourceRed: case OperandType::SourceRed:
case OperandType::OneMinusSourceRed: case OperandType::OneMinusSourceRed:
getSource(shader, source, index); getSource(shader, source, index, config);
shader += ".r"; shader += ".r";
break; break;
case OperandType::SourceGreen: case OperandType::SourceGreen:
case OperandType::OneMinusSourceGreen: case OperandType::OneMinusSourceGreen:
getSource(shader, source, index); getSource(shader, source, index, config);
shader += ".g"; shader += ".g";
break; break;
case OperandType::SourceBlue: case OperandType::SourceBlue:
case OperandType::OneMinusSourceBlue: case OperandType::OneMinusSourceBlue:
getSource(shader, source, index); getSource(shader, source, index, config);
shader += ".b"; shader += ".b";
break; break;
case OperandType::SourceAlpha: case OperandType::SourceAlpha:
case OperandType::OneMinusSourceAlpha: case OperandType::OneMinusSourceAlpha:
getSource(shader, source, index); getSource(shader, source, index, config);
shader += ".a"; shader += ".a";
break; break;
@ -360,14 +356,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) { switch (source) {
case TexEnvConfig::Source::PrimaryColor: shader += "v_colour"; break; case TexEnvConfig::Source::PrimaryColor: shader += "v_colour"; break;
case TexEnvConfig::Source::Texture0: shader += "texture(u_tex0, v_texcoord0.xy)"; 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::Texture1: shader += "texture(u_tex1, v_texcoord1)"; break;
case TexEnvConfig::Source::Texture2: { 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 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)"; shader += "texture(u_tex2, v_texcoord1)";
} else { } else {
shader += "texture(u_tex2, v_texcoord2)"; shader += "texture(u_tex2, v_texcoord2)";
@ -428,12 +424,11 @@ void FragmentGenerator::getAlphaOperation(std::string& shader, TexEnvConfig::Ope
} }
} }
void FragmentGenerator::applyAlphaTest(std::string& shader, const PICARegs& regs) { void FragmentGenerator::applyAlphaTest(std::string& shader, const PICA::FragmentConfig& config) {
const u32 alphaConfig = regs[InternalRegs::AlphaTestConfig]; const CompareFunction function = config.outConfig.alphaTestFunction;
const auto function = static_cast<CompareFunction>(Helpers::getBits<4, 3>(alphaConfig));
// Alpha test disabled // Alpha test disabled
if (Helpers::getBit<0>(alphaConfig) == 0 || function == CompareFunction::Always) { if (function == CompareFunction::Always) {
return; return;
} }
@ -458,7 +453,7 @@ void FragmentGenerator::applyAlphaTest(std::string& shader, const PICARegs& regs
shader += ") { discard; }\n"; 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) { if (!config.lighting.enable) {
return; return;
} }
@ -516,27 +511,27 @@ void FragmentGenerator::compileLights(std::string& shader, const PICA::FragmentC
", int(clamp(floor(distance_att_delta * 256.0), 0.0, 255.0)));\n"; ", int(clamp(floor(distance_att_delta * 256.0), 0.0, 255.0)));\n";
} }
compileLUTLookup(shader, config, regs, lightID, spotlightLutIndex); compileLUTLookup(shader, config, lightID, spotlightLutIndex);
shader += "spotlight_attenuation = lut_lookup_result;\n"; shader += "spotlight_attenuation = lut_lookup_result;\n";
compileLUTLookup(shader, config, regs, lightID, PICA::Lights::LUT_D0); compileLUTLookup(shader, config, lightID, PICA::Lights::LUT_D0);
shader += "specular0_dist = lut_lookup_result;\n"; shader += "specular0_dist = lut_lookup_result;\n";
compileLUTLookup(shader, config, regs, lightID, PICA::Lights::LUT_D1); compileLUTLookup(shader, config, lightID, PICA::Lights::LUT_D1);
shader += "specular1_dist = lut_lookup_result;\n"; shader += "specular1_dist = lut_lookup_result;\n";
compileLUTLookup(shader, config, regs, lightID, PICA::Lights::LUT_RR); compileLUTLookup(shader, config, lightID, PICA::Lights::LUT_RR);
shader += "reflected_color.r = lut_lookup_result;\n"; shader += "reflected_color.r = lut_lookup_result;\n";
if (isSamplerEnabled(config.lighting.config, PICA::Lights::LUT_RG)) { if (isSamplerEnabled(config.lighting.config, PICA::Lights::LUT_RG)) {
compileLUTLookup(shader, config, regs, lightID, PICA::Lights::LUT_RG); compileLUTLookup(shader, config, lightID, PICA::Lights::LUT_RG);
shader += "reflected_color.g = lut_lookup_result;\n"; shader += "reflected_color.g = lut_lookup_result;\n";
} else { } else {
shader += "reflected_color.g = reflected_color.r;\n"; shader += "reflected_color.g = reflected_color.r;\n";
} }
if (isSamplerEnabled(config.lighting.config, PICA::Lights::LUT_RB)) { if (isSamplerEnabled(config.lighting.config, PICA::Lights::LUT_RB)) {
compileLUTLookup(shader, config, regs, lightID, PICA::Lights::LUT_RB); compileLUTLookup(shader, config, lightID, PICA::Lights::LUT_RB);
shader += "reflected_color.b = lut_lookup_result;\n"; shader += "reflected_color.b = lut_lookup_result;\n";
} else { } else {
shader += "reflected_color.b = reflected_color.r;\n"; shader += "reflected_color.b = reflected_color.r;\n";
@ -565,7 +560,7 @@ void FragmentGenerator::compileLights(std::string& shader, const PICA::FragmentC
} }
if (config.lighting.enablePrimaryAlpha || config.lighting.enableSecondaryAlpha) { if (config.lighting.enablePrimaryAlpha || config.lighting.enableSecondaryAlpha) {
compileLUTLookup(shader, config, regs, lightID, PICA::Lights::LUT_FR); compileLUTLookup(shader, config, lightID, PICA::Lights::LUT_FR);
shader += "float fresnel_factor = lut_lookup_result;\n"; shader += "float fresnel_factor = lut_lookup_result;\n";
} }
@ -602,7 +597,7 @@ bool FragmentGenerator::isSamplerEnabled(u32 environmentID, u32 lutID) {
return samplerEnabled[environmentID * 7 + 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) {
uint lutIndex = 0; uint lutIndex = 0;
int bitInConfig1 = 0; int bitInConfig1 = 0;
@ -618,7 +613,7 @@ void FragmentGenerator::compileLUTLookup(std::string& shader, const PICA::Fragme
} }
const bool samplerEnabled = isSamplerEnabled(config.lighting.config, lutID); const bool samplerEnabled = isSamplerEnabled(config.lighting.config, lutID);
const u32 config1 = regs[InternalRegs::LightConfig1]; const u32 config1 = config.lighting.config1;
if (!samplerEnabled || ((config1 >> bitInConfig1) & 1)) { if (!samplerEnabled || ((config1 >> bitInConfig1) & 1)) {
shader += "lut_lookup_result = 1.0;\n"; shader += "lut_lookup_result = 1.0;\n";
@ -626,9 +621,9 @@ void FragmentGenerator::compileLUTLookup(std::string& shader, const PICA::Fragme
} }
static constexpr float scales[] = {1.0f, 2.0f, 4.0f, 8.0f, 0.0f, 0.0f, 0.25f, 0.5f}; 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 lutAbs = config.lighting.lutAbs;
const u32 lutSelect = regs[InternalRegs::LightLUTSelect]; const u32 lutSelect = config.lighting.lutSelect;
const u32 lutScale = regs[InternalRegs::LightLUTScale]; const u32 lutScale = config.lighting.lutScale;
// The way these bitfields are encoded is so cursed // The way these bitfields are encoded is so cursed
float scale = scales[(lutScale >> (4 * lutID)) & 0x7]; float scale = scales[(lutScale >> (4 * lutID)) & 0x7];

View file

@ -784,37 +784,12 @@ OpenGL::Program& RendererGL::getSpecializedShader() {
constexpr uint uboBlockBinding = 2; constexpr uint uboBlockBinding = 2;
PICA::FragmentConfig fsConfig(regs); 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<PICA::CompareFunction>(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], &regs[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]; CachedProgram& programEntry = shaderCache[fsConfig];
OpenGL::Program& program = programEntry.program; OpenGL::Program& program = programEntry.program;
if (!program.exists()) { 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); OpenGL::Shader fragShader({fs.c_str(), fs.size()}, OpenGL::Fragment);
program.create({defaultShadergenVs, fragShader}); program.create({defaultShadergenVs, fragShader});