summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/CMakeLists.txt16
-rw-r--r--src/common/fiber.cpp8
-rw-r--r--src/common/fiber.h2
-rw-r--r--src/common/file_util.cpp31
-rw-r--r--src/common/logging/backend.cpp2
-rw-r--r--src/common/string_util.cpp5
-rw-r--r--src/common/timer.cpp12
-rw-r--r--src/common/wall_clock.cpp2
-rw-r--r--src/common/x64/native_clock.h2
-rw-r--r--src/core/hle/service/ldr/ldr.cpp16
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp20
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl.h6
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp2
-rw-r--r--src/video_core/engines/shader_bytecode.h2
-rw-r--r--src/video_core/shader/async_shaders.cpp17
-rw-r--r--src/video_core/shader/decode/arithmetic.cpp3
16 files changed, 88 insertions, 58 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index e50ab2922..207c7a0a6 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -190,6 +190,22 @@ if(ARCHITECTURE_x86_64)
190 ) 190 )
191endif() 191endif()
192 192
193if (MSVC)
194 target_compile_definitions(common PRIVATE
195 # The standard library doesn't provide any replacement for codecvt yet
196 # so we can disable this deprecation warning for the time being.
197 _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING
198 )
199 target_compile_options(common PRIVATE
200 /W4
201 /WX
202 )
203else()
204 target_compile_options(common PRIVATE
205 -Werror
206 )
207endif()
208
193create_target_directory_groups(common) 209create_target_directory_groups(common)
194find_package(Boost 1.71 COMPONENTS context headers REQUIRED) 210find_package(Boost 1.71 COMPONENTS context headers REQUIRED)
195 211
diff --git a/src/common/fiber.cpp b/src/common/fiber.cpp
index e186ed880..b209f52fc 100644
--- a/src/common/fiber.cpp
+++ b/src/common/fiber.cpp
@@ -79,9 +79,9 @@ void Fiber::Exit() {
79 released = true; 79 released = true;
80} 80}
81 81
82void Fiber::SetRewindPoint(std::function<void(void*)>&& rewind_func, void* start_parameter) { 82void Fiber::SetRewindPoint(std::function<void(void*)>&& rewind_func, void* rewind_param) {
83 rewind_point = std::move(rewind_func); 83 rewind_point = std::move(rewind_func);
84 rewind_parameter = start_parameter; 84 rewind_parameter = rewind_param;
85} 85}
86 86
87void Fiber::Rewind() { 87void Fiber::Rewind() {
@@ -161,9 +161,9 @@ Fiber::Fiber(std::function<void(void*)>&& entry_point_func, void* start_paramete
161 boost::context::detail::make_fcontext(stack_base, impl->stack.size(), FiberStartFunc); 161 boost::context::detail::make_fcontext(stack_base, impl->stack.size(), FiberStartFunc);
162} 162}
163 163
164void Fiber::SetRewindPoint(std::function<void(void*)>&& rewind_func, void* start_parameter) { 164void Fiber::SetRewindPoint(std::function<void(void*)>&& rewind_func, void* rewind_param) {
165 rewind_point = std::move(rewind_func); 165 rewind_point = std::move(rewind_func);
166 rewind_parameter = start_parameter; 166 rewind_parameter = rewind_param;
167} 167}
168 168
169Fiber::Fiber() : impl{std::make_unique<FiberImpl>()} {} 169Fiber::Fiber() : impl{std::make_unique<FiberImpl>()} {}
diff --git a/src/common/fiber.h b/src/common/fiber.h
index cefd61df9..699286ee2 100644
--- a/src/common/fiber.h
+++ b/src/common/fiber.h
@@ -49,7 +49,7 @@ public:
49 static void YieldTo(std::shared_ptr<Fiber> from, std::shared_ptr<Fiber> to); 49 static void YieldTo(std::shared_ptr<Fiber> from, std::shared_ptr<Fiber> to);
50 [[nodiscard]] static std::shared_ptr<Fiber> ThreadToFiber(); 50 [[nodiscard]] static std::shared_ptr<Fiber> ThreadToFiber();
51 51
52 void SetRewindPoint(std::function<void(void*)>&& rewind_func, void* start_parameter); 52 void SetRewindPoint(std::function<void(void*)>&& rewind_func, void* rewind_param);
53 53
54 void Rewind(); 54 void Rewind();
55 55
diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp
index 16c3713e0..18fbfa25b 100644
--- a/src/common/file_util.cpp
+++ b/src/common/file_util.cpp
@@ -472,13 +472,14 @@ u64 ScanDirectoryTree(const std::string& directory, FSTEntry& parent_entry,
472} 472}
473 473
474bool DeleteDirRecursively(const std::string& directory, unsigned int recursion) { 474bool DeleteDirRecursively(const std::string& directory, unsigned int recursion) {
475 const auto callback = [recursion](u64* num_entries_out, const std::string& directory, 475 const auto callback = [recursion](u64*, const std::string& directory,
476 const std::string& virtual_name) -> bool { 476 const std::string& virtual_name) {
477 std::string new_path = directory + DIR_SEP_CHR + virtual_name; 477 const std::string new_path = directory + DIR_SEP_CHR + virtual_name;
478 478
479 if (IsDirectory(new_path)) { 479 if (IsDirectory(new_path)) {
480 if (recursion == 0) 480 if (recursion == 0) {
481 return false; 481 return false;
482 }
482 return DeleteDirRecursively(new_path, recursion - 1); 483 return DeleteDirRecursively(new_path, recursion - 1);
483 } 484 }
484 return Delete(new_path); 485 return Delete(new_path);
@@ -492,7 +493,8 @@ bool DeleteDirRecursively(const std::string& directory, unsigned int recursion)
492 return true; 493 return true;
493} 494}
494 495
495void CopyDir(const std::string& source_path, const std::string& dest_path) { 496void CopyDir([[maybe_unused]] const std::string& source_path,
497 [[maybe_unused]] const std::string& dest_path) {
496#ifndef _WIN32 498#ifndef _WIN32
497 if (source_path == dest_path) { 499 if (source_path == dest_path) {
498 return; 500 return;
@@ -553,7 +555,7 @@ std::optional<std::string> GetCurrentDir() {
553 std::string strDir = dir; 555 std::string strDir = dir;
554#endif 556#endif
555 free(dir); 557 free(dir);
556 return std::move(strDir); 558 return strDir;
557} 559}
558 560
559bool SetCurrentDir(const std::string& directory) { 561bool SetCurrentDir(const std::string& directory) {
@@ -772,21 +774,23 @@ std::size_t ReadFileToString(bool text_file, const std::string& filename, std::s
772 774
773void SplitFilename83(const std::string& filename, std::array<char, 9>& short_name, 775void SplitFilename83(const std::string& filename, std::array<char, 9>& short_name,
774 std::array<char, 4>& extension) { 776 std::array<char, 4>& extension) {
775 const std::string forbidden_characters = ".\"/\\[]:;=, "; 777 static constexpr std::string_view forbidden_characters = ".\"/\\[]:;=, ";
776 778
777 // On a FAT32 partition, 8.3 names are stored as a 11 bytes array, filled with spaces. 779 // On a FAT32 partition, 8.3 names are stored as a 11 bytes array, filled with spaces.
778 short_name = {{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '\0'}}; 780 short_name = {{' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '\0'}};
779 extension = {{' ', ' ', ' ', '\0'}}; 781 extension = {{' ', ' ', ' ', '\0'}};
780 782
781 std::string::size_type point = filename.rfind('.'); 783 auto point = filename.rfind('.');
782 if (point == filename.size() - 1) 784 if (point == filename.size() - 1) {
783 point = filename.rfind('.', point); 785 point = filename.rfind('.', point);
786 }
784 787
785 // Get short name. 788 // Get short name.
786 int j = 0; 789 int j = 0;
787 for (char letter : filename.substr(0, point)) { 790 for (char letter : filename.substr(0, point)) {
788 if (forbidden_characters.find(letter, 0) != std::string::npos) 791 if (forbidden_characters.find(letter, 0) != std::string::npos) {
789 continue; 792 continue;
793 }
790 if (j == 8) { 794 if (j == 8) {
791 // TODO(Link Mauve): also do that for filenames containing a space. 795 // TODO(Link Mauve): also do that for filenames containing a space.
792 // TODO(Link Mauve): handle multiple files having the same short name. 796 // TODO(Link Mauve): handle multiple files having the same short name.
@@ -794,14 +798,15 @@ void SplitFilename83(const std::string& filename, std::array<char, 9>& short_nam
794 short_name[7] = '1'; 798 short_name[7] = '1';
795 break; 799 break;
796 } 800 }
797 short_name[j++] = toupper(letter); 801 short_name[j++] = static_cast<char>(std::toupper(letter));
798 } 802 }
799 803
800 // Get extension. 804 // Get extension.
801 if (point != std::string::npos) { 805 if (point != std::string::npos) {
802 j = 0; 806 j = 0;
803 for (char letter : filename.substr(point + 1, 3)) 807 for (char letter : filename.substr(point + 1, 3)) {
804 extension[j++] = toupper(letter); 808 extension[j++] = static_cast<char>(std::toupper(letter));
809 }
805 } 810 }
806} 811}
807 812
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp
index 62cfde397..90dfa22ca 100644
--- a/src/common/logging/backend.cpp
+++ b/src/common/logging/backend.cpp
@@ -274,7 +274,6 @@ const char* GetLogClassName(Class log_class) {
274 case Class::Count: 274 case Class::Count:
275 break; 275 break;
276 } 276 }
277 UNREACHABLE();
278 return "Invalid"; 277 return "Invalid";
279} 278}
280 279
@@ -293,7 +292,6 @@ const char* GetLevelName(Level log_level) {
293 break; 292 break;
294 } 293 }
295#undef LVL 294#undef LVL
296 UNREACHABLE();
297 return "Invalid"; 295 return "Invalid";
298} 296}
299 297
diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp
index 84883a1d3..4cba2aaa4 100644
--- a/src/common/string_util.cpp
+++ b/src/common/string_util.cpp
@@ -8,6 +8,7 @@
8#include <cstdlib> 8#include <cstdlib>
9#include <locale> 9#include <locale>
10#include <sstream> 10#include <sstream>
11
11#include "common/common_paths.h" 12#include "common/common_paths.h"
12#include "common/logging/log.h" 13#include "common/logging/log.h"
13#include "common/string_util.h" 14#include "common/string_util.h"
@@ -21,14 +22,14 @@ namespace Common {
21/// Make a string lowercase 22/// Make a string lowercase
22std::string ToLower(std::string str) { 23std::string ToLower(std::string str) {
23 std::transform(str.begin(), str.end(), str.begin(), 24 std::transform(str.begin(), str.end(), str.begin(),
24 [](unsigned char c) { return std::tolower(c); }); 25 [](unsigned char c) { return static_cast<char>(std::tolower(c)); });
25 return str; 26 return str;
26} 27}
27 28
28/// Make a string uppercase 29/// Make a string uppercase
29std::string ToUpper(std::string str) { 30std::string ToUpper(std::string str) {
30 std::transform(str.begin(), str.end(), str.begin(), 31 std::transform(str.begin(), str.end(), str.begin(),
31 [](unsigned char c) { return std::toupper(c); }); 32 [](unsigned char c) { return static_cast<char>(std::toupper(c)); });
32 return str; 33 return str;
33} 34}
34 35
diff --git a/src/common/timer.cpp b/src/common/timer.cpp
index 2dc15e434..d17dc2a50 100644
--- a/src/common/timer.cpp
+++ b/src/common/timer.cpp
@@ -142,20 +142,18 @@ std::string Timer::GetTimeFormatted() {
142// ---------------- 142// ----------------
143double Timer::GetDoubleTime() { 143double Timer::GetDoubleTime() {
144 // Get continuous timestamp 144 // Get continuous timestamp
145 u64 TmpSeconds = static_cast<u64>(Common::Timer::GetTimeSinceJan1970().count()); 145 auto tmp_seconds = static_cast<u64>(GetTimeSinceJan1970().count());
146 double ms = static_cast<u64>(GetTimeMs().count()) % 1000; 146 const auto ms = static_cast<double>(static_cast<u64>(GetTimeMs().count()) % 1000);
147 147
148 // Remove a few years. We only really want enough seconds to make 148 // Remove a few years. We only really want enough seconds to make
149 // sure that we are detecting actual actions, perhaps 60 seconds is 149 // sure that we are detecting actual actions, perhaps 60 seconds is
150 // enough really, but I leave a year of seconds anyway, in case the 150 // enough really, but I leave a year of seconds anyway, in case the
151 // user's clock is incorrect or something like that. 151 // user's clock is incorrect or something like that.
152 TmpSeconds = TmpSeconds - (38 * 365 * 24 * 60 * 60); 152 tmp_seconds = tmp_seconds - (38 * 365 * 24 * 60 * 60);
153 153
154 // Make a smaller integer that fits in the double 154 // Make a smaller integer that fits in the double
155 u32 Seconds = static_cast<u32>(TmpSeconds); 155 const auto seconds = static_cast<u32>(tmp_seconds);
156 double TmpTime = Seconds + ms; 156 return seconds + ms;
157
158 return TmpTime;
159} 157}
160 158
161} // Namespace Common 159} // Namespace Common
diff --git a/src/common/wall_clock.cpp b/src/common/wall_clock.cpp
index 7a20e95b7..452a2837e 100644
--- a/src/common/wall_clock.cpp
+++ b/src/common/wall_clock.cpp
@@ -53,7 +53,7 @@ public:
53 return Common::Divide128On32(temporary, 1000000000).first; 53 return Common::Divide128On32(temporary, 1000000000).first;
54 } 54 }
55 55
56 void Pause(bool is_paused) override { 56 void Pause([[maybe_unused]] bool is_paused) override {
57 // Do nothing in this clock type. 57 // Do nothing in this clock type.
58 } 58 }
59 59
diff --git a/src/common/x64/native_clock.h b/src/common/x64/native_clock.h
index 7c503df26..97aab6ac9 100644
--- a/src/common/x64/native_clock.h
+++ b/src/common/x64/native_clock.h
@@ -34,7 +34,7 @@ private:
34 /// value used to reduce the native clocks accuracy as some apss rely on 34 /// value used to reduce the native clocks accuracy as some apss rely on
35 /// undefined behavior where the level of accuracy in the clock shouldn't 35 /// undefined behavior where the level of accuracy in the clock shouldn't
36 /// be higher. 36 /// be higher.
37 static constexpr u64 inaccuracy_mask = ~(0x400 - 1); 37 static constexpr u64 inaccuracy_mask = ~(UINT64_C(0x400) - 1);
38 38
39 SpinLock rtsc_serialize{}; 39 SpinLock rtsc_serialize{};
40 u64 last_measure{}; 40 u64 last_measure{};
diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp
index 9ad5bbf0d..eeaca44b6 100644
--- a/src/core/hle/service/ldr/ldr.cpp
+++ b/src/core/hle/service/ldr/ldr.cpp
@@ -166,7 +166,7 @@ public:
166 {0, &RelocatableObject::LoadNro, "LoadNro"}, 166 {0, &RelocatableObject::LoadNro, "LoadNro"},
167 {1, &RelocatableObject::UnloadNro, "UnloadNro"}, 167 {1, &RelocatableObject::UnloadNro, "UnloadNro"},
168 {2, &RelocatableObject::LoadNrr, "LoadNrr"}, 168 {2, &RelocatableObject::LoadNrr, "LoadNrr"},
169 {3, nullptr, "UnloadNrr"}, 169 {3, &RelocatableObject::UnloadNrr, "UnloadNrr"},
170 {4, &RelocatableObject::Initialize, "Initialize"}, 170 {4, &RelocatableObject::Initialize, "Initialize"},
171 {10, nullptr, "LoadNrrEx"}, 171 {10, nullptr, "LoadNrrEx"},
172 }; 172 };
@@ -272,6 +272,20 @@ public:
272 rb.Push(RESULT_SUCCESS); 272 rb.Push(RESULT_SUCCESS);
273 } 273 }
274 274
275 void UnloadNrr(Kernel::HLERequestContext& ctx) {
276 IPC::RequestParser rp{ctx};
277 const auto pid = rp.Pop<u64>();
278 const auto nrr_address = rp.Pop<VAddr>();
279
280 LOG_DEBUG(Service_LDR, "called with pid={}, nrr_address={:016X}", pid, nrr_address);
281
282 nrr.erase(nrr_address);
283
284 IPC::ResponseBuilder rb{ctx, 2};
285
286 rb.Push(RESULT_SUCCESS);
287 }
288
275 bool ValidateRegionForMap(Kernel::Memory::PageTable& page_table, VAddr start, 289 bool ValidateRegionForMap(Kernel::Memory::PageTable& page_table, VAddr start,
276 std::size_t size) const { 290 std::size_t size) const {
277 constexpr std::size_t padding_size{4 * Kernel::Memory::PageSize}; 291 constexpr std::size_t padding_size{4 * Kernel::Memory::PageSize};
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
index b27ee0502..75d9191ff 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
@@ -36,8 +36,8 @@ u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector<u8>& input, const std::v
36 return IocCtrlEventRegister(input, output); 36 return IocCtrlEventRegister(input, output);
37 case IoctlCommand::IocCtrlEventUnregisterCommand: 37 case IoctlCommand::IocCtrlEventUnregisterCommand:
38 return IocCtrlEventUnregister(input, output); 38 return IocCtrlEventUnregister(input, output);
39 case IoctlCommand::IocCtrlEventSignalCommand: 39 case IoctlCommand::IocCtrlClearEventWaitCommand:
40 return IocCtrlEventSignal(input, output); 40 return IocCtrlClearEventWait(input, output);
41 default: 41 default:
42 UNIMPLEMENTED_MSG("Unimplemented ioctl"); 42 UNIMPLEMENTED_MSG("Unimplemented ioctl");
43 return 0; 43 return 0;
@@ -154,23 +154,17 @@ u32 nvhost_ctrl::IocCtrlEventUnregister(const std::vector<u8>& input, std::vecto
154 return NvResult::Success; 154 return NvResult::Success;
155} 155}
156 156
157u32 nvhost_ctrl::IocCtrlEventSignal(const std::vector<u8>& input, std::vector<u8>& output) { 157u32 nvhost_ctrl::IocCtrlClearEventWait(const std::vector<u8>& input, std::vector<u8>& output) {
158 IocCtrlEventSignalParams params{}; 158 IocCtrlEventSignalParams params{};
159 std::memcpy(&params, input.data(), sizeof(params)); 159 std::memcpy(&params, input.data(), sizeof(params));
160 // TODO(Blinkhawk): This is normally called when an NvEvents timeout on WaitSynchronization 160 u32 event_id = params.event_id & 0x00FF;
161 // It is believed from RE to cancel the GPU Event. However, better research is required 161 LOG_WARNING(Service_NVDRV, "cleared event wait on, event_id: {:X}", event_id);
162 u32 event_id = params.user_event_id & 0x00FF;
163 LOG_WARNING(Service_NVDRV, "(STUBBED) called, user_event_id: {:X}", event_id);
164 if (event_id >= MaxNvEvents) { 162 if (event_id >= MaxNvEvents) {
165 return NvResult::BadParameter; 163 return NvResult::BadParameter;
166 } 164 }
167 if (events_interface.status[event_id] == EventState::Waiting) { 165 if (events_interface.status[event_id] == EventState::Waiting) {
168 auto& gpu = system.GPU(); 166 events_interface.LiberateEvent(event_id);
169 if (gpu.CancelSyncptInterrupt(events_interface.assigned_syncpt[event_id], 167 events_interface.events[event_id].writable->Signal();
170 events_interface.assigned_value[event_id])) {
171 events_interface.LiberateEvent(event_id);
172 events_interface.events[event_id].writable->Signal();
173 }
174 } 168 }
175 return NvResult::Success; 169 return NvResult::Success;
176} 170}
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
index 9898623de..f7b04d9f1 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
@@ -31,7 +31,7 @@ private:
31 IocSyncptWaitexCommand = 0xC0100019, 31 IocSyncptWaitexCommand = 0xC0100019,
32 IocSyncptReadMaxCommand = 0xC008001A, 32 IocSyncptReadMaxCommand = 0xC008001A,
33 IocGetConfigCommand = 0xC183001B, 33 IocGetConfigCommand = 0xC183001B,
34 IocCtrlEventSignalCommand = 0xC004001C, 34 IocCtrlClearEventWaitCommand = 0xC004001C,
35 IocCtrlEventWaitCommand = 0xC010001D, 35 IocCtrlEventWaitCommand = 0xC010001D,
36 IocCtrlEventWaitAsyncCommand = 0xC010001E, 36 IocCtrlEventWaitAsyncCommand = 0xC010001E,
37 IocCtrlEventRegisterCommand = 0xC004001F, 37 IocCtrlEventRegisterCommand = 0xC004001F,
@@ -94,7 +94,7 @@ private:
94 static_assert(sizeof(IocGetConfigParams) == 387, "IocGetConfigParams is incorrect size"); 94 static_assert(sizeof(IocGetConfigParams) == 387, "IocGetConfigParams is incorrect size");
95 95
96 struct IocCtrlEventSignalParams { 96 struct IocCtrlEventSignalParams {
97 u32_le user_event_id; 97 u32_le event_id;
98 }; 98 };
99 static_assert(sizeof(IocCtrlEventSignalParams) == 4, 99 static_assert(sizeof(IocCtrlEventSignalParams) == 4,
100 "IocCtrlEventSignalParams is incorrect size"); 100 "IocCtrlEventSignalParams is incorrect size");
@@ -142,7 +142,7 @@ private:
142 142
143 u32 IocCtrlEventUnregister(const std::vector<u8>& input, std::vector<u8>& output); 143 u32 IocCtrlEventUnregister(const std::vector<u8>& input, std::vector<u8>& output);
144 144
145 u32 IocCtrlEventSignal(const std::vector<u8>& input, std::vector<u8>& output); 145 u32 IocCtrlClearEventWait(const std::vector<u8>& input, std::vector<u8>& output);
146 146
147 EventInterface& events_interface; 147 EventInterface& events_interface;
148}; 148};
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
index 85792495f..30f03f845 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec_common.cpp
@@ -38,7 +38,7 @@ std::size_t WriteVectors(std::vector<u8>& dst, const std::vector<T>& src, std::s
38 38
39namespace NvErrCodes { 39namespace NvErrCodes {
40constexpr u32 Success{}; 40constexpr u32 Success{};
41constexpr u32 OutOfMemory{static_cast<u32>(-12)}; 41[[maybe_unused]] constexpr u32 OutOfMemory{static_cast<u32>(-12)};
42constexpr u32 InvalidInput{static_cast<u32>(-22)}; 42constexpr u32 InvalidInput{static_cast<u32>(-22)};
43} // namespace NvErrCodes 43} // namespace NvErrCodes
44 44
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index d374b73cf..a3c05d1b0 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -1893,6 +1893,7 @@ public:
1893 ICMP_IMM, 1893 ICMP_IMM,
1894 FCMP_RR, 1894 FCMP_RR,
1895 FCMP_RC, 1895 FCMP_RC,
1896 FCMP_IMMR,
1896 MUFU, // Multi-Function Operator 1897 MUFU, // Multi-Function Operator
1897 RRO_C, // Range Reduction Operator 1898 RRO_C, // Range Reduction Operator
1898 RRO_R, 1899 RRO_R,
@@ -2205,6 +2206,7 @@ private:
2205 INST("0111110-0-------", Id::HSET2_IMM, Type::HalfSet, "HSET2_IMM"), 2206 INST("0111110-0-------", Id::HSET2_IMM, Type::HalfSet, "HSET2_IMM"),
2206 INST("010110111010----", Id::FCMP_RR, Type::Arithmetic, "FCMP_RR"), 2207 INST("010110111010----", Id::FCMP_RR, Type::Arithmetic, "FCMP_RR"),
2207 INST("010010111010----", Id::FCMP_RC, Type::Arithmetic, "FCMP_RC"), 2208 INST("010010111010----", Id::FCMP_RC, Type::Arithmetic, "FCMP_RC"),
2209 INST("0011011-1010----", Id::FCMP_IMMR, Type::Arithmetic, "FCMP_IMMR"),
2208 INST("0101000010000---", Id::MUFU, Type::Arithmetic, "MUFU"), 2210 INST("0101000010000---", Id::MUFU, Type::Arithmetic, "MUFU"),
2209 INST("0100110010010---", Id::RRO_C, Type::Arithmetic, "RRO_C"), 2211 INST("0100110010010---", Id::RRO_C, Type::Arithmetic, "RRO_C"),
2210 INST("0101110010010---", Id::RRO_R, Type::Arithmetic, "RRO_R"), 2212 INST("0101110010010---", Id::RRO_R, Type::Arithmetic, "RRO_R"),
diff --git a/src/video_core/shader/async_shaders.cpp b/src/video_core/shader/async_shaders.cpp
index aabd62c5c..39cc3b869 100644
--- a/src/video_core/shader/async_shaders.cpp
+++ b/src/video_core/shader/async_shaders.cpp
@@ -20,14 +20,15 @@ AsyncShaders::~AsyncShaders() {
20} 20}
21 21
22void AsyncShaders::AllocateWorkers() { 22void AsyncShaders::AllocateWorkers() {
23 // Max worker threads we should allow 23 // Use at least one thread
24 constexpr u32 MAX_THREADS = 4; 24 u32 num_workers = 1;
25 // Deduce how many threads we can use 25
26 const u32 threads_used = std::thread::hardware_concurrency() / 4; 26 // Deduce how many more threads we can use
27 // Always allow at least 1 thread regardless of our settings 27 const u32 thread_count = std::thread::hardware_concurrency();
28 const auto max_worker_count = std::max(1U, threads_used); 28 if (thread_count >= 8) {
29 // Don't use more than MAX_THREADS 29 // Increase async workers by 1 for every 2 threads >= 8
30 const auto num_workers = std::min(max_worker_count, MAX_THREADS); 30 num_workers += 1 + (thread_count - 8) / 2;
31 }
31 32
32 // If we already have workers queued, ignore 33 // If we already have workers queued, ignore
33 if (num_workers == worker_threads.size()) { 34 if (num_workers == worker_threads.size()) {
diff --git a/src/video_core/shader/decode/arithmetic.cpp b/src/video_core/shader/decode/arithmetic.cpp
index 4db329fa5..afef5948d 100644
--- a/src/video_core/shader/decode/arithmetic.cpp
+++ b/src/video_core/shader/decode/arithmetic.cpp
@@ -137,7 +137,8 @@ u32 ShaderIR::DecodeArithmetic(NodeBlock& bb, u32 pc) {
137 break; 137 break;
138 } 138 }
139 case OpCode::Id::FCMP_RR: 139 case OpCode::Id::FCMP_RR:
140 case OpCode::Id::FCMP_RC: { 140 case OpCode::Id::FCMP_RC:
141 case OpCode::Id::FCMP_IMMR: {
141 UNIMPLEMENTED_IF(instr.fcmp.ftz == 0); 142 UNIMPLEMENTED_IF(instr.fcmp.ftz == 0);
142 Node op_c = GetRegister(instr.gpr39); 143 Node op_c = GetRegister(instr.gpr39);
143 Node comp = GetPredicateComparisonFloat(instr.fcmp.cond, std::move(op_c), Immediate(0.0f)); 144 Node comp = GetPredicateComparisonFloat(instr.fcmp.cond, std::move(op_c), Immediate(0.0f));