diff --git a/source/platform/gpu/pica.hpp b/source/platform/gpu/pica.hpp index 53aee38..f9dbf73 100644 --- a/source/platform/gpu/pica.hpp +++ b/source/platform/gpu/pica.hpp @@ -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 specular; LightingColor diffuse; LightingColor ambient; // NOTE: If is_directional() is false, these actually specify the position - uint32_t raw_light_dir[2]; + std::array 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 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; } diff --git a/source/video_core/src/video_core/debug_utils/debug_utils.cpp b/source/video_core/src/video_core/debug_utils/debug_utils.cpp index 1268398..39be330 100644 --- a/source/video_core/src/video_core/debug_utils/debug_utils.cpp +++ b/source/video_core/src/video_core/debug_utils/debug_utils.cpp @@ -676,7 +676,7 @@ void DumpTevStageConfig(const std::array& 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& 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(tev_stage.color_op.Value())); + op_str = fmt::format("UnknownOp_{:#x}", static_cast(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& 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"; diff --git a/source/video_core/src/video_core/rasterizer.cpp b/source/video_core/src/video_core/rasterizer.cpp index c15fa55..033d69b 100644 --- a/source/video_core/src/video_core/rasterizer.cpp +++ b/source/video_core/src/video_core/rasterizer.cpp @@ -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 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 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(std::min(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; } } diff --git a/source/video_core/src/video_core/vulkan/renderer.cpp b/source/video_core/src/video_core/vulkan/renderer.cpp index 8e47038..8318600 100644 --- a/source/video_core/src/video_core/vulkan/renderer.cpp +++ b/source/video_core/src/video_core/vulkan/renderer.cpp @@ -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); } diff --git a/source/video_core/src/video_core/vulkan/shader_gen.cpp b/source/video_core/src/video_core/vulkan/shader_gen.cpp index 478de58..6743757 100644 --- a/source/video_core/src/video_core/vulkan/shader_gen.cpp +++ b/source/video_core/src/video_core/vulkan/shader_gen.cpp @@ -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(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"; }