diff options
| -rw-r--r-- | src/core/hle/service/hid/controllers/npad.cpp | 64 | ||||
| -rw-r--r-- | src/core/hle/service/hid/controllers/npad.h | 10 | ||||
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 26 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 3 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_shader_decompiler.cpp | 3 | ||||
| -rw-r--r-- | src/video_core/shader/decode/arithmetic_integer.cpp | 6 | ||||
| -rw-r--r-- | src/video_core/shader/decode/image.cpp | 4 | ||||
| -rw-r--r-- | src/video_core/shader/decode/memory.cpp | 39 | ||||
| -rw-r--r-- | src/video_core/shader/decode/other.cpp | 2 | ||||
| -rw-r--r-- | src/video_core/shader/decode/shift.cpp | 2 | ||||
| -rw-r--r-- | src/video_core/shader/decode/video.cpp | 2 | ||||
| -rw-r--r-- | src/video_core/shader/decode/warp.cpp | 7 | ||||
| -rw-r--r-- | src/video_core/shader/shader_ir.h | 5 |
13 files changed, 80 insertions, 93 deletions
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index a2b25a796..81bd2f3cb 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp | |||
| @@ -583,36 +583,6 @@ bool Controller_NPad::SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2) { | |||
| 583 | return true; | 583 | return true; |
| 584 | } | 584 | } |
| 585 | 585 | ||
| 586 | bool Controller_NPad::IsControllerSupported(NPadControllerType controller) { | ||
| 587 | if (controller == NPadControllerType::Handheld) { | ||
| 588 | // Handheld is not even a supported type, lets stop here | ||
| 589 | if (std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(), | ||
| 590 | NPAD_HANDHELD) == supported_npad_id_types.end()) { | ||
| 591 | return false; | ||
| 592 | } | ||
| 593 | // Handheld should not be supported in docked mode | ||
| 594 | if (Settings::values.use_docked_mode) { | ||
| 595 | return false; | ||
| 596 | } | ||
| 597 | } | ||
| 598 | switch (controller) { | ||
| 599 | case NPadControllerType::ProController: | ||
| 600 | return style.pro_controller; | ||
| 601 | case NPadControllerType::Handheld: | ||
| 602 | return style.handheld; | ||
| 603 | case NPadControllerType::JoyDual: | ||
| 604 | return style.joycon_dual; | ||
| 605 | case NPadControllerType::JoyLeft: | ||
| 606 | return style.joycon_left; | ||
| 607 | case NPadControllerType::JoyRight: | ||
| 608 | return style.joycon_right; | ||
| 609 | case NPadControllerType::Pokeball: | ||
| 610 | return style.pokeball; | ||
| 611 | default: | ||
| 612 | return false; | ||
| 613 | } | ||
| 614 | } | ||
| 615 | |||
| 616 | Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) { | 586 | Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) { |
| 617 | if (npad_id == npad_id_list.back() || npad_id == npad_id_list[npad_id_list.size() - 2]) { | 587 | if (npad_id == npad_id_list.back() || npad_id == npad_id_list[npad_id_list.size() - 2]) { |
| 618 | // These are controllers without led patterns | 588 | // These are controllers without led patterns |
| @@ -659,25 +629,24 @@ void Controller_NPad::ClearAllConnectedControllers() { | |||
| 659 | } | 629 | } |
| 660 | 630 | ||
| 661 | void Controller_NPad::DisconnectAllConnectedControllers() { | 631 | void Controller_NPad::DisconnectAllConnectedControllers() { |
| 662 | std::for_each(connected_controllers.begin(), connected_controllers.end(), | 632 | for (ControllerHolder& controller : connected_controllers) { |
| 663 | [](ControllerHolder& controller) { controller.is_connected = false; }); | 633 | controller.is_connected = false; |
| 634 | } | ||
| 664 | } | 635 | } |
| 665 | 636 | ||
| 666 | void Controller_NPad::ConnectAllDisconnectedControllers() { | 637 | void Controller_NPad::ConnectAllDisconnectedControllers() { |
| 667 | std::for_each(connected_controllers.begin(), connected_controllers.end(), | 638 | for (ControllerHolder& controller : connected_controllers) { |
| 668 | [](ControllerHolder& controller) { | 639 | if (controller.type != NPadControllerType::None && !controller.is_connected) { |
| 669 | if (controller.type != NPadControllerType::None && !controller.is_connected) { | 640 | controller.is_connected = true; |
| 670 | controller.is_connected = false; | 641 | } |
| 671 | } | 642 | } |
| 672 | }); | ||
| 673 | } | 643 | } |
| 674 | 644 | ||
| 675 | void Controller_NPad::ClearAllControllers() { | 645 | void Controller_NPad::ClearAllControllers() { |
| 676 | std::for_each(connected_controllers.begin(), connected_controllers.end(), | 646 | for (ControllerHolder& controller : connected_controllers) { |
| 677 | [](ControllerHolder& controller) { | 647 | controller.type = NPadControllerType::None; |
| 678 | controller.type = NPadControllerType::None; | 648 | controller.is_connected = false; |
| 679 | controller.is_connected = false; | 649 | } |
| 680 | }); | ||
| 681 | } | 650 | } |
| 682 | 651 | ||
| 683 | u32 Controller_NPad::GetAndResetPressState() { | 652 | u32 Controller_NPad::GetAndResetPressState() { |
| @@ -685,10 +654,10 @@ u32 Controller_NPad::GetAndResetPressState() { | |||
| 685 | } | 654 | } |
| 686 | 655 | ||
| 687 | bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const { | 656 | bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const { |
| 688 | const bool support_handheld = | ||
| 689 | std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(), NPAD_HANDHELD) != | ||
| 690 | supported_npad_id_types.end(); | ||
| 691 | if (controller == NPadControllerType::Handheld) { | 657 | if (controller == NPadControllerType::Handheld) { |
| 658 | const bool support_handheld = | ||
| 659 | std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(), | ||
| 660 | NPAD_HANDHELD) != supported_npad_id_types.end(); | ||
| 692 | // Handheld is not even a supported type, lets stop here | 661 | // Handheld is not even a supported type, lets stop here |
| 693 | if (!support_handheld) { | 662 | if (!support_handheld) { |
| 694 | return false; | 663 | return false; |
| @@ -700,6 +669,7 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const | |||
| 700 | 669 | ||
| 701 | return true; | 670 | return true; |
| 702 | } | 671 | } |
| 672 | |||
| 703 | if (std::any_of(supported_npad_id_types.begin(), supported_npad_id_types.end(), | 673 | if (std::any_of(supported_npad_id_types.begin(), supported_npad_id_types.end(), |
| 704 | [](u32 npad_id) { return npad_id <= MAX_NPAD_ID; })) { | 674 | [](u32 npad_id) { return npad_id <= MAX_NPAD_ID; })) { |
| 705 | switch (controller) { | 675 | switch (controller) { |
| @@ -717,6 +687,7 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const | |||
| 717 | return false; | 687 | return false; |
| 718 | } | 688 | } |
| 719 | } | 689 | } |
| 690 | |||
| 720 | return false; | 691 | return false; |
| 721 | } | 692 | } |
| 722 | 693 | ||
| @@ -795,6 +766,7 @@ Controller_NPad::NPadControllerType Controller_NPad::DecideBestController( | |||
| 795 | priority_list.push_back(NPadControllerType::JoyLeft); | 766 | priority_list.push_back(NPadControllerType::JoyLeft); |
| 796 | priority_list.push_back(NPadControllerType::JoyRight); | 767 | priority_list.push_back(NPadControllerType::JoyRight); |
| 797 | priority_list.push_back(NPadControllerType::JoyDual); | 768 | priority_list.push_back(NPadControllerType::JoyDual); |
| 769 | break; | ||
| 798 | } | 770 | } |
| 799 | 771 | ||
| 800 | const auto iter = std::find_if(priority_list.begin(), priority_list.end(), | 772 | const auto iter = std::find_if(priority_list.begin(), priority_list.end(), |
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 1bc3d55d6..16c4caa1f 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h | |||
| @@ -301,6 +301,11 @@ private: | |||
| 301 | bool is_connected; | 301 | bool is_connected; |
| 302 | }; | 302 | }; |
| 303 | 303 | ||
| 304 | void InitNewlyAddedControler(std::size_t controller_idx); | ||
| 305 | bool IsControllerSupported(NPadControllerType controller) const; | ||
| 306 | NPadControllerType DecideBestController(NPadControllerType priority) const; | ||
| 307 | void RequestPadStateUpdate(u32 npad_id); | ||
| 308 | |||
| 304 | u32 press_state{}; | 309 | u32 press_state{}; |
| 305 | 310 | ||
| 306 | NPadType style{}; | 311 | NPadType style{}; |
| @@ -321,12 +326,7 @@ private: | |||
| 321 | std::array<ControllerHolder, 10> connected_controllers{}; | 326 | std::array<ControllerHolder, 10> connected_controllers{}; |
| 322 | bool can_controllers_vibrate{true}; | 327 | bool can_controllers_vibrate{true}; |
| 323 | 328 | ||
| 324 | void InitNewlyAddedControler(std::size_t controller_idx); | ||
| 325 | bool IsControllerSupported(NPadControllerType controller) const; | ||
| 326 | NPadControllerType DecideBestController(NPadControllerType priority) const; | ||
| 327 | void RequestPadStateUpdate(u32 npad_id); | ||
| 328 | std::array<ControllerPad, 10> npad_pad_states{}; | 329 | std::array<ControllerPad, 10> npad_pad_states{}; |
| 329 | bool IsControllerSupported(NPadControllerType controller); | ||
| 330 | bool is_in_lr_assignment_mode{false}; | 330 | bool is_in_lr_assignment_mode{false}; |
| 331 | Core::System& system; | 331 | Core::System& system; |
| 332 | }; | 332 | }; |
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 7a6355ce2..d3d05a866 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -574,7 +574,7 @@ enum class ShuffleOperation : u64 { | |||
| 574 | }; | 574 | }; |
| 575 | 575 | ||
| 576 | union Instruction { | 576 | union Instruction { |
| 577 | Instruction& operator=(const Instruction& instr) { | 577 | constexpr Instruction& operator=(const Instruction& instr) { |
| 578 | value = instr.value; | 578 | value = instr.value; |
| 579 | return *this; | 579 | return *this; |
| 580 | } | 580 | } |
| @@ -1760,22 +1760,22 @@ public: | |||
| 1760 | 1760 | ||
| 1761 | class Matcher { | 1761 | class Matcher { |
| 1762 | public: | 1762 | public: |
| 1763 | Matcher(const char* const name, u16 mask, u16 expected, OpCode::Id id, OpCode::Type type) | 1763 | constexpr Matcher(const char* const name, u16 mask, u16 expected, Id id, Type type) |
| 1764 | : name{name}, mask{mask}, expected{expected}, id{id}, type{type} {} | 1764 | : name{name}, mask{mask}, expected{expected}, id{id}, type{type} {} |
| 1765 | 1765 | ||
| 1766 | const char* GetName() const { | 1766 | constexpr const char* GetName() const { |
| 1767 | return name; | 1767 | return name; |
| 1768 | } | 1768 | } |
| 1769 | 1769 | ||
| 1770 | u16 GetMask() const { | 1770 | constexpr u16 GetMask() const { |
| 1771 | return mask; | 1771 | return mask; |
| 1772 | } | 1772 | } |
| 1773 | 1773 | ||
| 1774 | Id GetId() const { | 1774 | constexpr Id GetId() const { |
| 1775 | return id; | 1775 | return id; |
| 1776 | } | 1776 | } |
| 1777 | 1777 | ||
| 1778 | Type GetType() const { | 1778 | constexpr Type GetType() const { |
| 1779 | return type; | 1779 | return type; |
| 1780 | } | 1780 | } |
| 1781 | 1781 | ||
| @@ -1784,7 +1784,7 @@ public: | |||
| 1784 | * @param instruction The instruction to test | 1784 | * @param instruction The instruction to test |
| 1785 | * @returns true if the given instruction matches. | 1785 | * @returns true if the given instruction matches. |
| 1786 | */ | 1786 | */ |
| 1787 | bool Matches(u16 instruction) const { | 1787 | constexpr bool Matches(u16 instruction) const { |
| 1788 | return (instruction & mask) == expected; | 1788 | return (instruction & mask) == expected; |
| 1789 | } | 1789 | } |
| 1790 | 1790 | ||
| @@ -1818,7 +1818,7 @@ private: | |||
| 1818 | * A '0' in a bitstring indicates that a zero must be present at that bit position. | 1818 | * A '0' in a bitstring indicates that a zero must be present at that bit position. |
| 1819 | * A '1' in a bitstring indicates that a one must be present at that bit position. | 1819 | * A '1' in a bitstring indicates that a one must be present at that bit position. |
| 1820 | */ | 1820 | */ |
| 1821 | static auto GetMaskAndExpect(const char* const bitstring) { | 1821 | static constexpr auto GetMaskAndExpect(const char* const bitstring) { |
| 1822 | u16 mask = 0, expect = 0; | 1822 | u16 mask = 0, expect = 0; |
| 1823 | for (std::size_t i = 0; i < opcode_bitsize; i++) { | 1823 | for (std::size_t i = 0; i < opcode_bitsize; i++) { |
| 1824 | const std::size_t bit_position = opcode_bitsize - i - 1; | 1824 | const std::size_t bit_position = opcode_bitsize - i - 1; |
| @@ -1835,15 +1835,15 @@ private: | |||
| 1835 | break; | 1835 | break; |
| 1836 | } | 1836 | } |
| 1837 | } | 1837 | } |
| 1838 | return std::make_tuple(mask, expect); | 1838 | return std::make_pair(mask, expect); |
| 1839 | } | 1839 | } |
| 1840 | 1840 | ||
| 1841 | public: | 1841 | public: |
| 1842 | /// Creates a matcher that can match and parse instructions based on bitstring. | 1842 | /// Creates a matcher that can match and parse instructions based on bitstring. |
| 1843 | static auto GetMatcher(const char* const bitstring, OpCode::Id op, OpCode::Type type, | 1843 | static constexpr auto GetMatcher(const char* const bitstring, Id op, Type type, |
| 1844 | const char* const name) { | 1844 | const char* const name) { |
| 1845 | const auto mask_expect = GetMaskAndExpect(bitstring); | 1845 | const auto [mask, expected] = GetMaskAndExpect(bitstring); |
| 1846 | return Matcher(name, std::get<0>(mask_expect), std::get<1>(mask_expect), op, type); | 1846 | return Matcher(name, mask, expected, op, type); |
| 1847 | } | 1847 | } |
| 1848 | }; | 1848 | }; |
| 1849 | 1849 | ||
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index a3524a6a9..baec66ff0 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -2314,10 +2314,13 @@ public: | |||
| 2314 | switch (index) { | 2314 | switch (index) { |
| 2315 | case Tegra::Shader::Pred::NeverExecute: | 2315 | case Tegra::Shader::Pred::NeverExecute: |
| 2316 | target = "false"; | 2316 | target = "false"; |
| 2317 | break; | ||
| 2317 | case Tegra::Shader::Pred::UnusedIndex: | 2318 | case Tegra::Shader::Pred::UnusedIndex: |
| 2318 | target = "true"; | 2319 | target = "true"; |
| 2320 | break; | ||
| 2319 | default: | 2321 | default: |
| 2320 | target = decomp.GetPredicate(index); | 2322 | target = decomp.GetPredicate(index); |
| 2323 | break; | ||
| 2321 | } | 2324 | } |
| 2322 | } else if (const auto flag = std::get_if<InternalFlagNode>(&*cc)) { | 2325 | } else if (const auto flag = std::get_if<InternalFlagNode>(&*cc)) { |
| 2323 | target = decomp.GetInternalFlag(flag->GetFlag()); | 2326 | target = decomp.GetInternalFlag(flag->GetFlag()); |
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp index 3fb016b96..0d943a826 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp | |||
| @@ -1682,10 +1682,13 @@ public: | |||
| 1682 | switch (index) { | 1682 | switch (index) { |
| 1683 | case Tegra::Shader::Pred::NeverExecute: | 1683 | case Tegra::Shader::Pred::NeverExecute: |
| 1684 | target = decomp.v_false; | 1684 | target = decomp.v_false; |
| 1685 | break; | ||
| 1685 | case Tegra::Shader::Pred::UnusedIndex: | 1686 | case Tegra::Shader::Pred::UnusedIndex: |
| 1686 | target = decomp.v_true; | 1687 | target = decomp.v_true; |
| 1688 | break; | ||
| 1687 | default: | 1689 | default: |
| 1688 | target = decomp.predicates.at(index); | 1690 | target = decomp.predicates.at(index); |
| 1691 | break; | ||
| 1689 | } | 1692 | } |
| 1690 | } else if (const auto flag = std::get_if<InternalFlagNode>(&*cc)) { | 1693 | } else if (const auto flag = std::get_if<InternalFlagNode>(&*cc)) { |
| 1691 | target = decomp.internal_flags.at(static_cast<u32>(flag->GetFlag())); | 1694 | target = decomp.internal_flags.at(static_cast<u32>(flag->GetFlag())); |
diff --git a/src/video_core/shader/decode/arithmetic_integer.cpp b/src/video_core/shader/decode/arithmetic_integer.cpp index b73f6536e..a33d242e9 100644 --- a/src/video_core/shader/decode/arithmetic_integer.cpp +++ b/src/video_core/shader/decode/arithmetic_integer.cpp | |||
| @@ -144,7 +144,7 @@ u32 ShaderIR::DecodeArithmeticInteger(NodeBlock& bb, u32 pc) { | |||
| 144 | case OpCode::Id::ICMP_IMM: { | 144 | case OpCode::Id::ICMP_IMM: { |
| 145 | const Node zero = Immediate(0); | 145 | const Node zero = Immediate(0); |
| 146 | 146 | ||
| 147 | const auto [op_b, test] = [&]() -> std::pair<Node, Node> { | 147 | const auto [op_rhs, test] = [&]() -> std::pair<Node, Node> { |
| 148 | switch (opcode->get().GetId()) { | 148 | switch (opcode->get().GetId()) { |
| 149 | case OpCode::Id::ICMP_CR: | 149 | case OpCode::Id::ICMP_CR: |
| 150 | return {GetConstBuffer(instr.cbuf34.index, instr.cbuf34.offset), | 150 | return {GetConstBuffer(instr.cbuf34.index, instr.cbuf34.offset), |
| @@ -161,10 +161,10 @@ u32 ShaderIR::DecodeArithmeticInteger(NodeBlock& bb, u32 pc) { | |||
| 161 | return {zero, zero}; | 161 | return {zero, zero}; |
| 162 | } | 162 | } |
| 163 | }(); | 163 | }(); |
| 164 | const Node op_a = GetRegister(instr.gpr8); | 164 | const Node op_lhs = GetRegister(instr.gpr8); |
| 165 | const Node comparison = | 165 | const Node comparison = |
| 166 | GetPredicateComparisonInteger(instr.icmp.cond, instr.icmp.is_signed != 0, test, zero); | 166 | GetPredicateComparisonInteger(instr.icmp.cond, instr.icmp.is_signed != 0, test, zero); |
| 167 | SetRegister(bb, instr.gpr0, Operation(OperationCode::Select, comparison, op_a, op_b)); | 167 | SetRegister(bb, instr.gpr0, Operation(OperationCode::Select, comparison, op_lhs, op_rhs)); |
| 168 | break; | 168 | break; |
| 169 | } | 169 | } |
| 170 | case OpCode::Id::LOP_C: | 170 | case OpCode::Id::LOP_C: |
diff --git a/src/video_core/shader/decode/image.cpp b/src/video_core/shader/decode/image.cpp index 95ec1cdd9..b02d2cb95 100644 --- a/src/video_core/shader/decode/image.cpp +++ b/src/video_core/shader/decode/image.cpp | |||
| @@ -144,8 +144,8 @@ u32 ShaderIR::DecodeImage(NodeBlock& bb, u32 pc) { | |||
| 144 | 144 | ||
| 145 | Image& ShaderIR::GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type) { | 145 | Image& ShaderIR::GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type) { |
| 146 | const auto offset{static_cast<std::size_t>(image.index.Value())}; | 146 | const auto offset{static_cast<std::size_t>(image.index.Value())}; |
| 147 | if (const auto image = TryUseExistingImage(offset, type)) { | 147 | if (const auto existing_image = TryUseExistingImage(offset, type)) { |
| 148 | return *image; | 148 | return *existing_image; |
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | const std::size_t next_index{used_images.size()}; | 151 | const std::size_t next_index{used_images.size()}; |
diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp index 7923d4d69..335d78146 100644 --- a/src/video_core/shader/decode/memory.cpp +++ b/src/video_core/shader/decode/memory.cpp | |||
| @@ -166,9 +166,17 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { | |||
| 166 | }(); | 166 | }(); |
| 167 | 167 | ||
| 168 | const auto [real_address_base, base_address, descriptor] = | 168 | const auto [real_address_base, base_address, descriptor] = |
| 169 | TrackAndGetGlobalMemory(bb, instr, false); | 169 | TrackGlobalMemory(bb, instr, false); |
| 170 | 170 | ||
| 171 | const u32 count = GetUniformTypeElementsCount(type); | 171 | const u32 count = GetUniformTypeElementsCount(type); |
| 172 | if (!real_address_base || !base_address) { | ||
| 173 | // Tracking failed, load zeroes. | ||
| 174 | for (u32 i = 0; i < count; ++i) { | ||
| 175 | SetRegister(bb, instr.gpr0.Value() + i, Immediate(0.0f)); | ||
| 176 | } | ||
| 177 | break; | ||
| 178 | } | ||
| 179 | |||
| 172 | for (u32 i = 0; i < count; ++i) { | 180 | for (u32 i = 0; i < count; ++i) { |
| 173 | const Node it_offset = Immediate(i * 4); | 181 | const Node it_offset = Immediate(i * 4); |
| 174 | const Node real_address = | 182 | const Node real_address = |
| @@ -260,22 +268,19 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { | |||
| 260 | }(); | 268 | }(); |
| 261 | 269 | ||
| 262 | const auto [real_address_base, base_address, descriptor] = | 270 | const auto [real_address_base, base_address, descriptor] = |
| 263 | TrackAndGetGlobalMemory(bb, instr, true); | 271 | TrackGlobalMemory(bb, instr, true); |
| 264 | 272 | if (!real_address_base || !base_address) { | |
| 265 | // Encode in temporary registers like this: real_base_address, {registers_to_be_written...} | 273 | // Tracking failed, skip the store. |
| 266 | SetTemporary(bb, 0, real_address_base); | 274 | break; |
| 275 | } | ||
| 267 | 276 | ||
| 268 | const u32 count = GetUniformTypeElementsCount(type); | 277 | const u32 count = GetUniformTypeElementsCount(type); |
| 269 | for (u32 i = 0; i < count; ++i) { | 278 | for (u32 i = 0; i < count; ++i) { |
| 270 | SetTemporary(bb, i + 1, GetRegister(instr.gpr0.Value() + i)); | ||
| 271 | } | ||
| 272 | for (u32 i = 0; i < count; ++i) { | ||
| 273 | const Node it_offset = Immediate(i * 4); | 279 | const Node it_offset = Immediate(i * 4); |
| 274 | const Node real_address = | 280 | const Node real_address = Operation(OperationCode::UAdd, real_address_base, it_offset); |
| 275 | Operation(OperationCode::UAdd, NO_PRECISE, real_address_base, it_offset); | ||
| 276 | const Node gmem = MakeNode<GmemNode>(real_address, base_address, descriptor); | 281 | const Node gmem = MakeNode<GmemNode>(real_address, base_address, descriptor); |
| 277 | 282 | const Node value = GetRegister(instr.gpr0.Value() + i); | |
| 278 | bb.push_back(Operation(OperationCode::Assign, gmem, GetTemporary(i + 1))); | 283 | bb.push_back(Operation(OperationCode::Assign, gmem, value)); |
| 279 | } | 284 | } |
| 280 | break; | 285 | break; |
| 281 | } | 286 | } |
| @@ -301,15 +306,17 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { | |||
| 301 | return pc; | 306 | return pc; |
| 302 | } | 307 | } |
| 303 | 308 | ||
| 304 | std::tuple<Node, Node, GlobalMemoryBase> ShaderIR::TrackAndGetGlobalMemory(NodeBlock& bb, | 309 | std::tuple<Node, Node, GlobalMemoryBase> ShaderIR::TrackGlobalMemory(NodeBlock& bb, |
| 305 | Instruction instr, | 310 | Instruction instr, |
| 306 | bool is_write) { | 311 | bool is_write) { |
| 307 | const auto addr_register{GetRegister(instr.gmem.gpr)}; | 312 | const auto addr_register{GetRegister(instr.gmem.gpr)}; |
| 308 | const auto immediate_offset{static_cast<u32>(instr.gmem.offset)}; | 313 | const auto immediate_offset{static_cast<u32>(instr.gmem.offset)}; |
| 309 | 314 | ||
| 310 | const auto [base_address, index, offset] = | 315 | const auto [base_address, index, offset] = |
| 311 | TrackCbuf(addr_register, global_code, static_cast<s64>(global_code.size())); | 316 | TrackCbuf(addr_register, global_code, static_cast<s64>(global_code.size())); |
| 312 | ASSERT(base_address != nullptr); | 317 | ASSERT_OR_EXECUTE_MSG(base_address != nullptr, |
| 318 | { return std::make_tuple(nullptr, nullptr, GlobalMemoryBase{}); }, | ||
| 319 | "Global memory tracking failed"); | ||
| 313 | 320 | ||
| 314 | bb.push_back(Comment(fmt::format("Base address is c[0x{:x}][0x{:x}]", index, offset))); | 321 | bb.push_back(Comment(fmt::format("Base address is c[0x{:x}][0x{:x}]", index, offset))); |
| 315 | 322 | ||
diff --git a/src/video_core/shader/decode/other.cpp b/src/video_core/shader/decode/other.cpp index d46e0f823..116b95f76 100644 --- a/src/video_core/shader/decode/other.cpp +++ b/src/video_core/shader/decode/other.cpp | |||
| @@ -67,7 +67,7 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) { | |||
| 67 | break; | 67 | break; |
| 68 | } | 68 | } |
| 69 | case OpCode::Id::MOV_SYS: { | 69 | case OpCode::Id::MOV_SYS: { |
| 70 | const Node value = [&]() { | 70 | const Node value = [this, instr] { |
| 71 | switch (instr.sys20) { | 71 | switch (instr.sys20) { |
| 72 | case SystemVariable::Ydirection: | 72 | case SystemVariable::Ydirection: |
| 73 | return Operation(OperationCode::YNegate); | 73 | return Operation(OperationCode::YNegate); |
diff --git a/src/video_core/shader/decode/shift.cpp b/src/video_core/shader/decode/shift.cpp index f6ee68a54..d419e9c45 100644 --- a/src/video_core/shader/decode/shift.cpp +++ b/src/video_core/shader/decode/shift.cpp | |||
| @@ -18,7 +18,7 @@ u32 ShaderIR::DecodeShift(NodeBlock& bb, u32 pc) { | |||
| 18 | const auto opcode = OpCode::Decode(instr); | 18 | const auto opcode = OpCode::Decode(instr); |
| 19 | 19 | ||
| 20 | Node op_a = GetRegister(instr.gpr8); | 20 | Node op_a = GetRegister(instr.gpr8); |
| 21 | Node op_b = [&]() { | 21 | Node op_b = [this, instr] { |
| 22 | if (instr.is_b_imm) { | 22 | if (instr.is_b_imm) { |
| 23 | return Immediate(instr.alu.GetSignedImm20_20()); | 23 | return Immediate(instr.alu.GetSignedImm20_20()); |
| 24 | } else if (instr.is_b_gpr) { | 24 | } else if (instr.is_b_gpr) { |
diff --git a/src/video_core/shader/decode/video.cpp b/src/video_core/shader/decode/video.cpp index 97fc6f9b1..b047cf870 100644 --- a/src/video_core/shader/decode/video.cpp +++ b/src/video_core/shader/decode/video.cpp | |||
| @@ -23,7 +23,7 @@ u32 ShaderIR::DecodeVideo(NodeBlock& bb, u32 pc) { | |||
| 23 | const Node op_a = | 23 | const Node op_a = |
| 24 | GetVideoOperand(GetRegister(instr.gpr8), instr.video.is_byte_chunk_a, instr.video.signed_a, | 24 | GetVideoOperand(GetRegister(instr.gpr8), instr.video.is_byte_chunk_a, instr.video.signed_a, |
| 25 | instr.video.type_a, instr.video.byte_height_a); | 25 | instr.video.type_a, instr.video.byte_height_a); |
| 26 | const Node op_b = [&]() { | 26 | const Node op_b = [this, instr] { |
| 27 | if (instr.video.use_register_b) { | 27 | if (instr.video.use_register_b) { |
| 28 | return GetVideoOperand(GetRegister(instr.gpr20), instr.video.is_byte_chunk_b, | 28 | return GetVideoOperand(GetRegister(instr.gpr20), instr.video.is_byte_chunk_b, |
| 29 | instr.video.signed_b, instr.video.type_b, | 29 | instr.video.signed_b, instr.video.type_b, |
diff --git a/src/video_core/shader/decode/warp.cpp b/src/video_core/shader/decode/warp.cpp index a8e481b3c..fa8a250cc 100644 --- a/src/video_core/shader/decode/warp.cpp +++ b/src/video_core/shader/decode/warp.cpp | |||
| @@ -46,9 +46,10 @@ u32 ShaderIR::DecodeWarp(NodeBlock& bb, u32 pc) { | |||
| 46 | break; | 46 | break; |
| 47 | } | 47 | } |
| 48 | case OpCode::Id::SHFL: { | 48 | case OpCode::Id::SHFL: { |
| 49 | Node mask = instr.shfl.is_mask_imm ? Immediate(static_cast<u32>(instr.shfl.mask_imm)) | 49 | Node width = [this, instr] { |
| 50 | : GetRegister(instr.gpr39); | 50 | Node mask = instr.shfl.is_mask_imm ? Immediate(static_cast<u32>(instr.shfl.mask_imm)) |
| 51 | Node width = [&] { | 51 | : GetRegister(instr.gpr39); |
| 52 | |||
| 52 | // Convert the obscure SHFL mask back into GL_NV_shader_thread_shuffle's width. This has | 53 | // Convert the obscure SHFL mask back into GL_NV_shader_thread_shuffle's width. This has |
| 53 | // been done reversing Nvidia's math. It won't work on all cases due to SHFL having | 54 | // been done reversing Nvidia's math. It won't work on all cases due to SHFL having |
| 54 | // different parameters that don't properly map to GLSL's interface, but it should work | 55 | // different parameters that don't properly map to GLSL's interface, but it should work |
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index df64845f5..02ddf2a75 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h | |||
| @@ -371,8 +371,9 @@ private: | |||
| 371 | std::pair<Node, s64> TrackRegister(const GprNode* tracked, const NodeBlock& code, | 371 | std::pair<Node, s64> TrackRegister(const GprNode* tracked, const NodeBlock& code, |
| 372 | s64 cursor) const; | 372 | s64 cursor) const; |
| 373 | 373 | ||
| 374 | std::tuple<Node, Node, GlobalMemoryBase> TrackAndGetGlobalMemory( | 374 | std::tuple<Node, Node, GlobalMemoryBase> TrackGlobalMemory(NodeBlock& bb, |
| 375 | NodeBlock& bb, Tegra::Shader::Instruction instr, bool is_write); | 375 | Tegra::Shader::Instruction instr, |
| 376 | bool is_write); | ||
| 376 | 377 | ||
| 377 | const ProgramCode& program_code; | 378 | const ProgramCode& program_code; |
| 378 | const u32 main_offset; | 379 | const u32 main_offset; |