diff options
| -rw-r--r-- | src/audio_core/in/audio_in_system.cpp | 2 | ||||
| -rw-r--r-- | src/audio_core/in/audio_in_system.h | 2 | ||||
| -rw-r--r-- | src/audio_core/out/audio_out_system.cpp | 4 | ||||
| -rw-r--r-- | src/audio_core/out/audio_out_system.h | 4 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_32.cpp | 2 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_64.cpp | 2 | ||||
| -rw-r--r-- | src/core/file_sys/control_metadata.cpp | 43 | ||||
| -rw-r--r-- | src/core/file_sys/control_metadata.h | 6 | ||||
| -rw-r--r-- | src/core/hle/service/audio/audin_u.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/service/audio/audout_u.cpp | 2 | ||||
| -rw-r--r-- | src/shader_recompiler/frontend/ir/microinstruction.cpp | 5 | ||||
| -rw-r--r-- | src/shader_recompiler/frontend/ir/value.h | 4 | ||||
| -rw-r--r-- | src/shader_recompiler/ir_opt/dead_code_elimination_pass.cpp | 98 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.cpp | 129 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.h | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_rasterizer.cpp | 21 |
16 files changed, 139 insertions, 189 deletions
diff --git a/src/audio_core/in/audio_in_system.cpp b/src/audio_core/in/audio_in_system.cpp index 6b7e6715c..4324cafd8 100644 --- a/src/audio_core/in/audio_in_system.cpp +++ b/src/audio_core/in/audio_in_system.cpp | |||
| @@ -56,7 +56,7 @@ Result System::IsConfigValid(const std::string_view device_name, | |||
| 56 | return ResultSuccess; | 56 | return ResultSuccess; |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | Result System::Initialize(std::string& device_name, const AudioInParameter& in_params, | 59 | Result System::Initialize(std::string device_name, const AudioInParameter& in_params, |
| 60 | const u32 handle_, const u64 applet_resource_user_id_) { | 60 | const u32 handle_, const u64 applet_resource_user_id_) { |
| 61 | auto result{IsConfigValid(device_name, in_params)}; | 61 | auto result{IsConfigValid(device_name, in_params)}; |
| 62 | if (result.IsError()) { | 62 | if (result.IsError()) { |
diff --git a/src/audio_core/in/audio_in_system.h b/src/audio_core/in/audio_in_system.h index b9dc0e60f..1c5154638 100644 --- a/src/audio_core/in/audio_in_system.h +++ b/src/audio_core/in/audio_in_system.h | |||
| @@ -97,7 +97,7 @@ public: | |||
| 97 | * @param applet_resource_user_id - Unused. | 97 | * @param applet_resource_user_id - Unused. |
| 98 | * @return Result code. | 98 | * @return Result code. |
| 99 | */ | 99 | */ |
| 100 | Result Initialize(std::string& device_name, const AudioInParameter& in_params, u32 handle, | 100 | Result Initialize(std::string device_name, const AudioInParameter& in_params, u32 handle, |
| 101 | u64 applet_resource_user_id); | 101 | u64 applet_resource_user_id); |
| 102 | 102 | ||
| 103 | /** | 103 | /** |
diff --git a/src/audio_core/out/audio_out_system.cpp b/src/audio_core/out/audio_out_system.cpp index 48a801923..a66208ed9 100644 --- a/src/audio_core/out/audio_out_system.cpp +++ b/src/audio_core/out/audio_out_system.cpp | |||
| @@ -49,8 +49,8 @@ Result System::IsConfigValid(std::string_view device_name, | |||
| 49 | return Service::Audio::ERR_INVALID_CHANNEL_COUNT; | 49 | return Service::Audio::ERR_INVALID_CHANNEL_COUNT; |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | Result System::Initialize(std::string& device_name, const AudioOutParameter& in_params, u32 handle_, | 52 | Result System::Initialize(std::string device_name, const AudioOutParameter& in_params, u32 handle_, |
| 53 | u64& applet_resource_user_id_) { | 53 | u64 applet_resource_user_id_) { |
| 54 | auto result = IsConfigValid(device_name, in_params); | 54 | auto result = IsConfigValid(device_name, in_params); |
| 55 | if (result.IsError()) { | 55 | if (result.IsError()) { |
| 56 | return result; | 56 | return result; |
diff --git a/src/audio_core/out/audio_out_system.h b/src/audio_core/out/audio_out_system.h index 0817b2f37..b95cb91be 100644 --- a/src/audio_core/out/audio_out_system.h +++ b/src/audio_core/out/audio_out_system.h | |||
| @@ -88,8 +88,8 @@ public: | |||
| 88 | * @param applet_resource_user_id - Unused. | 88 | * @param applet_resource_user_id - Unused. |
| 89 | * @return Result code. | 89 | * @return Result code. |
| 90 | */ | 90 | */ |
| 91 | Result Initialize(std::string& device_name, const AudioOutParameter& in_params, u32 handle, | 91 | Result Initialize(std::string device_name, const AudioOutParameter& in_params, u32 handle, |
| 92 | u64& applet_resource_user_id); | 92 | u64 applet_resource_user_id); |
| 93 | 93 | ||
| 94 | /** | 94 | /** |
| 95 | * Start this system. | 95 | * Start this system. |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index d1e70f19d..287ba102e 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp | |||
| @@ -450,7 +450,7 @@ std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_32::GetBacktrace(Core::S | |||
| 450 | // Frame records are two words long: | 450 | // Frame records are two words long: |
| 451 | // fp+0 : pointer to previous frame record | 451 | // fp+0 : pointer to previous frame record |
| 452 | // fp+4 : value of lr for frame | 452 | // fp+4 : value of lr for frame |
| 453 | while (true) { | 453 | for (size_t i = 0; i < 256; i++) { |
| 454 | out.push_back({"", 0, lr, 0, ""}); | 454 | out.push_back({"", 0, lr, 0, ""}); |
| 455 | if (!fp || (fp % 4 != 0) || !memory.IsValidVirtualAddressRange(fp, 8)) { | 455 | if (!fp || (fp % 4 != 0) || !memory.IsValidVirtualAddressRange(fp, 8)) { |
| 456 | break; | 456 | break; |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 22b5d5656..afb7fb3a0 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp | |||
| @@ -517,7 +517,7 @@ std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_64::GetBacktrace(Core::S | |||
| 517 | // Frame records are two words long: | 517 | // Frame records are two words long: |
| 518 | // fp+0 : pointer to previous frame record | 518 | // fp+0 : pointer to previous frame record |
| 519 | // fp+8 : value of lr for frame | 519 | // fp+8 : value of lr for frame |
| 520 | while (true) { | 520 | for (size_t i = 0; i < 256; i++) { |
| 521 | out.push_back({"", 0, lr, 0, ""}); | 521 | out.push_back({"", 0, lr, 0, ""}); |
| 522 | if (!fp || (fp % 4 != 0) || !memory.IsValidVirtualAddressRange(fp, 16)) { | 522 | if (!fp || (fp % 4 != 0) || !memory.IsValidVirtualAddressRange(fp, 16)) { |
| 523 | break; | 523 | break; |
diff --git a/src/core/file_sys/control_metadata.cpp b/src/core/file_sys/control_metadata.cpp index be25da2f6..50f44f598 100644 --- a/src/core/file_sys/control_metadata.cpp +++ b/src/core/file_sys/control_metadata.cpp | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include "common/settings.h" | ||
| 4 | #include "common/string_util.h" | 5 | #include "common/string_util.h" |
| 5 | #include "common/swap.h" | 6 | #include "common/swap.h" |
| 6 | #include "core/file_sys/control_metadata.h" | 7 | #include "core/file_sys/control_metadata.h" |
| @@ -37,6 +38,27 @@ std::string LanguageEntry::GetDeveloperName() const { | |||
| 37 | developer_name.size()); | 38 | developer_name.size()); |
| 38 | } | 39 | } |
| 39 | 40 | ||
| 41 | constexpr std::array<Language, 18> language_to_codes = {{ | ||
| 42 | Language::Japanese, | ||
| 43 | Language::AmericanEnglish, | ||
| 44 | Language::French, | ||
| 45 | Language::German, | ||
| 46 | Language::Italian, | ||
| 47 | Language::Spanish, | ||
| 48 | Language::Chinese, | ||
| 49 | Language::Korean, | ||
| 50 | Language::Dutch, | ||
| 51 | Language::Portuguese, | ||
| 52 | Language::Russian, | ||
| 53 | Language::Taiwanese, | ||
| 54 | Language::BritishEnglish, | ||
| 55 | Language::CanadianFrench, | ||
| 56 | Language::LatinAmericanSpanish, | ||
| 57 | Language::Chinese, | ||
| 58 | Language::Taiwanese, | ||
| 59 | Language::BrazilianPortuguese, | ||
| 60 | }}; | ||
| 61 | |||
| 40 | NACP::NACP() = default; | 62 | NACP::NACP() = default; |
| 41 | 63 | ||
| 42 | NACP::NACP(VirtualFile file) { | 64 | NACP::NACP(VirtualFile file) { |
| @@ -45,9 +67,13 @@ NACP::NACP(VirtualFile file) { | |||
| 45 | 67 | ||
| 46 | NACP::~NACP() = default; | 68 | NACP::~NACP() = default; |
| 47 | 69 | ||
| 48 | const LanguageEntry& NACP::GetLanguageEntry(Language language) const { | 70 | const LanguageEntry& NACP::GetLanguageEntry() const { |
| 49 | if (language != Language::Default) { | 71 | Language language = language_to_codes[Settings::values.language_index.GetValue()]; |
| 50 | return raw.language_entries.at(static_cast<u8>(language)); | 72 | |
| 73 | { | ||
| 74 | const auto& language_entry = raw.language_entries.at(static_cast<u8>(language)); | ||
| 75 | if (!language_entry.GetApplicationName().empty()) | ||
| 76 | return language_entry; | ||
| 51 | } | 77 | } |
| 52 | 78 | ||
| 53 | for (const auto& language_entry : raw.language_entries) { | 79 | for (const auto& language_entry : raw.language_entries) { |
| @@ -55,16 +81,15 @@ const LanguageEntry& NACP::GetLanguageEntry(Language language) const { | |||
| 55 | return language_entry; | 81 | return language_entry; |
| 56 | } | 82 | } |
| 57 | 83 | ||
| 58 | // Fallback to English | 84 | return raw.language_entries.at(static_cast<u8>(Language::AmericanEnglish)); |
| 59 | return GetLanguageEntry(Language::AmericanEnglish); | ||
| 60 | } | 85 | } |
| 61 | 86 | ||
| 62 | std::string NACP::GetApplicationName(Language language) const { | 87 | std::string NACP::GetApplicationName() const { |
| 63 | return GetLanguageEntry(language).GetApplicationName(); | 88 | return GetLanguageEntry().GetApplicationName(); |
| 64 | } | 89 | } |
| 65 | 90 | ||
| 66 | std::string NACP::GetDeveloperName(Language language) const { | 91 | std::string NACP::GetDeveloperName() const { |
| 67 | return GetLanguageEntry(language).GetDeveloperName(); | 92 | return GetLanguageEntry().GetDeveloperName(); |
| 68 | } | 93 | } |
| 69 | 94 | ||
| 70 | u64 NACP::GetTitleId() const { | 95 | u64 NACP::GetTitleId() const { |
diff --git a/src/core/file_sys/control_metadata.h b/src/core/file_sys/control_metadata.h index 75295519c..6a81873b1 100644 --- a/src/core/file_sys/control_metadata.h +++ b/src/core/file_sys/control_metadata.h | |||
| @@ -101,9 +101,9 @@ public: | |||
| 101 | explicit NACP(VirtualFile file); | 101 | explicit NACP(VirtualFile file); |
| 102 | ~NACP(); | 102 | ~NACP(); |
| 103 | 103 | ||
| 104 | const LanguageEntry& GetLanguageEntry(Language language = Language::Default) const; | 104 | const LanguageEntry& GetLanguageEntry() const; |
| 105 | std::string GetApplicationName(Language language = Language::Default) const; | 105 | std::string GetApplicationName() const; |
| 106 | std::string GetDeveloperName(Language language = Language::Default) const; | 106 | std::string GetDeveloperName() const; |
| 107 | u64 GetTitleId() const; | 107 | u64 GetTitleId() const; |
| 108 | u64 GetDLCBaseTitleId() const; | 108 | u64 GetDLCBaseTitleId() const; |
| 109 | std::string GetVersionString() const; | 109 | std::string GetVersionString() const; |
diff --git a/src/core/hle/service/audio/audin_u.cpp b/src/core/hle/service/audio/audin_u.cpp index 48a9a73a0..608925dfc 100644 --- a/src/core/hle/service/audio/audin_u.cpp +++ b/src/core/hle/service/audio/audin_u.cpp | |||
| @@ -17,7 +17,7 @@ using namespace AudioCore::AudioIn; | |||
| 17 | class IAudioIn final : public ServiceFramework<IAudioIn> { | 17 | class IAudioIn final : public ServiceFramework<IAudioIn> { |
| 18 | public: | 18 | public: |
| 19 | explicit IAudioIn(Core::System& system_, Manager& manager, size_t session_id, | 19 | explicit IAudioIn(Core::System& system_, Manager& manager, size_t session_id, |
| 20 | std::string& device_name, const AudioInParameter& in_params, u32 handle, | 20 | const std::string& device_name, const AudioInParameter& in_params, u32 handle, |
| 21 | u64 applet_resource_user_id) | 21 | u64 applet_resource_user_id) |
| 22 | : ServiceFramework{system_, "IAudioIn"}, | 22 | : ServiceFramework{system_, "IAudioIn"}, |
| 23 | service_context{system_, "IAudioIn"}, event{service_context.CreateEvent("AudioInEvent")}, | 23 | service_context{system_, "IAudioIn"}, event{service_context.CreateEvent("AudioInEvent")}, |
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp index 49c092301..122290c6a 100644 --- a/src/core/hle/service/audio/audout_u.cpp +++ b/src/core/hle/service/audio/audout_u.cpp | |||
| @@ -24,7 +24,7 @@ using namespace AudioCore::AudioOut; | |||
| 24 | class IAudioOut final : public ServiceFramework<IAudioOut> { | 24 | class IAudioOut final : public ServiceFramework<IAudioOut> { |
| 25 | public: | 25 | public: |
| 26 | explicit IAudioOut(Core::System& system_, AudioCore::AudioOut::Manager& manager, | 26 | explicit IAudioOut(Core::System& system_, AudioCore::AudioOut::Manager& manager, |
| 27 | size_t session_id, std::string& device_name, | 27 | size_t session_id, const std::string& device_name, |
| 28 | const AudioOutParameter& in_params, u32 handle, u64 applet_resource_user_id) | 28 | const AudioOutParameter& in_params, u32 handle, u64 applet_resource_user_id) |
| 29 | : ServiceFramework{system_, "IAudioOut", ServiceThreadType::CreateNew}, | 29 | : ServiceFramework{system_, "IAudioOut", ServiceThreadType::CreateNew}, |
| 30 | service_context{system_, "IAudioOut"}, event{service_context.CreateEvent( | 30 | service_context{system_, "IAudioOut"}, event{service_context.CreateEvent( |
diff --git a/src/shader_recompiler/frontend/ir/microinstruction.cpp b/src/shader_recompiler/frontend/ir/microinstruction.cpp index 468782eb1..84417980b 100644 --- a/src/shader_recompiler/frontend/ir/microinstruction.cpp +++ b/src/shader_recompiler/frontend/ir/microinstruction.cpp | |||
| @@ -325,11 +325,6 @@ void Inst::AddPhiOperand(Block* predecessor, const Value& value) { | |||
| 325 | phi_args.emplace_back(predecessor, value); | 325 | phi_args.emplace_back(predecessor, value); |
| 326 | } | 326 | } |
| 327 | 327 | ||
| 328 | void Inst::ErasePhiOperand(size_t index) { | ||
| 329 | const auto operand_it{phi_args.begin() + static_cast<ptrdiff_t>(index)}; | ||
| 330 | phi_args.erase(operand_it); | ||
| 331 | } | ||
| 332 | |||
| 333 | void Inst::OrderPhiArgs() { | 328 | void Inst::OrderPhiArgs() { |
| 334 | if (op != Opcode::Phi) { | 329 | if (op != Opcode::Phi) { |
| 335 | throw LogicError("{} is not a Phi instruction", op); | 330 | throw LogicError("{} is not a Phi instruction", op); |
diff --git a/src/shader_recompiler/frontend/ir/value.h b/src/shader_recompiler/frontend/ir/value.h index 1a2e4ccb6..6a673ca05 100644 --- a/src/shader_recompiler/frontend/ir/value.h +++ b/src/shader_recompiler/frontend/ir/value.h | |||
| @@ -178,13 +178,9 @@ public: | |||
| 178 | 178 | ||
| 179 | /// Get a pointer to the block of a phi argument. | 179 | /// Get a pointer to the block of a phi argument. |
| 180 | [[nodiscard]] Block* PhiBlock(size_t index) const; | 180 | [[nodiscard]] Block* PhiBlock(size_t index) const; |
| 181 | |||
| 182 | /// Add phi operand to a phi instruction. | 181 | /// Add phi operand to a phi instruction. |
| 183 | void AddPhiOperand(Block* predecessor, const Value& value); | 182 | void AddPhiOperand(Block* predecessor, const Value& value); |
| 184 | 183 | ||
| 185 | // Erase the phi operand at the given index. | ||
| 186 | void ErasePhiOperand(size_t index); | ||
| 187 | |||
| 188 | /// Orders the Phi arguments from farthest away to nearest. | 184 | /// Orders the Phi arguments from farthest away to nearest. |
| 189 | void OrderPhiArgs(); | 185 | void OrderPhiArgs(); |
| 190 | 186 | ||
diff --git a/src/shader_recompiler/ir_opt/dead_code_elimination_pass.cpp b/src/shader_recompiler/ir_opt/dead_code_elimination_pass.cpp index 9a7d47344..1bd8afd6f 100644 --- a/src/shader_recompiler/ir_opt/dead_code_elimination_pass.cpp +++ b/src/shader_recompiler/ir_opt/dead_code_elimination_pass.cpp | |||
| @@ -1,104 +1,24 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include <algorithm> | ||
| 5 | |||
| 6 | #include <boost/container/small_vector.hpp> | ||
| 7 | |||
| 8 | #include "shader_recompiler/frontend/ir/basic_block.h" | 4 | #include "shader_recompiler/frontend/ir/basic_block.h" |
| 9 | #include "shader_recompiler/frontend/ir/value.h" | 5 | #include "shader_recompiler/frontend/ir/value.h" |
| 10 | #include "shader_recompiler/ir_opt/passes.h" | 6 | #include "shader_recompiler/ir_opt/passes.h" |
| 11 | 7 | ||
| 12 | namespace Shader::Optimization { | 8 | namespace Shader::Optimization { |
| 13 | namespace { | 9 | |
| 14 | template <bool TEST_USES> | 10 | void DeadCodeEliminationPass(IR::Program& program) { |
| 15 | void DeadInstElimination(IR::Block* const block) { | ||
| 16 | // We iterate over the instructions in reverse order. | 11 | // We iterate over the instructions in reverse order. |
| 17 | // This is because removing an instruction reduces the number of uses for earlier instructions. | 12 | // This is because removing an instruction reduces the number of uses for earlier instructions. |
| 18 | auto it{block->end()}; | 13 | for (IR::Block* const block : program.post_order_blocks) { |
| 19 | while (it != block->begin()) { | 14 | auto it{block->end()}; |
| 20 | --it; | 15 | while (it != block->begin()) { |
| 21 | if constexpr (TEST_USES) { | 16 | --it; |
| 22 | if (it->HasUses() || it->MayHaveSideEffects()) { | 17 | if (!it->HasUses() && !it->MayHaveSideEffects()) { |
| 23 | continue; | 18 | it->Invalidate(); |
| 24 | } | 19 | it = block->Instructions().erase(it); |
| 25 | } | ||
| 26 | it->Invalidate(); | ||
| 27 | it = block->Instructions().erase(it); | ||
| 28 | } | ||
| 29 | } | ||
| 30 | |||
| 31 | void DeletedPhiArgElimination(IR::Program& program, std::span<const IR::Block*> dead_blocks) { | ||
| 32 | for (IR::Block* const block : program.blocks) { | ||
| 33 | for (IR::Inst& phi : *block) { | ||
| 34 | if (!IR::IsPhi(phi)) { | ||
| 35 | continue; | ||
| 36 | } | ||
| 37 | for (size_t i = 0; i < phi.NumArgs(); ++i) { | ||
| 38 | if (std::ranges::find(dead_blocks, phi.PhiBlock(i)) == dead_blocks.end()) { | ||
| 39 | continue; | ||
| 40 | } | ||
| 41 | // Phi operand at this index is an unreachable block | ||
| 42 | phi.ErasePhiOperand(i); | ||
| 43 | --i; | ||
| 44 | } | ||
| 45 | } | ||
| 46 | } | ||
| 47 | } | ||
| 48 | |||
| 49 | void DeadBranchElimination(IR::Program& program) { | ||
| 50 | boost::container::small_vector<const IR::Block*, 3> dead_blocks; | ||
| 51 | const auto begin_it{program.syntax_list.begin()}; | ||
| 52 | for (auto node_it = begin_it; node_it != program.syntax_list.end(); ++node_it) { | ||
| 53 | if (node_it->type != IR::AbstractSyntaxNode::Type::If) { | ||
| 54 | continue; | ||
| 55 | } | ||
| 56 | IR::Inst* const cond_ref{node_it->data.if_node.cond.Inst()}; | ||
| 57 | const IR::U1 cond{cond_ref->Arg(0)}; | ||
| 58 | if (!cond.IsImmediate()) { | ||
| 59 | continue; | ||
| 60 | } | ||
| 61 | if (cond.U1()) { | ||
| 62 | continue; | ||
| 63 | } | ||
| 64 | // False immediate condition. Remove condition ref, erase the entire branch. | ||
| 65 | cond_ref->Invalidate(); | ||
| 66 | // Account for nested if-statements within the if(false) branch | ||
| 67 | u32 nested_ifs{1u}; | ||
| 68 | while (node_it->type != IR::AbstractSyntaxNode::Type::EndIf || nested_ifs > 0) { | ||
| 69 | node_it = program.syntax_list.erase(node_it); | ||
| 70 | switch (node_it->type) { | ||
| 71 | case IR::AbstractSyntaxNode::Type::If: | ||
| 72 | ++nested_ifs; | ||
| 73 | break; | ||
| 74 | case IR::AbstractSyntaxNode::Type::EndIf: | ||
| 75 | --nested_ifs; | ||
| 76 | break; | ||
| 77 | case IR::AbstractSyntaxNode::Type::Block: { | ||
| 78 | IR::Block* const block{node_it->data.block}; | ||
| 79 | DeadInstElimination<false>(block); | ||
| 80 | dead_blocks.push_back(block); | ||
| 81 | break; | ||
| 82 | } | ||
| 83 | default: | ||
| 84 | break; | ||
| 85 | } | 20 | } |
| 86 | } | 21 | } |
| 87 | // Erase EndIf node of the if(false) branch | ||
| 88 | node_it = program.syntax_list.erase(node_it); | ||
| 89 | // Account for loop increment | ||
| 90 | --node_it; | ||
| 91 | } | ||
| 92 | if (!dead_blocks.empty()) { | ||
| 93 | DeletedPhiArgElimination(program, std::span(dead_blocks.data(), dead_blocks.size())); | ||
| 94 | } | ||
| 95 | } | ||
| 96 | } // namespace | ||
| 97 | |||
| 98 | void DeadCodeEliminationPass(IR::Program& program) { | ||
| 99 | DeadBranchElimination(program); | ||
| 100 | for (IR::Block* const block : program.post_order_blocks) { | ||
| 101 | DeadInstElimination<true>(block); | ||
| 102 | } | 22 | } |
| 103 | } | 23 | } |
| 104 | 24 | ||
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 5208bea75..f9794dfe4 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp | |||
| @@ -123,9 +123,6 @@ void Maxwell3D::InitializeRegisterDefaults() { | |||
| 123 | draw_command[MAXWELL3D_REG_INDEX(vertex_buffer.count)] = true; | 123 | draw_command[MAXWELL3D_REG_INDEX(vertex_buffer.count)] = true; |
| 124 | draw_command[MAXWELL3D_REG_INDEX(index_buffer.first)] = true; | 124 | draw_command[MAXWELL3D_REG_INDEX(index_buffer.first)] = true; |
| 125 | draw_command[MAXWELL3D_REG_INDEX(index_buffer.count)] = true; | 125 | draw_command[MAXWELL3D_REG_INDEX(index_buffer.count)] = true; |
| 126 | draw_command[MAXWELL3D_REG_INDEX(index_buffer32_first)] = true; | ||
| 127 | draw_command[MAXWELL3D_REG_INDEX(index_buffer16_first)] = true; | ||
| 128 | draw_command[MAXWELL3D_REG_INDEX(index_buffer8_first)] = true; | ||
| 129 | draw_command[MAXWELL3D_REG_INDEX(draw_inline_index)] = true; | 126 | draw_command[MAXWELL3D_REG_INDEX(draw_inline_index)] = true; |
| 130 | draw_command[MAXWELL3D_REG_INDEX(inline_index_2x16.even)] = true; | 127 | draw_command[MAXWELL3D_REG_INDEX(inline_index_2x16.even)] = true; |
| 131 | draw_command[MAXWELL3D_REG_INDEX(inline_index_4x8.index0)] = true; | 128 | draw_command[MAXWELL3D_REG_INDEX(inline_index_4x8.index0)] = true; |
| @@ -216,6 +213,21 @@ void Maxwell3D::ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argume | |||
| 216 | return ProcessCBBind(3); | 213 | return ProcessCBBind(3); |
| 217 | case MAXWELL3D_REG_INDEX(bind_groups[4].raw_config): | 214 | case MAXWELL3D_REG_INDEX(bind_groups[4].raw_config): |
| 218 | return ProcessCBBind(4); | 215 | return ProcessCBBind(4); |
| 216 | case MAXWELL3D_REG_INDEX(index_buffer32_first): | ||
| 217 | regs.index_buffer.count = regs.index_buffer32_first.count; | ||
| 218 | regs.index_buffer.first = regs.index_buffer32_first.first; | ||
| 219 | dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | ||
| 220 | return ProcessDraw(); | ||
| 221 | case MAXWELL3D_REG_INDEX(index_buffer16_first): | ||
| 222 | regs.index_buffer.count = regs.index_buffer16_first.count; | ||
| 223 | regs.index_buffer.first = regs.index_buffer16_first.first; | ||
| 224 | dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | ||
| 225 | return ProcessDraw(); | ||
| 226 | case MAXWELL3D_REG_INDEX(index_buffer8_first): | ||
| 227 | regs.index_buffer.count = regs.index_buffer8_first.count; | ||
| 228 | regs.index_buffer.first = regs.index_buffer8_first.first; | ||
| 229 | dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | ||
| 230 | return ProcessDraw(); | ||
| 219 | case MAXWELL3D_REG_INDEX(topology_override): | 231 | case MAXWELL3D_REG_INDEX(topology_override): |
| 220 | use_topology_override = true; | 232 | use_topology_override = true; |
| 221 | return; | 233 | return; |
| @@ -583,6 +595,31 @@ void Maxwell3D::ProcessClearBuffers() { | |||
| 583 | rasterizer->Clear(); | 595 | rasterizer->Clear(); |
| 584 | } | 596 | } |
| 585 | 597 | ||
| 598 | void Maxwell3D::ProcessDraw(u32 instance_count) { | ||
| 599 | LOG_TRACE(HW_GPU, "called, topology={}, count={}", regs.draw.topology.Value(), | ||
| 600 | regs.vertex_buffer.count); | ||
| 601 | |||
| 602 | ASSERT_MSG(!(regs.index_buffer.count && regs.vertex_buffer.count), "Both indexed and direct?"); | ||
| 603 | |||
| 604 | // Both instance configuration registers can not be set at the same time. | ||
| 605 | ASSERT_MSG(regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::First || | ||
| 606 | regs.draw.instance_id != Maxwell3D::Regs::Draw::InstanceId::Unchanged, | ||
| 607 | "Illegal combination of instancing parameters"); | ||
| 608 | |||
| 609 | ProcessTopologyOverride(); | ||
| 610 | |||
| 611 | const bool is_indexed = regs.index_buffer.count && !regs.vertex_buffer.count; | ||
| 612 | if (ShouldExecute()) { | ||
| 613 | rasterizer->Draw(is_indexed, instance_count); | ||
| 614 | } | ||
| 615 | |||
| 616 | if (is_indexed) { | ||
| 617 | regs.index_buffer.count = 0; | ||
| 618 | } else { | ||
| 619 | regs.vertex_buffer.count = 0; | ||
| 620 | } | ||
| 621 | } | ||
| 622 | |||
| 586 | void Maxwell3D::ProcessDeferredDraw() { | 623 | void Maxwell3D::ProcessDeferredDraw() { |
| 587 | if (deferred_draw_method.empty()) { | 624 | if (deferred_draw_method.empty()) { |
| 588 | return; | 625 | return; |
| @@ -596,23 +633,28 @@ void Maxwell3D::ProcessDeferredDraw() { | |||
| 596 | DrawMode draw_mode{DrawMode::Undefined}; | 633 | DrawMode draw_mode{DrawMode::Undefined}; |
| 597 | u32 instance_count = 1; | 634 | u32 instance_count = 1; |
| 598 | 635 | ||
| 599 | auto first_method = deferred_draw_method[0]; | 636 | u32 index = 0; |
| 600 | if (MAXWELL3D_REG_INDEX(draw.begin) == first_method) { | 637 | u32 method = 0; |
| 601 | // The minimum number of methods for drawing must be greater than or equal to | 638 | u32 method_count = static_cast<u32>(deferred_draw_method.size()); |
| 602 | // 3[draw.begin->vertex(index)count->draw.end] to avoid errors in index mode drawing | 639 | for (; index < method_count && |
| 603 | if (deferred_draw_method.size() < 3) { | 640 | (method = deferred_draw_method[index]) != MAXWELL3D_REG_INDEX(draw.begin); |
| 604 | return; | 641 | ++index) |
| 605 | } | 642 | ; |
| 606 | draw_mode = (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent) || | 643 | |
| 607 | (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Unchanged) | 644 | if (MAXWELL3D_REG_INDEX(draw.begin) != method) { |
| 608 | ? DrawMode::Instance | 645 | return; |
| 609 | : DrawMode::General; | ||
| 610 | } else if (MAXWELL3D_REG_INDEX(index_buffer32_first) == first_method || | ||
| 611 | MAXWELL3D_REG_INDEX(index_buffer16_first) == first_method || | ||
| 612 | MAXWELL3D_REG_INDEX(index_buffer8_first) == first_method) { | ||
| 613 | draw_mode = DrawMode::General; | ||
| 614 | } | 646 | } |
| 615 | 647 | ||
| 648 | // The minimum number of methods for drawing must be greater than or equal to | ||
| 649 | // 3[draw.begin->vertex(index)count(first)->draw.end] to avoid errors in index mode drawing | ||
| 650 | if ((method_count - index) < 3) { | ||
| 651 | return; | ||
| 652 | } | ||
| 653 | draw_mode = (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent) || | ||
| 654 | (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Unchanged) | ||
| 655 | ? DrawMode::Instance | ||
| 656 | : DrawMode::General; | ||
| 657 | |||
| 616 | // Drawing will only begin with draw.begin or index_buffer method, other methods directly | 658 | // Drawing will only begin with draw.begin or index_buffer method, other methods directly |
| 617 | // clear | 659 | // clear |
| 618 | if (draw_mode == DrawMode::Undefined) { | 660 | if (draw_mode == DrawMode::Undefined) { |
| @@ -622,53 +664,18 @@ void Maxwell3D::ProcessDeferredDraw() { | |||
| 622 | 664 | ||
| 623 | if (draw_mode == DrawMode::Instance) { | 665 | if (draw_mode == DrawMode::Instance) { |
| 624 | ASSERT_MSG(deferred_draw_method.size() % 4 == 0, "Instance mode method size error"); | 666 | ASSERT_MSG(deferred_draw_method.size() % 4 == 0, "Instance mode method size error"); |
| 625 | instance_count = static_cast<u32>(deferred_draw_method.size()) / 4; | 667 | instance_count = static_cast<u32>(method_count - index) / 4; |
| 626 | } else { | 668 | } else { |
| 627 | if (MAXWELL3D_REG_INDEX(index_buffer32_first) == first_method) { | 669 | method = deferred_draw_method[index + 1]; |
| 628 | regs.index_buffer.count = regs.index_buffer32_first.count; | 670 | if (MAXWELL3D_REG_INDEX(draw_inline_index) == method || |
| 629 | regs.index_buffer.first = regs.index_buffer32_first.first; | 671 | MAXWELL3D_REG_INDEX(inline_index_2x16.even) == method || |
| 630 | dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | 672 | MAXWELL3D_REG_INDEX(inline_index_4x8.index0) == method) { |
| 631 | } else if (MAXWELL3D_REG_INDEX(index_buffer32_first) == first_method) { | 673 | regs.index_buffer.count = static_cast<u32>(inline_index_draw_indexes.size() / 4); |
| 632 | regs.index_buffer.count = regs.index_buffer16_first.count; | 674 | regs.index_buffer.format = Regs::IndexFormat::UnsignedInt; |
| 633 | regs.index_buffer.first = regs.index_buffer16_first.first; | ||
| 634 | dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | ||
| 635 | } else if (MAXWELL3D_REG_INDEX(index_buffer32_first) == first_method) { | ||
| 636 | regs.index_buffer.count = regs.index_buffer8_first.count; | ||
| 637 | regs.index_buffer.first = regs.index_buffer8_first.first; | ||
| 638 | dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | ||
| 639 | } else { | ||
| 640 | auto second_method = deferred_draw_method[1]; | ||
| 641 | if (MAXWELL3D_REG_INDEX(draw_inline_index) == second_method || | ||
| 642 | MAXWELL3D_REG_INDEX(inline_index_2x16.even) == second_method || | ||
| 643 | MAXWELL3D_REG_INDEX(inline_index_4x8.index0) == second_method) { | ||
| 644 | regs.index_buffer.count = static_cast<u32>(inline_index_draw_indexes.size() / 4); | ||
| 645 | regs.index_buffer.format = Regs::IndexFormat::UnsignedInt; | ||
| 646 | } | ||
| 647 | } | 675 | } |
| 648 | } | 676 | } |
| 649 | 677 | ||
| 650 | LOG_TRACE(HW_GPU, "called, topology={}, count={}", regs.draw.topology.Value(), | 678 | ProcessDraw(instance_count); |
| 651 | regs.vertex_buffer.count); | ||
| 652 | |||
| 653 | ASSERT_MSG(!(regs.index_buffer.count && regs.vertex_buffer.count), "Both indexed and direct?"); | ||
| 654 | |||
| 655 | // Both instance configuration registers can not be set at the same time. | ||
| 656 | ASSERT_MSG(regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::First || | ||
| 657 | regs.draw.instance_id != Maxwell3D::Regs::Draw::InstanceId::Unchanged, | ||
| 658 | "Illegal combination of instancing parameters"); | ||
| 659 | |||
| 660 | ProcessTopologyOverride(); | ||
| 661 | |||
| 662 | const bool is_indexed = regs.index_buffer.count && !regs.vertex_buffer.count; | ||
| 663 | if (ShouldExecute()) { | ||
| 664 | rasterizer->Draw(is_indexed, instance_count); | ||
| 665 | } | ||
| 666 | |||
| 667 | if (is_indexed) { | ||
| 668 | regs.index_buffer.count = 0; | ||
| 669 | } else { | ||
| 670 | regs.vertex_buffer.count = 0; | ||
| 671 | } | ||
| 672 | 679 | ||
| 673 | deferred_draw_method.clear(); | 680 | deferred_draw_method.clear(); |
| 674 | inline_index_draw_indexes.clear(); | 681 | inline_index_draw_indexes.clear(); |
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index bd23ebc12..a948fcb14 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -3143,6 +3143,8 @@ private: | |||
| 3143 | /// Handles use of topology overrides (e.g., to avoid using a topology assigned from a macro) | 3143 | /// Handles use of topology overrides (e.g., to avoid using a topology assigned from a macro) |
| 3144 | void ProcessTopologyOverride(); | 3144 | void ProcessTopologyOverride(); |
| 3145 | 3145 | ||
| 3146 | void ProcessDraw(u32 instance_count = 1); | ||
| 3147 | |||
| 3146 | void ProcessDeferredDraw(); | 3148 | void ProcessDeferredDraw(); |
| 3147 | 3149 | ||
| 3148 | /// Returns a query's value or an empty object if the value will be deferred through a cache. | 3150 | /// Returns a query's value or an empty object if the value will be deferred through a cache. |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 9f05a7a18..6ab68892c 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -305,14 +305,19 @@ void RasterizerVulkan::Clear() { | |||
| 305 | } | 305 | } |
| 306 | } | 306 | } |
| 307 | 307 | ||
| 308 | scheduler.Record([color_attachment, clear_value, clear_rect](vk::CommandBuffer cmdbuf) { | 308 | if (regs.clear_surface.R && regs.clear_surface.G && regs.clear_surface.B && |
| 309 | const VkClearAttachment attachment{ | 309 | regs.clear_surface.A) { |
| 310 | .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, | 310 | scheduler.Record([color_attachment, clear_value, clear_rect](vk::CommandBuffer cmdbuf) { |
| 311 | .colorAttachment = color_attachment, | 311 | const VkClearAttachment attachment{ |
| 312 | .clearValue = clear_value, | 312 | .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, |
| 313 | }; | 313 | .colorAttachment = color_attachment, |
| 314 | cmdbuf.ClearAttachments(attachment, clear_rect); | 314 | .clearValue = clear_value, |
| 315 | }); | 315 | }; |
| 316 | cmdbuf.ClearAttachments(attachment, clear_rect); | ||
| 317 | }); | ||
| 318 | } else { | ||
| 319 | UNIMPLEMENTED_MSG("Unimplemented Clear only the specified channel"); | ||
| 320 | } | ||
| 316 | } | 321 | } |
| 317 | 322 | ||
| 318 | if (!use_depth && !use_stencil) { | 323 | if (!use_depth && !use_stencil) { |