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?
};
union AlphaTest {
struct AlphaTest {
enum class Function : uint32_t {
Always = 1,
NotEqual = 3,
@ -39,9 +39,11 @@ union AlphaTest {
GreaterThanOrEqual = 7,
};
BitFieldLegacy<0, 1, uint32_t> enable;
BitFieldLegacy<4, 3, Function> function;
BitFieldLegacy<8, 8, uint32_t> reference;
uint32_t storage;
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 {
@ -474,54 +476,46 @@ struct Regs {
AddThenMultiply = 9,
};
union {
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;
};
uint32_t storage[5];
union {
BitFieldLegacy< 0, 4, ColorModifier> color_modifier1;
BitFieldLegacy< 4, 4, ColorModifier> color_modifier2;
BitFieldLegacy< 8, 4, ColorModifier> color_modifier3;
BitFieldLegacy<12, 3, AlphaModifier> alpha_modifier1;
BitFieldLegacy<16, 3, AlphaModifier> alpha_modifier2;
BitFieldLegacy<20, 3, AlphaModifier> alpha_modifier3;
};
auto color_source1() const { return BitField::v3::MakeFieldOn<0, 4, Source>(&storage[0]); }
auto color_source2() const { return BitField::v3::MakeFieldOn<4, 4, Source>(&storage[0]); }
auto color_source3() const { return BitField::v3::MakeFieldOn<8, 4, Source>(&storage[0]); }
auto alpha_source1() const { return BitField::v3::MakeFieldOn<16, 4, Source>(&storage[0]); }
auto alpha_source2() const { return BitField::v3::MakeFieldOn<20, 4, Source>(&storage[0]); }
auto alpha_source3() const { return BitField::v3::MakeFieldOn<24, 4, Source>(&storage[0]); }
union {
BitFieldLegacy< 0, 4, Operation> color_op;
BitFieldLegacy<16, 4, Operation> alpha_op;
};
auto color_modifier1() const { return BitField::v3::MakeFieldOn<0, 4, ColorModifier>(&storage[1]); }
auto color_modifier2() const { return BitField::v3::MakeFieldOn<4, 4, ColorModifier>(&storage[1]); }
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 {
BitFieldLegacy< 0, 8, uint32_t> const_r;
BitFieldLegacy< 8, 8, uint32_t> const_g;
BitFieldLegacy<16, 8, uint32_t> const_b;
BitFieldLegacy<24, 8, uint32_t> const_a;
};
auto color_op() const { return BitField::v3::MakeFieldOn<0, 4, Operation>(&storage[2]); }
auto alpha_op() const { return BitField::v3::MakeFieldOn<16, 4, Operation>(&storage[2]); }
union {
// Access these through the convenience getters below
BitFieldLegacy< 0, 2, uint32_t> multiplier_exp_rgb;
BitFieldLegacy<16, 2, uint32_t> multiplier_exp_a;
};
auto const_r() const { return BitField::v3::MakeFieldOn<0, 8, uint8_t>(&storage[3]); }
auto const_g() const { return BitField::v3::MakeFieldOn<8, 8, uint8_t>(&storage[3]); }
auto const_b() const { return BitField::v3::MakeFieldOn<16, 8, uint8_t>(&storage[3]); }
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 {
if (multiplier_exp_rgb == 3) {
if (multiplier_exp_rgb() == 3) {
throw std::runtime_error("Invalid RGB scaling exponent 3");
}
return (1 << multiplier_exp_rgb);
return (1 << multiplier_exp_rgb());
}
uint32_t GetMultiplierA() const {
if (multiplier_exp_a == 3) {
if (multiplier_exp_a() == 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 {
// The 3DS fragment lighting pipeline doesn't distinguish between
// materials and lights, so these properties are premultiplied
LightingColor specular[2];
std::array<LightingColor, 2> specular;
LightingColor diffuse;
LightingColor ambient;
// 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_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]); }
@ -701,7 +695,7 @@ struct Regs {
float16 get_light_dir_z() const { return float16::FromRawFloat(raw_light_dir_z()); }
// 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_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]); }
@ -857,7 +851,7 @@ struct Regs {
uint32_t storage_light_permutation;
// 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;
}

View file

@ -676,7 +676,7 @@ void DumpTevStageConfig(const std::array<Pica::Regs::TevStageConfig,6>& stages)
{ Source::Texture0, "Texture0" },
{ Source::Texture1, "Texture1" },
{ 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" },
};
@ -733,18 +733,18 @@ void DumpTevStageConfig(const std::array<Pica::Regs::TevStageConfig,6>& stages)
};
static auto GetColorCombinerStr =
[](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)";
if (op_it != combiner_map.end()) {
op_str = op_it->second;
} 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, "%source2", GetColorSourceStr(tev_stage.color_source2, tev_stage.color_modifier2));
return ReplacePattern(op_str, "%source3", GetColorSourceStr(tev_stage.color_source3, tev_stage.color_modifier3));
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()));
return ReplacePattern(op_str, "%source3", GetColorSourceStr(tev_stage.color_source3(), tev_stage.color_modifier3()));
};
static auto GetAlphaSourceStr =
[](const Source& src, const AlphaModifier& modifier) {
@ -765,14 +765,14 @@ void DumpTevStageConfig(const std::array<Pica::Regs::TevStageConfig,6>& stages)
};
static auto GetAlphaCombinerStr =
[](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)";
if (op_it != combiner_map.end())
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, "%source2", GetAlphaSourceStr(tev_stage.alpha_source2, tev_stage.alpha_modifier2));
return ReplacePattern(op_str, "%source3", GetAlphaSourceStr(tev_stage.alpha_source3, tev_stage.alpha_modifier3));
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()));
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";

View file

@ -547,7 +547,7 @@ static void ProcessTriangleInternal(Context& context,
return texture_color[2];
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:
return combiner_buffer;
@ -731,19 +731,19 @@ static void ProcessTriangleInternal(Context& context,
// combiner_output.rgb(), but instead store it in a temporary variable until
// alpha combining has been done.
Math::Vec3<u8> color_result[3] = {
GetColorModifier(tev_stage.color_modifier1, GetCombinerSource(tev_stage.color_source1)),
GetColorModifier(tev_stage.color_modifier2, GetCombinerSource(tev_stage.color_source2)),
GetColorModifier(tev_stage.color_modifier3, GetCombinerSource(tev_stage.color_source3))
GetColorModifier(tev_stage.color_modifier1(), GetCombinerSource(tev_stage.color_source1())),
GetColorModifier(tev_stage.color_modifier2(), GetCombinerSource(tev_stage.color_source2())),
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
std::array<u8,3> alpha_result = {
GetAlphaModifier(tev_stage.alpha_modifier1, GetCombinerSource(tev_stage.alpha_source1)),
GetAlphaModifier(tev_stage.alpha_modifier2, GetCombinerSource(tev_stage.alpha_source2)),
GetAlphaModifier(tev_stage.alpha_modifier3, GetCombinerSource(tev_stage.alpha_source3))
GetAlphaModifier(tev_stage.alpha_modifier1(), GetCombinerSource(tev_stage.alpha_source1())),
GetAlphaModifier(tev_stage.alpha_modifier2(), GetCombinerSource(tev_stage.alpha_source2())),
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
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()));
}
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 (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())) {
continue;
}
}

View file

@ -1173,7 +1173,7 @@ void Renderer::FinalizeTriangleBatchInternal(Context& context, const VertexShade
const auto tev_stages = context.registers.GetTevStages();
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));
ubo_data_ptr += sizeof(val);
}

View file

@ -349,8 +349,8 @@ std::string GenerateFragmentShader(Context& context) {
using AlphaModifier = Regs::TevStageConfig::AlphaModifier;
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_a = (tev_stage.alpha_modifier1 == AlphaModifier::SourceAlpha && tev_stage.alpha_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);
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_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_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_in3 = " + GetModifiedColor(tev_stage.color_modifier3(), GetSourceColor(tev_stage.color_source3()).c_str()) + ";\n";
auto CombineRGB = [&](Operation op) -> std::string {
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_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_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_in3 = " + GetModifiedAlpha(tev_stage.alpha_modifier3(), GetSourceAlpha(tev_stage.alpha_source3()).c_str()) + ";\n";
auto CombineA = [&](Operation op) -> std::string {
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
if (tev_stage_index > 0) {
@ -663,8 +663,8 @@ std::string GenerateFragmentShader(Context& context) {
}
auto& alpha_test = context.registers.output_merger.alpha_test;
if (alpha_test.enable && alpha_test.function != AlphaTest::Function::Always) {
const char* op = std::invoke([func=alpha_test.function.Value()]() {
if (alpha_test.enable() && alpha_test.function() != AlphaTest::Function::Always) {
const char* op = std::invoke([func=alpha_test.function()()]() {
// Inverse mapping for finding failing pixels rather than passing ones
switch (func) {
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)));
}
});
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";
}