mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-07-01 12:56:21 +12:00
Remove dependency of PICA regs in fragment config
This commit is contained in:
parent
eb7e02fbc2
commit
ce4146f9ba
4 changed files with 90 additions and 90 deletions
|
@ -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], ®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
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(
|
static_assert(
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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], ®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];
|
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});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue