mirror of
https://github.com/mikage-emu/mikage-dev.git
synced 2025-01-06 21:40:59 +01:00
Pica: Migrate some register definitions to BitField::v3
This commit is contained in:
parent
14a19c29ae
commit
2100cfe3ee
5 changed files with 72 additions and 78 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue