Pica: Migrate some register definitions to BitField::v3

This commit is contained in:
Tony Wasserka 2024-10-20 00:19:21 +02:00
parent 14a19c29ae
commit 2100cfe3ee
5 changed files with 72 additions and 78 deletions

View file

@ -31,7 +31,7 @@ enum class CullMode : uint32_t {
// TODO: What does the third value imply? // TODO: What does the third value imply?
}; };
union AlphaTest { struct AlphaTest {
enum class Function : uint32_t { enum class Function : uint32_t {
Always = 1, Always = 1,
NotEqual = 3, NotEqual = 3,
@ -39,9 +39,11 @@ union AlphaTest {
GreaterThanOrEqual = 7, GreaterThanOrEqual = 7,
}; };
BitFieldLegacy<0, 1, uint32_t> enable; uint32_t storage;
BitFieldLegacy<4, 3, Function> function;
BitFieldLegacy<8, 8, uint32_t> reference; auto enable() const { return BitField::v3::MakeFlagOn<0>(this); }
auto function() const { return BitField::v3::MakeFieldOn<4, 3, Function>(this); }
auto reference() const { return BitField::v3::MakeFieldOn<8, 8>(this); }
}; };
struct StencilTest { struct StencilTest {
@ -474,54 +476,46 @@ struct Regs {
AddThenMultiply = 9, AddThenMultiply = 9,
}; };
union { uint32_t storage[5];
BitFieldLegacy< 0, 4, Source> color_source1;
BitFieldLegacy< 4, 4, Source> color_source2;
BitFieldLegacy< 8, 4, Source> color_source3;
BitFieldLegacy<16, 4, Source> alpha_source1;
BitFieldLegacy<20, 4, Source> alpha_source2;
BitFieldLegacy<24, 4, Source> alpha_source3;
};
union { auto color_source1() const { return BitField::v3::MakeFieldOn<0, 4, Source>(&storage[0]); }
BitFieldLegacy< 0, 4, ColorModifier> color_modifier1; auto color_source2() const { return BitField::v3::MakeFieldOn<4, 4, Source>(&storage[0]); }
BitFieldLegacy< 4, 4, ColorModifier> color_modifier2; auto color_source3() const { return BitField::v3::MakeFieldOn<8, 4, Source>(&storage[0]); }
BitFieldLegacy< 8, 4, ColorModifier> color_modifier3; auto alpha_source1() const { return BitField::v3::MakeFieldOn<16, 4, Source>(&storage[0]); }
BitFieldLegacy<12, 3, AlphaModifier> alpha_modifier1; auto alpha_source2() const { return BitField::v3::MakeFieldOn<20, 4, Source>(&storage[0]); }
BitFieldLegacy<16, 3, AlphaModifier> alpha_modifier2; auto alpha_source3() const { return BitField::v3::MakeFieldOn<24, 4, Source>(&storage[0]); }
BitFieldLegacy<20, 3, AlphaModifier> alpha_modifier3;
};
union { auto color_modifier1() const { return BitField::v3::MakeFieldOn<0, 4, ColorModifier>(&storage[1]); }
BitFieldLegacy< 0, 4, Operation> color_op; auto color_modifier2() const { return BitField::v3::MakeFieldOn<4, 4, ColorModifier>(&storage[1]); }
BitFieldLegacy<16, 4, Operation> alpha_op; auto color_modifier3() const { return BitField::v3::MakeFieldOn<8, 4, ColorModifier>(&storage[1]); }
}; auto alpha_modifier1() const { return BitField::v3::MakeFieldOn<12, 3, AlphaModifier>(&storage[1]); }
auto alpha_modifier2() const { return BitField::v3::MakeFieldOn<16, 3, AlphaModifier>(&storage[1]); }
auto alpha_modifier3() const { return BitField::v3::MakeFieldOn<20, 3, AlphaModifier>(&storage[1]); }
union { auto color_op() const { return BitField::v3::MakeFieldOn<0, 4, Operation>(&storage[2]); }
BitFieldLegacy< 0, 8, uint32_t> const_r; auto alpha_op() const { return BitField::v3::MakeFieldOn<16, 4, Operation>(&storage[2]); }
BitFieldLegacy< 8, 8, uint32_t> const_g;
BitFieldLegacy<16, 8, uint32_t> const_b;
BitFieldLegacy<24, 8, uint32_t> const_a;
};
union { auto const_r() const { return BitField::v3::MakeFieldOn<0, 8, uint8_t>(&storage[3]); }
// Access these through the convenience getters below auto const_g() const { return BitField::v3::MakeFieldOn<8, 8, uint8_t>(&storage[3]); }
BitFieldLegacy< 0, 2, uint32_t> multiplier_exp_rgb; auto const_b() const { return BitField::v3::MakeFieldOn<16, 8, uint8_t>(&storage[3]); }
BitFieldLegacy<16, 2, uint32_t> multiplier_exp_a; auto const_a() const { return BitField::v3::MakeFieldOn<24, 8, uint8_t>(&storage[3]); }
};
// Access these through the convenience getters below
auto multiplier_exp_rgb() const { return BitField::v3::MakeFieldOn<0, 2>(&storage[4]); }
auto multiplier_exp_a() const { return BitField::v3::MakeFieldOn<16, 2>(&storage[4]); }
uint32_t GetMultiplierRGB() const { uint32_t GetMultiplierRGB() const {
if (multiplier_exp_rgb == 3) { if (multiplier_exp_rgb() == 3) {
throw std::runtime_error("Invalid RGB scaling exponent 3"); throw std::runtime_error("Invalid RGB scaling exponent 3");
} }
return (1 << multiplier_exp_rgb); return (1 << multiplier_exp_rgb());
} }
uint32_t GetMultiplierA() const { uint32_t GetMultiplierA() const {
if (multiplier_exp_a == 3) { if (multiplier_exp_a() == 3) {
throw std::runtime_error("Invalid alpha scaling exponent 3"); throw std::runtime_error("Invalid alpha scaling exponent 3");
} }
return (1 << multiplier_exp_a); return (1 << multiplier_exp_a());
} }
}; };
@ -687,12 +681,12 @@ struct Regs {
struct { struct {
// The 3DS fragment lighting pipeline doesn't distinguish between // The 3DS fragment lighting pipeline doesn't distinguish between
// materials and lights, so these properties are premultiplied // materials and lights, so these properties are premultiplied
LightingColor specular[2]; std::array<LightingColor, 2> specular;
LightingColor diffuse; LightingColor diffuse;
LightingColor ambient; LightingColor ambient;
// NOTE: If is_directional() is false, these actually specify the position // NOTE: If is_directional() is false, these actually specify the position
uint32_t raw_light_dir[2]; std::array<uint32_t, 2> raw_light_dir;
constexpr auto raw_light_dir_x() const { return BitField::v3::MakeFieldOn< 0, 16>(&raw_light_dir[0]); } constexpr auto raw_light_dir_x() const { return BitField::v3::MakeFieldOn< 0, 16>(&raw_light_dir[0]); }
constexpr auto raw_light_dir_y() const { return BitField::v3::MakeFieldOn<16, 16>(&raw_light_dir[0]); } constexpr auto raw_light_dir_y() const { return BitField::v3::MakeFieldOn<16, 16>(&raw_light_dir[0]); }
constexpr auto raw_light_dir_z() const { return BitField::v3::MakeFieldOn< 0, 16>(&raw_light_dir[1]); } constexpr auto raw_light_dir_z() const { return BitField::v3::MakeFieldOn< 0, 16>(&raw_light_dir[1]); }
@ -701,7 +695,7 @@ struct Regs {
float16 get_light_dir_z() const { return float16::FromRawFloat(raw_light_dir_z()); } float16 get_light_dir_z() const { return float16::FromRawFloat(raw_light_dir_z()); }
// 13-bit signed fixed-point coordinates with 11 bits of precision // 13-bit signed fixed-point coordinates with 11 bits of precision
uint32_t raw_spot_dir[2]; std::array<uint32_t, 2> raw_spot_dir;
constexpr auto spot_dir_x() const { return BitField::v3::MakeFieldOn< 0, 13, int32_t>(&raw_spot_dir[0]); } constexpr auto spot_dir_x() const { return BitField::v3::MakeFieldOn< 0, 13, int32_t>(&raw_spot_dir[0]); }
constexpr auto spot_dir_y() const { return BitField::v3::MakeFieldOn<16, 13, int32_t>(&raw_spot_dir[0]); } constexpr auto spot_dir_y() const { return BitField::v3::MakeFieldOn<16, 13, int32_t>(&raw_spot_dir[0]); }
constexpr auto spot_dir_z() const { return BitField::v3::MakeFieldOn< 0, 13, int32_t>(&raw_spot_dir[1]); } constexpr auto spot_dir_z() const { return BitField::v3::MakeFieldOn< 0, 13, int32_t>(&raw_spot_dir[1]); }
@ -857,7 +851,7 @@ struct Regs {
uint32_t storage_light_permutation; uint32_t storage_light_permutation;
// Maps light IDs (0..max_light_id) to indexes into the light config array // Maps light IDs (0..max_light_id) to indexes into the light config array
unsigned GetLightIndex(unsigned id) { unsigned GetLightIndex(unsigned id) const {
return (storage_light_permutation >> (4 * id)) & 0b111; return (storage_light_permutation >> (4 * id)) & 0b111;
} }

View file

@ -676,7 +676,7 @@ void DumpTevStageConfig(const std::array<Pica::Regs::TevStageConfig,6>& stages)
{ Source::Texture0, "Texture0" }, { Source::Texture0, "Texture0" },
{ Source::Texture1, "Texture1" }, { Source::Texture1, "Texture1" },
{ Source::Texture2, "Texture2" }, { Source::Texture2, "Texture2" },
{ Source::Constant, fmt::format("({}, {}, {}, {})", tev_stage.const_r.Value(), tev_stage.const_g.Value(), tev_stage.const_b.Value(), tev_stage.const_a.Value()) }, { Source::Constant, fmt::format("({}, {}, {}, {})", tev_stage.const_r()(), tev_stage.const_g()(), tev_stage.const_b()(), tev_stage.const_a()()) },
{ Source::Previous, "Previous" }, { Source::Previous, "Previous" },
}; };
@ -733,18 +733,18 @@ void DumpTevStageConfig(const std::array<Pica::Regs::TevStageConfig,6>& stages)
}; };
static auto GetColorCombinerStr = static auto GetColorCombinerStr =
[](const Regs::TevStageConfig& tev_stage) { [](const Regs::TevStageConfig& tev_stage) {
auto op_it = combiner_map.find(tev_stage.color_op); auto op_it = combiner_map.find(tev_stage.color_op());
std::string op_str = "Unknown op (%source1, %source2, %source3)"; std::string op_str = "Unknown op (%source1, %source2, %source3)";
if (op_it != combiner_map.end()) { if (op_it != combiner_map.end()) {
op_str = op_it->second; op_str = op_it->second;
} else { } else {
op_str = fmt::format("UnknownOp_{:#x}", static_cast<uint32_t>(tev_stage.color_op.Value())); op_str = fmt::format("UnknownOp_{:#x}", static_cast<uint32_t>(tev_stage.color_op()()));
} }
op_str = ReplacePattern(op_str, "%source1", GetColorSourceStr(tev_stage.color_source1, tev_stage.color_modifier1)); op_str = ReplacePattern(op_str, "%source1", GetColorSourceStr(tev_stage.color_source1(), tev_stage.color_modifier1()));
op_str = ReplacePattern(op_str, "%source2", GetColorSourceStr(tev_stage.color_source2, tev_stage.color_modifier2)); op_str = ReplacePattern(op_str, "%source2", GetColorSourceStr(tev_stage.color_source2(), tev_stage.color_modifier2()));
return ReplacePattern(op_str, "%source3", GetColorSourceStr(tev_stage.color_source3, tev_stage.color_modifier3)); return ReplacePattern(op_str, "%source3", GetColorSourceStr(tev_stage.color_source3(), tev_stage.color_modifier3()));
}; };
static auto GetAlphaSourceStr = static auto GetAlphaSourceStr =
[](const Source& src, const AlphaModifier& modifier) { [](const Source& src, const AlphaModifier& modifier) {
@ -765,14 +765,14 @@ void DumpTevStageConfig(const std::array<Pica::Regs::TevStageConfig,6>& stages)
}; };
static auto GetAlphaCombinerStr = static auto GetAlphaCombinerStr =
[](const Regs::TevStageConfig& tev_stage) { [](const Regs::TevStageConfig& tev_stage) {
auto op_it = combiner_map.find(tev_stage.alpha_op); auto op_it = combiner_map.find(tev_stage.alpha_op());
std::string op_str = "Unknown op (%source1, %source2, %source3)"; std::string op_str = "Unknown op (%source1, %source2, %source3)";
if (op_it != combiner_map.end()) if (op_it != combiner_map.end())
op_str = op_it->second; op_str = op_it->second;
op_str = ReplacePattern(op_str, "%source1", GetAlphaSourceStr(tev_stage.alpha_source1, tev_stage.alpha_modifier1)); op_str = ReplacePattern(op_str, "%source1", GetAlphaSourceStr(tev_stage.alpha_source1(), tev_stage.alpha_modifier1()));
op_str = ReplacePattern(op_str, "%source2", GetAlphaSourceStr(tev_stage.alpha_source2, tev_stage.alpha_modifier2)); op_str = ReplacePattern(op_str, "%source2", GetAlphaSourceStr(tev_stage.alpha_source2(), tev_stage.alpha_modifier2()));
return ReplacePattern(op_str, "%source3", GetAlphaSourceStr(tev_stage.alpha_source3, tev_stage.alpha_modifier3)); return ReplacePattern(op_str, "%source3", GetAlphaSourceStr(tev_stage.alpha_source3(), tev_stage.alpha_modifier3()));
}; };
stage_info += "Stage " + std::to_string(index) + ": " + GetColorCombinerStr(tev_stage) + " " + GetAlphaCombinerStr(tev_stage) + "\n"; stage_info += "Stage " + std::to_string(index) + ": " + GetColorCombinerStr(tev_stage) + " " + GetAlphaCombinerStr(tev_stage) + "\n";

View file

@ -547,7 +547,7 @@ static void ProcessTriangleInternal(Context& context,
return texture_color[2]; return texture_color[2];
case Source::Constant: case Source::Constant:
return {tev_stage.const_r, tev_stage.const_g, tev_stage.const_b, tev_stage.const_a}; return {tev_stage.const_r()(), tev_stage.const_g()(), tev_stage.const_b()(), tev_stage.const_a()()};
case Source::CombinerBuffer: case Source::CombinerBuffer:
return combiner_buffer; return combiner_buffer;
@ -731,19 +731,19 @@ static void ProcessTriangleInternal(Context& context,
// combiner_output.rgb(), but instead store it in a temporary variable until // combiner_output.rgb(), but instead store it in a temporary variable until
// alpha combining has been done. // alpha combining has been done.
Math::Vec3<u8> color_result[3] = { Math::Vec3<u8> color_result[3] = {
GetColorModifier(tev_stage.color_modifier1, GetCombinerSource(tev_stage.color_source1)), GetColorModifier(tev_stage.color_modifier1(), GetCombinerSource(tev_stage.color_source1())),
GetColorModifier(tev_stage.color_modifier2, GetCombinerSource(tev_stage.color_source2)), GetColorModifier(tev_stage.color_modifier2(), GetCombinerSource(tev_stage.color_source2())),
GetColorModifier(tev_stage.color_modifier3, GetCombinerSource(tev_stage.color_source3)) GetColorModifier(tev_stage.color_modifier3(), GetCombinerSource(tev_stage.color_source3()))
}; };
auto color_output = ColorCombine(tev_stage.color_op, color_result); auto color_output = ColorCombine(tev_stage.color_op(), color_result);
// alpha combiner // alpha combiner
std::array<u8,3> alpha_result = { std::array<u8,3> alpha_result = {
GetAlphaModifier(tev_stage.alpha_modifier1, GetCombinerSource(tev_stage.alpha_source1)), GetAlphaModifier(tev_stage.alpha_modifier1(), GetCombinerSource(tev_stage.alpha_source1())),
GetAlphaModifier(tev_stage.alpha_modifier2, GetCombinerSource(tev_stage.alpha_source2)), GetAlphaModifier(tev_stage.alpha_modifier2(), GetCombinerSource(tev_stage.alpha_source2())),
GetAlphaModifier(tev_stage.alpha_modifier3, GetCombinerSource(tev_stage.alpha_source3)) GetAlphaModifier(tev_stage.alpha_modifier3(), GetCombinerSource(tev_stage.alpha_source3()))
}; };
auto alpha_output = AlphaCombine(tev_stage.alpha_op, alpha_result); auto alpha_output = AlphaCombine(tev_stage.alpha_op(), alpha_result);
// TODO: Move to pica.h // TODO: Move to pica.h
if (tev_stage_index > 0) { if (tev_stage_index > 0) {
@ -770,8 +770,8 @@ static void ProcessTriangleInternal(Context& context,
combiner_output.a() = static_cast<uint8_t>(std::min<unsigned>(255, alpha_output * tev_stage.GetMultiplierA())); combiner_output.a() = static_cast<uint8_t>(std::min<unsigned>(255, alpha_output * tev_stage.GetMultiplierA()));
} }
if (registers.output_merger.alpha_test.enable && registers.output_merger.alpha_test.function != AlphaTest::Function::Always) { if (registers.output_merger.alpha_test.enable() && registers.output_merger.alpha_test.function() != AlphaTest::Function::Always) {
if (AlphaTestFailed(combiner_output.a(), registers.output_merger.alpha_test.reference, registers.output_merger.alpha_test.function)) { if (AlphaTestFailed(combiner_output.a(), registers.output_merger.alpha_test.reference(), registers.output_merger.alpha_test.function())) {
continue; continue;
} }
} }

View file

@ -1173,7 +1173,7 @@ void Renderer::FinalizeTriangleBatchInternal(Context& context, const VertexShade
const auto tev_stages = context.registers.GetTevStages(); const auto tev_stages = context.registers.GetTevStages();
for (auto& tev_stage : tev_stages) { for (auto& tev_stage : tev_stages) {
for (uint32_t val : { tev_stage.const_r.Value(), tev_stage.const_g.Value(), tev_stage.const_b.Value(), tev_stage.const_a.Value() }) { for (uint32_t val : { tev_stage.const_r()(), tev_stage.const_g()(), tev_stage.const_b()(), tev_stage.const_a()() }) {
memcpy(ubo_data_ptr, &val, sizeof(val)); memcpy(ubo_data_ptr, &val, sizeof(val));
ubo_data_ptr += sizeof(val); ubo_data_ptr += sizeof(val);
} }

View file

@ -349,8 +349,8 @@ std::string GenerateFragmentShader(Context& context) {
using AlphaModifier = Regs::TevStageConfig::AlphaModifier; using AlphaModifier = Regs::TevStageConfig::AlphaModifier;
using Operation = Regs::TevStageConfig::Operation; using Operation = Regs::TevStageConfig::Operation;
const bool is_nop_stage_rgb = (tev_stage.color_modifier1 == ColorModifier::SourceColor && tev_stage.color_op == Operation::Replace); const bool is_nop_stage_rgb = (tev_stage.color_modifier1() == ColorModifier::SourceColor && tev_stage.color_op() == Operation::Replace);
const bool is_nop_stage_a = (tev_stage.alpha_modifier1 == AlphaModifier::SourceAlpha && tev_stage.alpha_op == Operation::Replace); const bool is_nop_stage_a = (tev_stage.alpha_modifier1() == AlphaModifier::SourceAlpha && tev_stage.alpha_op() == Operation::Replace);
std::string tev_stage_str = "tev" + std::to_string(tev_stage_index) + "_"; std::string tev_stage_str = "tev" + std::to_string(tev_stage_index) + "_";
@ -518,9 +518,9 @@ std::string GenerateFragmentShader(Context& context) {
} }
}; };
code += "uvec3 " + tev_stage_str + "rgb_in1 = " + GetModifiedColor(tev_stage.color_modifier1, GetSourceColor(tev_stage.color_source1).c_str()) + ";\n"; code += "uvec3 " + tev_stage_str + "rgb_in1 = " + GetModifiedColor(tev_stage.color_modifier1(), GetSourceColor(tev_stage.color_source1()).c_str()) + ";\n";
code += "uvec3 " + tev_stage_str + "rgb_in2 = " + GetModifiedColor(tev_stage.color_modifier2, GetSourceColor(tev_stage.color_source2).c_str()) + ";\n"; code += "uvec3 " + tev_stage_str + "rgb_in2 = " + GetModifiedColor(tev_stage.color_modifier2(), GetSourceColor(tev_stage.color_source2()).c_str()) + ";\n";
code += "uvec3 " + tev_stage_str + "rgb_in3 = " + GetModifiedColor(tev_stage.color_modifier3, GetSourceColor(tev_stage.color_source3).c_str()) + ";\n"; code += "uvec3 " + tev_stage_str + "rgb_in3 = " + GetModifiedColor(tev_stage.color_modifier3(), GetSourceColor(tev_stage.color_source3()).c_str()) + ";\n";
auto CombineRGB = [&](Operation op) -> std::string { auto CombineRGB = [&](Operation op) -> std::string {
switch (op) { switch (op) {
@ -582,9 +582,9 @@ std::string GenerateFragmentShader(Context& context) {
} }
}; };
code += "uint " + tev_stage_str + "a_in1 = " + GetModifiedAlpha(tev_stage.alpha_modifier1, GetSourceAlpha(tev_stage.alpha_source1).c_str()) + ";\n"; code += "uint " + tev_stage_str + "a_in1 = " + GetModifiedAlpha(tev_stage.alpha_modifier1(), GetSourceAlpha(tev_stage.alpha_source1()).c_str()) + ";\n";
code += "uint " + tev_stage_str + "a_in2 = " + GetModifiedAlpha(tev_stage.alpha_modifier2, GetSourceAlpha(tev_stage.alpha_source2).c_str()) + ";\n"; code += "uint " + tev_stage_str + "a_in2 = " + GetModifiedAlpha(tev_stage.alpha_modifier2(), GetSourceAlpha(tev_stage.alpha_source2()).c_str()) + ";\n";
code += "uint " + tev_stage_str + "a_in3 = " + GetModifiedAlpha(tev_stage.alpha_modifier3, GetSourceAlpha(tev_stage.alpha_source3).c_str()) + ";\n"; code += "uint " + tev_stage_str + "a_in3 = " + GetModifiedAlpha(tev_stage.alpha_modifier3(), GetSourceAlpha(tev_stage.alpha_source3()).c_str()) + ";\n";
auto CombineA = [&](Operation op) -> std::string { auto CombineA = [&](Operation op) -> std::string {
switch (op) { switch (op) {
@ -628,9 +628,9 @@ std::string GenerateFragmentShader(Context& context) {
} }
}; };
code += "uvec3 " + tev_stage_str + "out_rgb = " + CombineRGB(tev_stage.color_op) + ";\n"; code += "uvec3 " + tev_stage_str + "out_rgb = " + CombineRGB(tev_stage.color_op()) + ";\n";
code += "uint " + tev_stage_str + "out_a = " + CombineA(tev_stage.alpha_op) + ";\n"; code += "uint " + tev_stage_str + "out_a = " + CombineA(tev_stage.alpha_op()) + ";\n";
// TODO: Move to pica.h // TODO: Move to pica.h
if (tev_stage_index > 0) { if (tev_stage_index > 0) {
@ -663,8 +663,8 @@ std::string GenerateFragmentShader(Context& context) {
} }
auto& alpha_test = context.registers.output_merger.alpha_test; auto& alpha_test = context.registers.output_merger.alpha_test;
if (alpha_test.enable && alpha_test.function != AlphaTest::Function::Always) { if (alpha_test.enable() && alpha_test.function() != AlphaTest::Function::Always) {
const char* op = std::invoke([func=alpha_test.function.Value()]() { const char* op = std::invoke([func=alpha_test.function()()]() {
// Inverse mapping for finding failing pixels rather than passing ones // Inverse mapping for finding failing pixels rather than passing ones
switch (func) { switch (func) {
case AlphaTest::Function::NotEqual: case AlphaTest::Function::NotEqual:
@ -680,7 +680,7 @@ std::string GenerateFragmentShader(Context& context) {
throw std::runtime_error(fmt::format("Unknown alpha test function {:#x}", static_cast<uint32_t>(func))); throw std::runtime_error(fmt::format("Unknown alpha test function {:#x}", static_cast<uint32_t>(func)));
} }
}); });
code += fmt::format("if (combiner_output.a {} {})\n", op, alpha_test.reference.Value()); code += fmt::format("if (combiner_output.a {} {})\n", op, alpha_test.reference()());
code += " discard;\n"; code += " discard;\n";
} }