summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt7
-rw-r--r--src/core/hle/ipc_helpers.h2
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp2
-rw-r--r--src/core/hle/kernel/object.h4
-rw-r--r--src/core/hle/kernel/readable_event.cpp3
-rw-r--r--src/core/hle/kernel/svc.cpp10
-rw-r--r--src/core/hle/service/am/am.cpp8
-rw-r--r--src/core/hle/service/am/applets/applets.cpp6
-rw-r--r--src/core/hle/service/aoc/aoc_u.cpp2
-rw-r--r--src/core/hle/service/audio/audout_u.cpp2
-rw-r--r--src/core/hle/service/audio/audren_u.cpp4
-rw-r--r--src/core/hle/service/btdrv/btdrv.cpp4
-rw-r--r--src/core/hle/service/btm/btm.cpp8
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp2
-rw-r--r--src/core/hle/service/nfp/nfp.cpp6
-rw-r--r--src/core/hle/service/nifm/nifm.cpp4
-rw-r--r--src/core/hle/service/nim/nim.cpp2
-rw-r--r--src/core/hle/service/nvdrv/interface.cpp2
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.cpp2
-rw-r--r--src/core/hle/service/vi/display/vi_display.cpp2
-rw-r--r--src/video_core/engines/engine_upload.cpp6
-rw-r--r--src/video_core/engines/engine_upload.h8
-rw-r--r--src/video_core/engines/maxwell_3d.cpp38
-rw-r--r--src/video_core/engines/maxwell_3d.h2
-rw-r--r--src/video_core/gpu_thread.cpp4
-rw-r--r--src/video_core/gpu_thread.h2
-rw-r--r--src/video_core/macro_interpreter.cpp6
-rw-r--r--src/video_core/memory_manager.cpp6
-rw-r--r--src/video_core/memory_manager.h31
-rw-r--r--src/video_core/rasterizer_cache.h7
-rw-r--r--src/video_core/renderer_opengl/gl_buffer_cache.h6
-rw-r--r--src/video_core/renderer_opengl/gl_global_cache.h7
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp8
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp26
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.h28
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.h7
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp11
-rw-r--r--src/video_core/renderer_opengl/gl_shader_gen.cpp14
-rw-r--r--src/video_core/renderer_opengl/maxwell_to_gl.h2
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.h7
-rw-r--r--src/video_core/renderer_vulkan/vk_shader_decompiler.cpp1
-rw-r--r--src/video_core/shader/decode/texture.cpp1
-rw-r--r--src/video_core/textures/astc.cpp8
-rw-r--r--src/yuzu/CMakeLists.txt2
-rw-r--r--src/yuzu/about_dialog.cpp8
-rw-r--r--src/yuzu/applets/error.cpp2
-rw-r--r--src/yuzu/applets/profile_select.cpp4
-rw-r--r--src/yuzu/bootmanager.cpp1
-rw-r--r--src/yuzu/configuration/configure_graphics.cpp8
-rw-r--r--src/yuzu/debugger/graphics/graphics_breakpoints.cpp2
-rw-r--r--src/yuzu/debugger/profiler.cpp4
-rw-r--r--src/yuzu/debugger/wait_tree.cpp39
-rw-r--r--src/yuzu/main.cpp25
-rw-r--r--src/yuzu/main.h1
-rw-r--r--src/yuzu/util/spinbox.cpp278
-rw-r--r--src/yuzu/util/spinbox.h86
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2.cpp6
-rw-r--r--src/yuzu_cmd/yuzu.cpp1
59 files changed, 234 insertions, 553 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index a1d87bbbc..04018233f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -27,6 +27,7 @@ if (MSVC)
27 # /Zo - Enhanced debug info for optimized builds 27 # /Zo - Enhanced debug info for optimized builds
28 # /permissive- - Enables stricter C++ standards conformance checks 28 # /permissive- - Enables stricter C++ standards conformance checks
29 # /EHsc - C++-only exception handling semantics 29 # /EHsc - C++-only exception handling semantics
30 # /volatile:iso - Use strict standards-compliant volatile semantics.
30 # /Zc:externConstexpr - Allow extern constexpr variables to have external linkage, like the standard mandates 31 # /Zc:externConstexpr - Allow extern constexpr variables to have external linkage, like the standard mandates
31 # /Zc:inline - Let codegen omit inline functions in object files 32 # /Zc:inline - Let codegen omit inline functions in object files
32 # /Zc:throwingNew - Let codegen assume `operator new` (without std::nothrow) will never return null 33 # /Zc:throwingNew - Let codegen assume `operator new` (without std::nothrow) will never return null
@@ -38,6 +39,7 @@ if (MSVC)
38 /permissive- 39 /permissive-
39 /EHsc 40 /EHsc
40 /std:c++latest 41 /std:c++latest
42 /volatile:iso
41 /Zc:externConstexpr 43 /Zc:externConstexpr
42 /Zc:inline 44 /Zc:inline
43 /Zc:throwingNew 45 /Zc:throwingNew
@@ -49,7 +51,10 @@ if (MSVC)
49 set(CMAKE_EXE_LINKER_FLAGS_DEBUG "/DEBUG /MANIFEST:NO" CACHE STRING "" FORCE) 51 set(CMAKE_EXE_LINKER_FLAGS_DEBUG "/DEBUG /MANIFEST:NO" CACHE STRING "" FORCE)
50 set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/DEBUG /MANIFEST:NO /INCREMENTAL:NO /OPT:REF,ICF" CACHE STRING "" FORCE) 52 set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/DEBUG /MANIFEST:NO /INCREMENTAL:NO /OPT:REF,ICF" CACHE STRING "" FORCE)
51else() 53else()
52 add_compile_options("-Wno-attributes") 54 add_compile_options(
55 -Wall
56 -Wno-attributes
57 )
53 58
54 if (APPLE AND CMAKE_CXX_COMPILER_ID STREQUAL Clang) 59 if (APPLE AND CMAKE_CXX_COMPILER_ID STREQUAL Clang)
55 add_compile_options("-stdlib=libc++") 60 add_compile_options("-stdlib=libc++")
diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h
index ac0e1d796..5bb139483 100644
--- a/src/core/hle/ipc_helpers.h
+++ b/src/core/hle/ipc_helpers.h
@@ -438,7 +438,7 @@ inline float RequestParser::Pop() {
438template <> 438template <>
439inline double RequestParser::Pop() { 439inline double RequestParser::Pop() {
440 const u64 value = Pop<u64>(); 440 const u64 value = Pop<u64>();
441 float real; 441 double real;
442 std::memcpy(&real, &value, sizeof(real)); 442 std::memcpy(&real, &value, sizeof(real));
443 return real; 443 return real;
444} 444}
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index fe710eb6e..42d9dd844 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -58,7 +58,7 @@ SharedPtr<WritableEvent> HLERequestContext::SleepClientThread(
58 auto& kernel = Core::System::GetInstance().Kernel(); 58 auto& kernel = Core::System::GetInstance().Kernel();
59 if (!writable_event) { 59 if (!writable_event) {
60 // Create event if not provided 60 // Create event if not provided
61 const auto pair = WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot, 61 const auto pair = WritableEvent::CreateEventPair(kernel, ResetType::Automatic,
62 "HLE Pause Event: " + reason); 62 "HLE Pause Event: " + reason);
63 writable_event = pair.writable; 63 writable_event = pair.writable;
64 } 64 }
diff --git a/src/core/hle/kernel/object.h b/src/core/hle/kernel/object.h
index 332876c27..2821176a7 100644
--- a/src/core/hle/kernel/object.h
+++ b/src/core/hle/kernel/object.h
@@ -33,8 +33,8 @@ enum class HandleType : u32 {
33}; 33};
34 34
35enum class ResetType { 35enum class ResetType {
36 OneShot, ///< Reset automatically on object acquisition 36 Automatic, ///< Reset automatically on object acquisition
37 Sticky, ///< Never reset automatically 37 Manual, ///< Never reset automatically
38}; 38};
39 39
40class Object : NonCopyable { 40class Object : NonCopyable {
diff --git a/src/core/hle/kernel/readable_event.cpp b/src/core/hle/kernel/readable_event.cpp
index c2b798a4e..06463cd26 100644
--- a/src/core/hle/kernel/readable_event.cpp
+++ b/src/core/hle/kernel/readable_event.cpp
@@ -21,8 +21,9 @@ bool ReadableEvent::ShouldWait(const Thread* thread) const {
21void ReadableEvent::Acquire(Thread* thread) { 21void ReadableEvent::Acquire(Thread* thread) {
22 ASSERT_MSG(!ShouldWait(thread), "object unavailable!"); 22 ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
23 23
24 if (reset_type == ResetType::OneShot) 24 if (reset_type == ResetType::Automatic) {
25 signaled = false; 25 signaled = false;
26 }
26} 27}
27 28
28void ReadableEvent::Signal() { 29void ReadableEvent::Signal() {
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 2dcf174c5..c23106299 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -1255,8 +1255,8 @@ static ResultCode MapProcessCodeMemory(Core::System& system, Handle process_hand
1255 return vm_manager.MapCodeMemory(dst_address, src_address, size); 1255 return vm_manager.MapCodeMemory(dst_address, src_address, size);
1256} 1256}
1257 1257
1258ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst_address, 1258static ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_handle,
1259 u64 src_address, u64 size) { 1259 u64 dst_address, u64 src_address, u64 size) {
1260 LOG_DEBUG(Kernel_SVC, 1260 LOG_DEBUG(Kernel_SVC,
1261 "called. process_handle=0x{:08X}, dst_address=0x{:016X}, src_address=0x{:016X}, " 1261 "called. process_handle=0x{:08X}, dst_address=0x{:016X}, src_address=0x{:016X}, "
1262 "size=0x{:016X}", 1262 "size=0x{:016X}",
@@ -1980,7 +1980,7 @@ static ResultCode CreateEvent(Core::System& system, Handle* write_handle, Handle
1980 1980
1981 auto& kernel = system.Kernel(); 1981 auto& kernel = system.Kernel();
1982 const auto [readable_event, writable_event] = 1982 const auto [readable_event, writable_event] =
1983 WritableEvent::CreateEventPair(kernel, ResetType::Sticky, "CreateEvent"); 1983 WritableEvent::CreateEventPair(kernel, ResetType::Manual, "CreateEvent");
1984 1984
1985 HandleTable& handle_table = kernel.CurrentProcess()->GetHandleTable(); 1985 HandleTable& handle_table = kernel.CurrentProcess()->GetHandleTable();
1986 1986
@@ -2183,8 +2183,8 @@ static ResultCode GetProcessList(Core::System& system, u32* out_num_processes,
2183 return RESULT_SUCCESS; 2183 return RESULT_SUCCESS;
2184} 2184}
2185 2185
2186ResultCode GetThreadList(Core::System& system, u32* out_num_threads, VAddr out_thread_ids, 2186static ResultCode GetThreadList(Core::System& system, u32* out_num_threads, VAddr out_thread_ids,
2187 u32 out_thread_ids_size, Handle debug_handle) { 2187 u32 out_thread_ids_size, Handle debug_handle) {
2188 // TODO: Handle this case when debug events are supported. 2188 // TODO: Handle this case when debug events are supported.
2189 UNIMPLEMENTED_IF(debug_handle != InvalidHandle); 2189 UNIMPLEMENTED_IF(debug_handle != InvalidHandle);
2190 2190
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 26a665bfd..1a32a109f 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -276,7 +276,7 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger
276 RegisterHandlers(functions); 276 RegisterHandlers(functions);
277 277
278 auto& kernel = Core::System::GetInstance().Kernel(); 278 auto& kernel = Core::System::GetInstance().Kernel();
279 launchable_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky, 279 launchable_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual,
280 "ISelfController:LaunchableEvent"); 280 "ISelfController:LaunchableEvent");
281} 281}
282 282
@@ -442,10 +442,10 @@ void ISelfController::GetIdleTimeDetectionExtension(Kernel::HLERequestContext& c
442 442
443AppletMessageQueue::AppletMessageQueue() { 443AppletMessageQueue::AppletMessageQueue() {
444 auto& kernel = Core::System::GetInstance().Kernel(); 444 auto& kernel = Core::System::GetInstance().Kernel();
445 on_new_message = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky, 445 on_new_message = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual,
446 "AMMessageQueue:OnMessageRecieved"); 446 "AMMessageQueue:OnMessageRecieved");
447 on_operation_mode_changed = Kernel::WritableEvent::CreateEventPair( 447 on_operation_mode_changed = Kernel::WritableEvent::CreateEventPair(
448 kernel, Kernel::ResetType::OneShot, "AMMessageQueue:OperationModeChanged"); 448 kernel, Kernel::ResetType::Automatic, "AMMessageQueue:OperationModeChanged");
449} 449}
450 450
451AppletMessageQueue::~AppletMessageQueue() = default; 451AppletMessageQueue::~AppletMessageQueue() = default;
@@ -835,6 +835,7 @@ void IStorageAccessor::Write(Kernel::HLERequestContext& ctx) {
835 835
836 IPC::ResponseBuilder rb{ctx, 2}; 836 IPC::ResponseBuilder rb{ctx, 2};
837 rb.Push(ERR_SIZE_OUT_OF_BOUNDS); 837 rb.Push(ERR_SIZE_OUT_OF_BOUNDS);
838 return;
838 } 839 }
839 840
840 std::memcpy(backing.buffer.data() + offset, data.data(), data.size()); 841 std::memcpy(backing.buffer.data() + offset, data.data(), data.size());
@@ -857,6 +858,7 @@ void IStorageAccessor::Read(Kernel::HLERequestContext& ctx) {
857 858
858 IPC::ResponseBuilder rb{ctx, 2}; 859 IPC::ResponseBuilder rb{ctx, 2};
859 rb.Push(ERR_SIZE_OUT_OF_BOUNDS); 860 rb.Push(ERR_SIZE_OUT_OF_BOUNDS);
861 return;
860 } 862 }
861 863
862 ctx.WriteBuffer(backing.buffer.data() + offset, size); 864 ctx.WriteBuffer(backing.buffer.data() + offset, size);
diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp
index 7f70b10df..e812c66e9 100644
--- a/src/core/hle/service/am/applets/applets.cpp
+++ b/src/core/hle/service/am/applets/applets.cpp
@@ -26,11 +26,11 @@ namespace Service::AM::Applets {
26AppletDataBroker::AppletDataBroker() { 26AppletDataBroker::AppletDataBroker() {
27 auto& kernel = Core::System::GetInstance().Kernel(); 27 auto& kernel = Core::System::GetInstance().Kernel();
28 state_changed_event = Kernel::WritableEvent::CreateEventPair( 28 state_changed_event = Kernel::WritableEvent::CreateEventPair(
29 kernel, Kernel::ResetType::Sticky, "ILibraryAppletAccessor:StateChangedEvent"); 29 kernel, Kernel::ResetType::Manual, "ILibraryAppletAccessor:StateChangedEvent");
30 pop_out_data_event = Kernel::WritableEvent::CreateEventPair( 30 pop_out_data_event = Kernel::WritableEvent::CreateEventPair(
31 kernel, Kernel::ResetType::Sticky, "ILibraryAppletAccessor:PopDataOutEvent"); 31 kernel, Kernel::ResetType::Manual, "ILibraryAppletAccessor:PopDataOutEvent");
32 pop_interactive_out_data_event = Kernel::WritableEvent::CreateEventPair( 32 pop_interactive_out_data_event = Kernel::WritableEvent::CreateEventPair(
33 kernel, Kernel::ResetType::Sticky, "ILibraryAppletAccessor:PopInteractiveDataOutEvent"); 33 kernel, Kernel::ResetType::Manual, "ILibraryAppletAccessor:PopInteractiveDataOutEvent");
34} 34}
35 35
36AppletDataBroker::~AppletDataBroker() = default; 36AppletDataBroker::~AppletDataBroker() = default;
diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp
index 51d8c26b4..bd4e38461 100644
--- a/src/core/hle/service/aoc/aoc_u.cpp
+++ b/src/core/hle/service/aoc/aoc_u.cpp
@@ -68,7 +68,7 @@ AOC_U::AOC_U() : ServiceFramework("aoc:u"), add_on_content(AccumulateAOCTitleIDs
68 RegisterHandlers(functions); 68 RegisterHandlers(functions);
69 69
70 auto& kernel = Core::System::GetInstance().Kernel(); 70 auto& kernel = Core::System::GetInstance().Kernel();
71 aoc_change_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky, 71 aoc_change_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual,
72 "GetAddOnContentListChanged:Event"); 72 "GetAddOnContentListChanged:Event");
73} 73}
74 74
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp
index 12875fb42..6ba41b20a 100644
--- a/src/core/hle/service/audio/audout_u.cpp
+++ b/src/core/hle/service/audio/audout_u.cpp
@@ -67,7 +67,7 @@ public:
67 // This is the event handle used to check if the audio buffer was released 67 // This is the event handle used to check if the audio buffer was released
68 auto& system = Core::System::GetInstance(); 68 auto& system = Core::System::GetInstance();
69 buffer_event = Kernel::WritableEvent::CreateEventPair( 69 buffer_event = Kernel::WritableEvent::CreateEventPair(
70 system.Kernel(), Kernel::ResetType::Sticky, "IAudioOutBufferReleased"); 70 system.Kernel(), Kernel::ResetType::Manual, "IAudioOutBufferReleased");
71 71
72 stream = audio_core.OpenStream(system.CoreTiming(), audio_params.sample_rate, 72 stream = audio_core.OpenStream(system.CoreTiming(), audio_params.sample_rate,
73 audio_params.channel_count, std::move(unique_name), 73 audio_params.channel_count, std::move(unique_name),
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index 1dde6edb7..e69f6cf7f 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -46,7 +46,7 @@ public:
46 46
47 auto& system = Core::System::GetInstance(); 47 auto& system = Core::System::GetInstance();
48 system_event = Kernel::WritableEvent::CreateEventPair( 48 system_event = Kernel::WritableEvent::CreateEventPair(
49 system.Kernel(), Kernel::ResetType::Sticky, "IAudioRenderer:SystemEvent"); 49 system.Kernel(), Kernel::ResetType::Manual, "IAudioRenderer:SystemEvent");
50 renderer = std::make_unique<AudioCore::AudioRenderer>(system.CoreTiming(), audren_params, 50 renderer = std::make_unique<AudioCore::AudioRenderer>(system.CoreTiming(), audren_params,
51 system_event.writable); 51 system_event.writable);
52 } 52 }
@@ -178,7 +178,7 @@ public:
178 RegisterHandlers(functions); 178 RegisterHandlers(functions);
179 179
180 auto& kernel = Core::System::GetInstance().Kernel(); 180 auto& kernel = Core::System::GetInstance().Kernel();
181 buffer_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot, 181 buffer_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic,
182 "IAudioOutBufferReleasedEvent"); 182 "IAudioOutBufferReleasedEvent");
183 } 183 }
184 184
diff --git a/src/core/hle/service/btdrv/btdrv.cpp b/src/core/hle/service/btdrv/btdrv.cpp
index 974ff8e1a..3c7ca2c44 100644
--- a/src/core/hle/service/btdrv/btdrv.cpp
+++ b/src/core/hle/service/btdrv/btdrv.cpp
@@ -34,8 +34,8 @@ public:
34 RegisterHandlers(functions); 34 RegisterHandlers(functions);
35 35
36 auto& kernel = Core::System::GetInstance().Kernel(); 36 auto& kernel = Core::System::GetInstance().Kernel();
37 register_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot, 37 register_event = Kernel::WritableEvent::CreateEventPair(
38 "BT:RegisterEvent"); 38 kernel, Kernel::ResetType::Automatic, "BT:RegisterEvent");
39 } 39 }
40 40
41private: 41private:
diff --git a/src/core/hle/service/btm/btm.cpp b/src/core/hle/service/btm/btm.cpp
index 4f15c3f19..b439ee7ec 100644
--- a/src/core/hle/service/btm/btm.cpp
+++ b/src/core/hle/service/btm/btm.cpp
@@ -57,13 +57,13 @@ public:
57 RegisterHandlers(functions); 57 RegisterHandlers(functions);
58 58
59 auto& kernel = Core::System::GetInstance().Kernel(); 59 auto& kernel = Core::System::GetInstance().Kernel();
60 scan_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot, 60 scan_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic,
61 "IBtmUserCore:ScanEvent"); 61 "IBtmUserCore:ScanEvent");
62 connection_event = Kernel::WritableEvent::CreateEventPair( 62 connection_event = Kernel::WritableEvent::CreateEventPair(
63 kernel, Kernel::ResetType::OneShot, "IBtmUserCore:ConnectionEvent"); 63 kernel, Kernel::ResetType::Automatic, "IBtmUserCore:ConnectionEvent");
64 service_discovery = Kernel::WritableEvent::CreateEventPair( 64 service_discovery = Kernel::WritableEvent::CreateEventPair(
65 kernel, Kernel::ResetType::OneShot, "IBtmUserCore:Discovery"); 65 kernel, Kernel::ResetType::Automatic, "IBtmUserCore:Discovery");
66 config_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot, 66 config_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic,
67 "IBtmUserCore:ConfigEvent"); 67 "IBtmUserCore:ConfigEvent");
68 } 68 }
69 69
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index e7fc7a619..fdd6d79a2 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -170,7 +170,7 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) {
170void Controller_NPad::OnInit() { 170void Controller_NPad::OnInit() {
171 auto& kernel = Core::System::GetInstance().Kernel(); 171 auto& kernel = Core::System::GetInstance().Kernel();
172 styleset_changed_event = Kernel::WritableEvent::CreateEventPair( 172 styleset_changed_event = Kernel::WritableEvent::CreateEventPair(
173 kernel, Kernel::ResetType::OneShot, "npad:NpadStyleSetChanged"); 173 kernel, Kernel::ResetType::Automatic, "npad:NpadStyleSetChanged");
174 174
175 if (!IsControllerActivated()) { 175 if (!IsControllerActivated()) {
176 return; 176 return;
diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp
index c6babdd4d..a5cb06f8a 100644
--- a/src/core/hle/service/nfp/nfp.cpp
+++ b/src/core/hle/service/nfp/nfp.cpp
@@ -26,7 +26,7 @@ constexpr ResultCode ERR_NO_APPLICATION_AREA(ErrorModule::NFP, 152);
26Module::Interface::Interface(std::shared_ptr<Module> module, const char* name) 26Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
27 : ServiceFramework(name), module(std::move(module)) { 27 : ServiceFramework(name), module(std::move(module)) {
28 auto& kernel = Core::System::GetInstance().Kernel(); 28 auto& kernel = Core::System::GetInstance().Kernel();
29 nfc_tag_load = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot, 29 nfc_tag_load = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic,
30 "IUser:NFCTagDetected"); 30 "IUser:NFCTagDetected");
31} 31}
32 32
@@ -67,9 +67,9 @@ public:
67 67
68 auto& kernel = Core::System::GetInstance().Kernel(); 68 auto& kernel = Core::System::GetInstance().Kernel();
69 deactivate_event = Kernel::WritableEvent::CreateEventPair( 69 deactivate_event = Kernel::WritableEvent::CreateEventPair(
70 kernel, Kernel::ResetType::OneShot, "IUser:DeactivateEvent"); 70 kernel, Kernel::ResetType::Automatic, "IUser:DeactivateEvent");
71 availability_change_event = Kernel::WritableEvent::CreateEventPair( 71 availability_change_event = Kernel::WritableEvent::CreateEventPair(
72 kernel, Kernel::ResetType::OneShot, "IUser:AvailabilityChangeEvent"); 72 kernel, Kernel::ResetType::Automatic, "IUser:AvailabilityChangeEvent");
73 } 73 }
74 74
75private: 75private:
diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp
index f92571008..76b12b482 100644
--- a/src/core/hle/service/nifm/nifm.cpp
+++ b/src/core/hle/service/nifm/nifm.cpp
@@ -62,9 +62,9 @@ public:
62 RegisterHandlers(functions); 62 RegisterHandlers(functions);
63 63
64 auto& kernel = Core::System::GetInstance().Kernel(); 64 auto& kernel = Core::System::GetInstance().Kernel();
65 event1 = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot, 65 event1 = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic,
66 "IRequest:Event1"); 66 "IRequest:Event1");
67 event2 = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot, 67 event2 = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic,
68 "IRequest:Event2"); 68 "IRequest:Event2");
69 } 69 }
70 70
diff --git a/src/core/hle/service/nim/nim.cpp b/src/core/hle/service/nim/nim.cpp
index 0dabcd23b..f319a3ca1 100644
--- a/src/core/hle/service/nim/nim.cpp
+++ b/src/core/hle/service/nim/nim.cpp
@@ -141,7 +141,7 @@ public:
141 141
142 auto& kernel = Core::System::GetInstance().Kernel(); 142 auto& kernel = Core::System::GetInstance().Kernel();
143 finished_event = Kernel::WritableEvent::CreateEventPair( 143 finished_event = Kernel::WritableEvent::CreateEventPair(
144 kernel, Kernel::ResetType::OneShot, 144 kernel, Kernel::ResetType::Automatic,
145 "IEnsureNetworkClockAvailabilityService:FinishEvent"); 145 "IEnsureNetworkClockAvailabilityService:FinishEvent");
146 } 146 }
147 147
diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp
index 3b9ab4b14..b60fc748b 100644
--- a/src/core/hle/service/nvdrv/interface.cpp
+++ b/src/core/hle/service/nvdrv/interface.cpp
@@ -129,7 +129,7 @@ NVDRV::NVDRV(std::shared_ptr<Module> nvdrv, const char* name)
129 RegisterHandlers(functions); 129 RegisterHandlers(functions);
130 130
131 auto& kernel = Core::System::GetInstance().Kernel(); 131 auto& kernel = Core::System::GetInstance().Kernel();
132 query_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot, 132 query_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic,
133 "NVDRV::query_event"); 133 "NVDRV::query_event");
134} 134}
135 135
diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp
index 4d150fc71..5731e815f 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.cpp
+++ b/src/core/hle/service/nvflinger/buffer_queue.cpp
@@ -16,7 +16,7 @@ namespace Service::NVFlinger {
16 16
17BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) { 17BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) {
18 auto& kernel = Core::System::GetInstance().Kernel(); 18 auto& kernel = Core::System::GetInstance().Kernel();
19 buffer_wait_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky, 19 buffer_wait_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual,
20 "BufferQueue NativeHandle"); 20 "BufferQueue NativeHandle");
21} 21}
22 22
diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp
index 01d80311b..a8d088305 100644
--- a/src/core/hle/service/vi/display/vi_display.cpp
+++ b/src/core/hle/service/vi/display/vi_display.cpp
@@ -17,7 +17,7 @@ namespace Service::VI {
17 17
18Display::Display(u64 id, std::string name) : id{id}, name{std::move(name)} { 18Display::Display(u64 id, std::string name) : id{id}, name{std::move(name)} {
19 auto& kernel = Core::System::GetInstance().Kernel(); 19 auto& kernel = Core::System::GetInstance().Kernel();
20 vsync_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky, 20 vsync_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual,
21 fmt::format("Display VSync Event {}", id)); 21 fmt::format("Display VSync Event {}", id));
22} 22}
23 23
diff --git a/src/video_core/engines/engine_upload.cpp b/src/video_core/engines/engine_upload.cpp
index f8aa4ff55..082a40cd9 100644
--- a/src/video_core/engines/engine_upload.cpp
+++ b/src/video_core/engines/engine_upload.cpp
@@ -2,6 +2,8 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <cstring>
6
5#include "common/assert.h" 7#include "common/assert.h"
6#include "video_core/engines/engine_upload.h" 8#include "video_core/engines/engine_upload.h"
7#include "video_core/memory_manager.h" 9#include "video_core/memory_manager.h"
@@ -10,7 +12,9 @@
10namespace Tegra::Engines::Upload { 12namespace Tegra::Engines::Upload {
11 13
12State::State(MemoryManager& memory_manager, Registers& regs) 14State::State(MemoryManager& memory_manager, Registers& regs)
13 : memory_manager(memory_manager), regs(regs) {} 15 : regs{regs}, memory_manager{memory_manager} {}
16
17State::~State() = default;
14 18
15void State::ProcessExec(const bool is_linear) { 19void State::ProcessExec(const bool is_linear) {
16 write_offset = 0; 20 write_offset = 0;
diff --git a/src/video_core/engines/engine_upload.h b/src/video_core/engines/engine_upload.h
index 9c6e0d21c..ef4f5839a 100644
--- a/src/video_core/engines/engine_upload.h
+++ b/src/video_core/engines/engine_upload.h
@@ -4,10 +4,8 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <cstddef>
8#include <vector> 7#include <vector>
9#include "common/bit_field.h" 8#include "common/bit_field.h"
10#include "common/common_funcs.h"
11#include "common/common_types.h" 9#include "common/common_types.h"
12 10
13namespace Tegra { 11namespace Tegra {
@@ -57,10 +55,10 @@ struct Registers {
57class State { 55class State {
58public: 56public:
59 State(MemoryManager& memory_manager, Registers& regs); 57 State(MemoryManager& memory_manager, Registers& regs);
60 ~State() = default; 58 ~State();
61 59
62 void ProcessExec(const bool is_linear); 60 void ProcessExec(bool is_linear);
63 void ProcessData(const u32 data, const bool is_last_call); 61 void ProcessData(u32 data, bool is_last_call);
64 62
65private: 63private:
66 u32 write_offset = 0; 64 u32 write_offset = 0;
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index d7b586db9..39968d403 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -34,9 +34,9 @@ void Maxwell3D::InitializeRegisterDefaults() {
34 34
35 // Depth range near/far is not always set, but is expected to be the default 0.0f, 1.0f. This is 35 // Depth range near/far is not always set, but is expected to be the default 0.0f, 1.0f. This is
36 // needed for ARMS. 36 // needed for ARMS.
37 for (std::size_t viewport{}; viewport < Regs::NumViewports; ++viewport) { 37 for (auto& viewport : regs.viewports) {
38 regs.viewports[viewport].depth_range_near = 0.0f; 38 viewport.depth_range_near = 0.0f;
39 regs.viewports[viewport].depth_range_far = 1.0f; 39 viewport.depth_range_far = 1.0f;
40 } 40 }
41 41
42 // Doom and Bomberman seems to use the uninitialized registers and just enable blend 42 // Doom and Bomberman seems to use the uninitialized registers and just enable blend
@@ -47,13 +47,13 @@ void Maxwell3D::InitializeRegisterDefaults() {
47 regs.blend.equation_a = Regs::Blend::Equation::Add; 47 regs.blend.equation_a = Regs::Blend::Equation::Add;
48 regs.blend.factor_source_a = Regs::Blend::Factor::One; 48 regs.blend.factor_source_a = Regs::Blend::Factor::One;
49 regs.blend.factor_dest_a = Regs::Blend::Factor::Zero; 49 regs.blend.factor_dest_a = Regs::Blend::Factor::Zero;
50 for (std::size_t blend_index = 0; blend_index < Regs::NumRenderTargets; blend_index++) { 50 for (auto& blend : regs.independent_blend) {
51 regs.independent_blend[blend_index].equation_rgb = Regs::Blend::Equation::Add; 51 blend.equation_rgb = Regs::Blend::Equation::Add;
52 regs.independent_blend[blend_index].factor_source_rgb = Regs::Blend::Factor::One; 52 blend.factor_source_rgb = Regs::Blend::Factor::One;
53 regs.independent_blend[blend_index].factor_dest_rgb = Regs::Blend::Factor::Zero; 53 blend.factor_dest_rgb = Regs::Blend::Factor::Zero;
54 regs.independent_blend[blend_index].equation_a = Regs::Blend::Equation::Add; 54 blend.equation_a = Regs::Blend::Equation::Add;
55 regs.independent_blend[blend_index].factor_source_a = Regs::Blend::Factor::One; 55 blend.factor_source_a = Regs::Blend::Factor::One;
56 regs.independent_blend[blend_index].factor_dest_a = Regs::Blend::Factor::Zero; 56 blend.factor_dest_a = Regs::Blend::Factor::Zero;
57 } 57 }
58 regs.stencil_front_op_fail = Regs::StencilOp::Keep; 58 regs.stencil_front_op_fail = Regs::StencilOp::Keep;
59 regs.stencil_front_op_zfail = Regs::StencilOp::Keep; 59 regs.stencil_front_op_zfail = Regs::StencilOp::Keep;
@@ -75,11 +75,11 @@ void Maxwell3D::InitializeRegisterDefaults() {
75 75
76 // TODO(bunnei): Some games do not initialize the color masks (e.g. Sonic Mania). Assuming a 76 // TODO(bunnei): Some games do not initialize the color masks (e.g. Sonic Mania). Assuming a
77 // default of enabled fixes rendering here. 77 // default of enabled fixes rendering here.
78 for (std::size_t color_mask = 0; color_mask < Regs::NumRenderTargets; color_mask++) { 78 for (auto& color_mask : regs.color_mask) {
79 regs.color_mask[color_mask].R.Assign(1); 79 color_mask.R.Assign(1);
80 regs.color_mask[color_mask].G.Assign(1); 80 color_mask.G.Assign(1);
81 regs.color_mask[color_mask].B.Assign(1); 81 color_mask.B.Assign(1);
82 regs.color_mask[color_mask].A.Assign(1); 82 color_mask.A.Assign(1);
83 } 83 }
84 84
85 // Commercial games seem to assume this value is enabled and nouveau sets this value manually. 85 // Commercial games seem to assume this value is enabled and nouveau sets this value manually.
@@ -178,13 +178,13 @@ void Maxwell3D::CallMethod(const GPU::MethodCall& method_call) {
178 178
179 // Vertex buffer 179 // Vertex buffer
180 if (method >= MAXWELL3D_REG_INDEX(vertex_array) && 180 if (method >= MAXWELL3D_REG_INDEX(vertex_array) &&
181 method < MAXWELL3D_REG_INDEX(vertex_array) + 4 * 32) { 181 method < MAXWELL3D_REG_INDEX(vertex_array) + 4 * Regs::NumVertexArrays) {
182 dirty_flags.vertex_array.set((method - MAXWELL3D_REG_INDEX(vertex_array)) >> 2); 182 dirty_flags.vertex_array.set((method - MAXWELL3D_REG_INDEX(vertex_array)) >> 2);
183 } else if (method >= MAXWELL3D_REG_INDEX(vertex_array_limit) && 183 } else if (method >= MAXWELL3D_REG_INDEX(vertex_array_limit) &&
184 method < MAXWELL3D_REG_INDEX(vertex_array_limit) + 2 * 32) { 184 method < MAXWELL3D_REG_INDEX(vertex_array_limit) + 2 * Regs::NumVertexArrays) {
185 dirty_flags.vertex_array.set((method - MAXWELL3D_REG_INDEX(vertex_array_limit)) >> 1); 185 dirty_flags.vertex_array.set((method - MAXWELL3D_REG_INDEX(vertex_array_limit)) >> 1);
186 } else if (method >= MAXWELL3D_REG_INDEX(instanced_arrays) && 186 } else if (method >= MAXWELL3D_REG_INDEX(instanced_arrays) &&
187 method < MAXWELL3D_REG_INDEX(instanced_arrays) + 32) { 187 method < MAXWELL3D_REG_INDEX(instanced_arrays) + Regs::NumVertexArrays) {
188 dirty_flags.vertex_array.set(method - MAXWELL3D_REG_INDEX(instanced_arrays)); 188 dirty_flags.vertex_array.set(method - MAXWELL3D_REG_INDEX(instanced_arrays));
189 } 189 }
190 } 190 }
@@ -442,7 +442,7 @@ Texture::TICEntry Maxwell3D::GetTICEntry(u32 tic_index) const {
442 const auto a_type = tic_entry.a_type.Value(); 442 const auto a_type = tic_entry.a_type.Value();
443 443
444 // TODO(Subv): Different data types for separate components are not supported 444 // TODO(Subv): Different data types for separate components are not supported
445 ASSERT(r_type == g_type && r_type == b_type && r_type == a_type); 445 DEBUG_ASSERT(r_type == g_type && r_type == b_type && r_type == a_type);
446 446
447 return tic_entry; 447 return tic_entry;
448} 448}
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index 4883b582a..48e4fec33 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -6,6 +6,7 @@
6 6
7#include <array> 7#include <array>
8#include <bitset> 8#include <bitset>
9#include <type_traits>
9#include <unordered_map> 10#include <unordered_map>
10#include <vector> 11#include <vector>
11 12
@@ -1107,6 +1108,7 @@ public:
1107 } regs{}; 1108 } regs{};
1108 1109
1109 static_assert(sizeof(Regs) == Regs::NUM_REGS * sizeof(u32), "Maxwell3D Regs has wrong size"); 1110 static_assert(sizeof(Regs) == Regs::NUM_REGS * sizeof(u32), "Maxwell3D Regs has wrong size");
1111 static_assert(std::is_trivially_copyable_v<Regs>, "Maxwell3D Regs must be trivially copyable");
1110 1112
1111 struct State { 1113 struct State {
1112 struct ConstBufferInfo { 1114 struct ConstBufferInfo {
diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp
index c9a2077de..1e2ff46b0 100644
--- a/src/video_core/gpu_thread.cpp
+++ b/src/video_core/gpu_thread.cpp
@@ -44,7 +44,7 @@ static void RunThread(VideoCore::RendererBase& renderer, Tegra::DmaPusher& dma_p
44 renderer.Rasterizer().FlushRegion(data->addr, data->size); 44 renderer.Rasterizer().FlushRegion(data->addr, data->size);
45 } else if (const auto data = std::get_if<InvalidateRegionCommand>(&next.data)) { 45 } else if (const auto data = std::get_if<InvalidateRegionCommand>(&next.data)) {
46 renderer.Rasterizer().InvalidateRegion(data->addr, data->size); 46 renderer.Rasterizer().InvalidateRegion(data->addr, data->size);
47 } else if (const auto data = std::get_if<EndProcessingCommand>(&next.data)) { 47 } else if (std::holds_alternative<EndProcessingCommand>(next.data)) {
48 return; 48 return;
49 } else { 49 } else {
50 UNREACHABLE(); 50 UNREACHABLE();
@@ -118,7 +118,7 @@ void SynchState::WaitForSynchronization(u64 fence) {
118 // Wait for the GPU to be idle (all commands to be executed) 118 // Wait for the GPU to be idle (all commands to be executed)
119 { 119 {
120 MICROPROFILE_SCOPE(GPU_wait); 120 MICROPROFILE_SCOPE(GPU_wait);
121 std::unique_lock<std::mutex> lock{synchronization_mutex}; 121 std::unique_lock lock{synchronization_mutex};
122 synchronization_condition.wait(lock, [this, fence] { return signaled_fence >= fence; }); 122 synchronization_condition.wait(lock, [this, fence] { return signaled_fence >= fence; });
123 } 123 }
124} 124}
diff --git a/src/video_core/gpu_thread.h b/src/video_core/gpu_thread.h
index cc14527c7..cdf86f562 100644
--- a/src/video_core/gpu_thread.h
+++ b/src/video_core/gpu_thread.h
@@ -109,7 +109,7 @@ struct SynchState final {
109 109
110 void TrySynchronize() { 110 void TrySynchronize() {
111 if (IsSynchronized()) { 111 if (IsSynchronized()) {
112 std::lock_guard<std::mutex> lock{synchronization_mutex}; 112 std::lock_guard lock{synchronization_mutex};
113 synchronization_condition.notify_one(); 113 synchronization_condition.notify_one();
114 } 114 }
115 } 115 }
diff --git a/src/video_core/macro_interpreter.cpp b/src/video_core/macro_interpreter.cpp
index 524d9ea5a..fbea107ca 100644
--- a/src/video_core/macro_interpreter.cpp
+++ b/src/video_core/macro_interpreter.cpp
@@ -118,10 +118,10 @@ bool MacroInterpreter::Step(u32 offset, bool is_delay_slot) {
118 static_cast<u32>(opcode.operation.Value())); 118 static_cast<u32>(opcode.operation.Value()));
119 } 119 }
120 120
121 if (opcode.is_exit) { 121 // An instruction with the Exit flag will not actually
122 // cause an exit if it's executed inside a delay slot.
123 if (opcode.is_exit && !is_delay_slot) {
122 // Exit has a delay slot, execute the next instruction 124 // Exit has a delay slot, execute the next instruction
123 // Note: Executing an exit during a branch delay slot will cause the instruction at the
124 // branch target to be executed before exiting.
125 Step(offset, true); 125 Step(offset, true);
126 return false; 126 return false;
127 } 127 }
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp
index 6c98c6701..5d8d126c1 100644
--- a/src/video_core/memory_manager.cpp
+++ b/src/video_core/memory_manager.cpp
@@ -25,6 +25,8 @@ MemoryManager::MemoryManager(VideoCore::RasterizerInterface& rasterizer) : raste
25 UpdatePageTableForVMA(initial_vma); 25 UpdatePageTableForVMA(initial_vma);
26} 26}
27 27
28MemoryManager::~MemoryManager() = default;
29
28GPUVAddr MemoryManager::AllocateSpace(u64 size, u64 align) { 30GPUVAddr MemoryManager::AllocateSpace(u64 size, u64 align) {
29 const u64 aligned_size{Common::AlignUp(size, page_size)}; 31 const u64 aligned_size{Common::AlignUp(size, page_size)};
30 const GPUVAddr gpu_addr{FindFreeRegion(address_space_base, aligned_size)}; 32 const GPUVAddr gpu_addr{FindFreeRegion(address_space_base, aligned_size)};
@@ -199,11 +201,11 @@ const u8* MemoryManager::GetPointer(GPUVAddr addr) const {
199 return {}; 201 return {};
200} 202}
201 203
202bool MemoryManager::IsBlockContinous(const GPUVAddr start, const std::size_t size) { 204bool MemoryManager::IsBlockContinuous(const GPUVAddr start, const std::size_t size) const {
203 const GPUVAddr end = start + size; 205 const GPUVAddr end = start + size;
204 const auto host_ptr_start = reinterpret_cast<std::uintptr_t>(GetPointer(start)); 206 const auto host_ptr_start = reinterpret_cast<std::uintptr_t>(GetPointer(start));
205 const auto host_ptr_end = reinterpret_cast<std::uintptr_t>(GetPointer(end)); 207 const auto host_ptr_end = reinterpret_cast<std::uintptr_t>(GetPointer(end));
206 const std::size_t range = static_cast<std::size_t>(host_ptr_end - host_ptr_start); 208 const auto range = static_cast<std::size_t>(host_ptr_end - host_ptr_start);
207 return range == size; 209 return range == size;
208} 210}
209 211
diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h
index e4f0c4bd6..113f9d8f3 100644
--- a/src/video_core/memory_manager.h
+++ b/src/video_core/memory_manager.h
@@ -47,7 +47,8 @@ struct VirtualMemoryArea {
47 47
48class MemoryManager final { 48class MemoryManager final {
49public: 49public:
50 MemoryManager(VideoCore::RasterizerInterface& rasterizer); 50 explicit MemoryManager(VideoCore::RasterizerInterface& rasterizer);
51 ~MemoryManager();
51 52
52 GPUVAddr AllocateSpace(u64 size, u64 align); 53 GPUVAddr AllocateSpace(u64 size, u64 align);
53 GPUVAddr AllocateSpace(GPUVAddr addr, u64 size, u64 align); 54 GPUVAddr AllocateSpace(GPUVAddr addr, u64 size, u64 align);
@@ -65,18 +66,18 @@ public:
65 u8* GetPointer(GPUVAddr addr); 66 u8* GetPointer(GPUVAddr addr);
66 const u8* GetPointer(GPUVAddr addr) const; 67 const u8* GetPointer(GPUVAddr addr) const;
67 68
68 // Returns true if the block is continous in host memory, false otherwise 69 /// Returns true if the block is continuous in host memory, false otherwise
69 bool IsBlockContinous(const GPUVAddr start, const std::size_t size); 70 bool IsBlockContinuous(GPUVAddr start, std::size_t size) const;
70 71
71 /** 72 /**
72 * ReadBlock and WriteBlock are full read and write operations over virtual 73 * ReadBlock and WriteBlock are full read and write operations over virtual
73 * GPU Memory. It's important to use these when GPU memory may not be continous 74 * GPU Memory. It's important to use these when GPU memory may not be continuous
74 * in the Host Memory counterpart. Note: This functions cause Host GPU Memory 75 * in the Host Memory counterpart. Note: This functions cause Host GPU Memory
75 * Flushes and Invalidations, respectively to each operation. 76 * Flushes and Invalidations, respectively to each operation.
76 */ 77 */
77 void ReadBlock(GPUVAddr src_addr, void* dest_buffer, const std::size_t size) const; 78 void ReadBlock(GPUVAddr src_addr, void* dest_buffer, std::size_t size) const;
78 void WriteBlock(GPUVAddr dest_addr, const void* src_buffer, const std::size_t size); 79 void WriteBlock(GPUVAddr dest_addr, const void* src_buffer, std::size_t size);
79 void CopyBlock(GPUVAddr dest_addr, GPUVAddr src_addr, const std::size_t size); 80 void CopyBlock(GPUVAddr dest_addr, GPUVAddr src_addr, std::size_t size);
80 81
81 /** 82 /**
82 * ReadBlockUnsafe and WriteBlockUnsafe are special versions of ReadBlock and 83 * ReadBlockUnsafe and WriteBlockUnsafe are special versions of ReadBlock and
@@ -88,9 +89,9 @@ public:
88 * WriteBlockUnsafe instead of WriteBlock since it shouldn't invalidate the texture 89 * WriteBlockUnsafe instead of WriteBlock since it shouldn't invalidate the texture
89 * being flushed. 90 * being flushed.
90 */ 91 */
91 void ReadBlockUnsafe(GPUVAddr src_addr, void* dest_buffer, const std::size_t size) const; 92 void ReadBlockUnsafe(GPUVAddr src_addr, void* dest_buffer, std::size_t size) const;
92 void WriteBlockUnsafe(GPUVAddr dest_addr, const void* src_buffer, const std::size_t size); 93 void WriteBlockUnsafe(GPUVAddr dest_addr, const void* src_buffer, std::size_t size);
93 void CopyBlockUnsafe(GPUVAddr dest_addr, GPUVAddr src_addr, const std::size_t size); 94 void CopyBlockUnsafe(GPUVAddr dest_addr, GPUVAddr src_addr, std::size_t size);
94 95
95private: 96private:
96 using VMAMap = std::map<GPUVAddr, VirtualMemoryArea>; 97 using VMAMap = std::map<GPUVAddr, VirtualMemoryArea>;
@@ -111,10 +112,10 @@ private:
111 /** 112 /**
112 * Maps an unmanaged host memory pointer at a given address. 113 * Maps an unmanaged host memory pointer at a given address.
113 * 114 *
114 * @param target The guest address to start the mapping at. 115 * @param target The guest address to start the mapping at.
115 * @param memory The memory to be mapped. 116 * @param memory The memory to be mapped.
116 * @param size Size of the mapping. 117 * @param size Size of the mapping in bytes.
117 * @param state MemoryState tag to attach to the VMA. 118 * @param backing_addr The base address of the range to back this mapping.
118 */ 119 */
119 VMAHandle MapBackingMemory(GPUVAddr target, u8* memory, u64 size, VAddr backing_addr); 120 VMAHandle MapBackingMemory(GPUVAddr target, u8* memory, u64 size, VAddr backing_addr);
120 121
@@ -124,7 +125,7 @@ private:
124 /// Converts a VMAHandle to a mutable VMAIter. 125 /// Converts a VMAHandle to a mutable VMAIter.
125 VMAIter StripIterConstness(const VMAHandle& iter); 126 VMAIter StripIterConstness(const VMAHandle& iter);
126 127
127 /// Marks as the specfied VMA as allocated. 128 /// Marks as the specified VMA as allocated.
128 VMAIter Allocate(VMAIter vma); 129 VMAIter Allocate(VMAIter vma);
129 130
130 /** 131 /**
diff --git a/src/video_core/rasterizer_cache.h b/src/video_core/rasterizer_cache.h
index 291772186..f820f3ed9 100644
--- a/src/video_core/rasterizer_cache.h
+++ b/src/video_core/rasterizer_cache.h
@@ -37,9 +37,6 @@ public:
37 /// Gets the size of the shader in guest memory, required for cache management 37 /// Gets the size of the shader in guest memory, required for cache management
38 virtual std::size_t GetSizeInBytes() const = 0; 38 virtual std::size_t GetSizeInBytes() const = 0;
39 39
40 /// Wriets any cached resources back to memory
41 virtual void Flush() = 0;
42
43 /// Sets whether the cached object should be considered registered 40 /// Sets whether the cached object should be considered registered
44 void SetIsRegistered(bool registered) { 41 void SetIsRegistered(bool registered) {
45 is_registered = registered; 42 is_registered = registered;
@@ -158,6 +155,8 @@ protected:
158 return ++modified_ticks; 155 return ++modified_ticks;
159 } 156 }
160 157
158 virtual void FlushObjectInner(const T& object) = 0;
159
161 /// Flushes the specified object, updating appropriate cache state as needed 160 /// Flushes the specified object, updating appropriate cache state as needed
162 void FlushObject(const T& object) { 161 void FlushObject(const T& object) {
163 std::lock_guard lock{mutex}; 162 std::lock_guard lock{mutex};
@@ -165,7 +164,7 @@ protected:
165 if (!object->IsDirty()) { 164 if (!object->IsDirty()) {
166 return; 165 return;
167 } 166 }
168 object->Flush(); 167 FlushObjectInner(object);
169 object->MarkAsModified(false, *this); 168 object->MarkAsModified(false, *this);
170 } 169 }
171 170
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.h b/src/video_core/renderer_opengl/gl_buffer_cache.h
index fc33aa433..f9247a40e 100644
--- a/src/video_core/renderer_opengl/gl_buffer_cache.h
+++ b/src/video_core/renderer_opengl/gl_buffer_cache.h
@@ -42,9 +42,6 @@ public:
42 return alignment; 42 return alignment;
43 } 43 }
44 44
45 // We do not have to flush this cache as things in it are never modified by us.
46 void Flush() override {}
47
48private: 45private:
49 VAddr cpu_addr{}; 46 VAddr cpu_addr{};
50 std::size_t size{}; 47 std::size_t size{};
@@ -75,6 +72,9 @@ public:
75protected: 72protected:
76 void AlignBuffer(std::size_t alignment); 73 void AlignBuffer(std::size_t alignment);
77 74
75 // We do not have to flush this cache as things in it are never modified by us.
76 void FlushObjectInner(const std::shared_ptr<CachedBufferEntry>& object) override {}
77
78private: 78private:
79 OGLStreamBuffer stream_buffer; 79 OGLStreamBuffer stream_buffer;
80 80
diff --git a/src/video_core/renderer_opengl/gl_global_cache.h b/src/video_core/renderer_opengl/gl_global_cache.h
index 196e6e278..2d467a240 100644
--- a/src/video_core/renderer_opengl/gl_global_cache.h
+++ b/src/video_core/renderer_opengl/gl_global_cache.h
@@ -46,7 +46,7 @@ public:
46 /// Reloads the global region from guest memory 46 /// Reloads the global region from guest memory
47 void Reload(u32 size_); 47 void Reload(u32 size_);
48 48
49 void Flush() override; 49 void Flush();
50 50
51private: 51private:
52 VAddr cpu_addr{}; 52 VAddr cpu_addr{};
@@ -65,6 +65,11 @@ public:
65 GlobalRegion GetGlobalRegion(const GLShader::GlobalMemoryEntry& descriptor, 65 GlobalRegion GetGlobalRegion(const GLShader::GlobalMemoryEntry& descriptor,
66 Tegra::Engines::Maxwell3D::Regs::ShaderStage stage); 66 Tegra::Engines::Maxwell3D::Regs::ShaderStage stage);
67 67
68protected:
69 void FlushObjectInner(const GlobalRegion& object) override {
70 object->Flush();
71 }
72
68private: 73private:
69 GlobalRegion TryGetReservedGlobalRegion(CacheAddr addr, u32 size) const; 74 GlobalRegion TryGetReservedGlobalRegion(CacheAddr addr, u32 size) const;
70 GlobalRegion GetUncachedGlobalRegion(GPUVAddr addr, u8* host_ptr, u32 size); 75 GlobalRegion GetUncachedGlobalRegion(GPUVAddr addr, u8* host_ptr, u32 size);
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 3cc945235..dbd8049f5 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -261,8 +261,8 @@ DrawParameters RasterizerOpenGL::SetupDraw() {
261 // MakeQuadArray always generates u32 indexes 261 // MakeQuadArray always generates u32 indexes
262 params.index_format = GL_UNSIGNED_INT; 262 params.index_format = GL_UNSIGNED_INT;
263 params.count = (regs.vertex_buffer.count / 4) * 6; 263 params.count = (regs.vertex_buffer.count / 4) * 6;
264 params.index_buffer_offset = 264 params.index_buffer_offset = primitive_assembler.MakeQuadArray(
265 primitive_assembler.MakeQuadArray(regs.vertex_buffer.first, params.count); 265 regs.vertex_buffer.first, regs.vertex_buffer.count);
266 } 266 }
267 return params; 267 return params;
268 } 268 }
@@ -1135,7 +1135,9 @@ void RasterizerOpenGL::SyncTransformFeedback() {
1135 1135
1136void RasterizerOpenGL::SyncPointState() { 1136void RasterizerOpenGL::SyncPointState() {
1137 const auto& regs = system.GPU().Maxwell3D().regs; 1137 const auto& regs = system.GPU().Maxwell3D().regs;
1138 state.point.size = regs.point_size; 1138 // Limit the point size to 1 since nouveau sometimes sets a point size of 0 (and that's invalid
1139 // in OpenGL).
1140 state.point.size = std::max(1.0f, regs.point_size);
1139} 1141}
1140 1142
1141void RasterizerOpenGL::SyncPolygonOffset() { 1143void RasterizerOpenGL::SyncPolygonOffset() {
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index 5a25f5b37..a7681902e 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -628,9 +628,11 @@ CachedSurface::CachedSurface(const SurfaceParams& params)
628} 628}
629 629
630MICROPROFILE_DEFINE(OpenGL_SurfaceLoad, "OpenGL", "Surface Load", MP_RGB(128, 192, 64)); 630MICROPROFILE_DEFINE(OpenGL_SurfaceLoad, "OpenGL", "Surface Load", MP_RGB(128, 192, 64));
631void CachedSurface::LoadGLBuffer() { 631void CachedSurface::LoadGLBuffer(RasterizerTemporaryMemory& res_cache_tmp_mem) {
632 MICROPROFILE_SCOPE(OpenGL_SurfaceLoad); 632 MICROPROFILE_SCOPE(OpenGL_SurfaceLoad);
633 gl_buffer.resize(params.max_mip_level); 633 auto& gl_buffer = res_cache_tmp_mem.gl_buffer;
634 if (gl_buffer.size() < params.max_mip_level)
635 gl_buffer.resize(params.max_mip_level);
634 for (u32 i = 0; i < params.max_mip_level; i++) 636 for (u32 i = 0; i < params.max_mip_level; i++)
635 gl_buffer[i].resize(params.GetMipmapSizeGL(i)); 637 gl_buffer[i].resize(params.GetMipmapSizeGL(i));
636 if (params.is_tiled) { 638 if (params.is_tiled) {
@@ -671,13 +673,13 @@ void CachedSurface::LoadGLBuffer() {
671} 673}
672 674
673MICROPROFILE_DEFINE(OpenGL_SurfaceFlush, "OpenGL", "Surface Flush", MP_RGB(128, 192, 64)); 675MICROPROFILE_DEFINE(OpenGL_SurfaceFlush, "OpenGL", "Surface Flush", MP_RGB(128, 192, 64));
674void CachedSurface::FlushGLBuffer() { 676void CachedSurface::FlushGLBuffer(RasterizerTemporaryMemory& res_cache_tmp_mem) {
675 MICROPROFILE_SCOPE(OpenGL_SurfaceFlush); 677 MICROPROFILE_SCOPE(OpenGL_SurfaceFlush);
676 678
677 ASSERT_MSG(!IsPixelFormatASTC(params.pixel_format), "Unimplemented"); 679 ASSERT_MSG(!IsPixelFormatASTC(params.pixel_format), "Unimplemented");
678 680
681 auto& gl_buffer = res_cache_tmp_mem.gl_buffer;
679 // OpenGL temporary buffer needs to be big enough to store raw texture size 682 // OpenGL temporary buffer needs to be big enough to store raw texture size
680 gl_buffer.resize(1);
681 gl_buffer[0].resize(GetSizeInBytes()); 683 gl_buffer[0].resize(GetSizeInBytes());
682 684
683 const FormatTuple& tuple = GetFormatTuple(params.pixel_format, params.component_type); 685 const FormatTuple& tuple = GetFormatTuple(params.pixel_format, params.component_type);
@@ -713,10 +715,12 @@ void CachedSurface::FlushGLBuffer() {
713 } 715 }
714} 716}
715 717
716void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, 718void CachedSurface::UploadGLMipmapTexture(RasterizerTemporaryMemory& res_cache_tmp_mem, u32 mip_map,
717 GLuint draw_fb_handle) { 719 GLuint read_fb_handle, GLuint draw_fb_handle) {
718 const auto& rect{params.GetRect(mip_map)}; 720 const auto& rect{params.GetRect(mip_map)};
719 721
722 auto& gl_buffer = res_cache_tmp_mem.gl_buffer;
723
720 // Load data from memory to the surface 724 // Load data from memory to the surface
721 const auto x0 = static_cast<GLint>(rect.left); 725 const auto x0 = static_cast<GLint>(rect.left);
722 const auto y0 = static_cast<GLint>(rect.bottom); 726 const auto y0 = static_cast<GLint>(rect.bottom);
@@ -801,7 +805,6 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle,
801 tuple.type, &gl_buffer[mip_map][buffer_offset]); 805 tuple.type, &gl_buffer[mip_map][buffer_offset]);
802 break; 806 break;
803 case SurfaceTarget::TextureCubemap: { 807 case SurfaceTarget::TextureCubemap: {
804 std::size_t start = buffer_offset;
805 for (std::size_t face = 0; face < params.depth; ++face) { 808 for (std::size_t face = 0; face < params.depth; ++face) {
806 glTextureSubImage3D(texture.handle, mip_map, x0, y0, static_cast<GLint>(face), 809 glTextureSubImage3D(texture.handle, mip_map, x0, y0, static_cast<GLint>(face),
807 static_cast<GLsizei>(rect.GetWidth()), 810 static_cast<GLsizei>(rect.GetWidth()),
@@ -845,11 +848,12 @@ void CachedSurface::EnsureTextureDiscrepantView() {
845} 848}
846 849
847MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 192, 64)); 850MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 192, 64));
848void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle) { 851void CachedSurface::UploadGLTexture(RasterizerTemporaryMemory& res_cache_tmp_mem,
852 GLuint read_fb_handle, GLuint draw_fb_handle) {
849 MICROPROFILE_SCOPE(OpenGL_TextureUL); 853 MICROPROFILE_SCOPE(OpenGL_TextureUL);
850 854
851 for (u32 i = 0; i < params.max_mip_level; i++) 855 for (u32 i = 0; i < params.max_mip_level; i++)
852 UploadGLMipmapTexture(i, read_fb_handle, draw_fb_handle); 856 UploadGLMipmapTexture(res_cache_tmp_mem, i, read_fb_handle, draw_fb_handle);
853} 857}
854 858
855void CachedSurface::UpdateSwizzle(Tegra::Texture::SwizzleSource swizzle_x, 859void CachedSurface::UpdateSwizzle(Tegra::Texture::SwizzleSource swizzle_x,
@@ -929,8 +933,8 @@ Surface RasterizerCacheOpenGL::GetColorBufferSurface(std::size_t index, bool pre
929} 933}
930 934
931void RasterizerCacheOpenGL::LoadSurface(const Surface& surface) { 935void RasterizerCacheOpenGL::LoadSurface(const Surface& surface) {
932 surface->LoadGLBuffer(); 936 surface->LoadGLBuffer(temporal_memory);
933 surface->UploadGLTexture(read_framebuffer.handle, draw_framebuffer.handle); 937 surface->UploadGLTexture(temporal_memory, read_framebuffer.handle, draw_framebuffer.handle);
934 surface->MarkAsModified(false, *this); 938 surface->MarkAsModified(false, *this);
935 surface->MarkForReload(false); 939 surface->MarkForReload(false);
936} 940}
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index db280dbb3..6263ef3e7 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -355,6 +355,12 @@ namespace OpenGL {
355 355
356class RasterizerOpenGL; 356class RasterizerOpenGL;
357 357
358// This is used to store temporary big buffers,
359// instead of creating/destroying all the time
360struct RasterizerTemporaryMemory {
361 std::vector<std::vector<u8>> gl_buffer;
362};
363
358class CachedSurface final : public RasterizerCacheObject { 364class CachedSurface final : public RasterizerCacheObject {
359public: 365public:
360 explicit CachedSurface(const SurfaceParams& params); 366 explicit CachedSurface(const SurfaceParams& params);
@@ -371,10 +377,6 @@ public:
371 return memory_size; 377 return memory_size;
372 } 378 }
373 379
374 void Flush() override {
375 FlushGLBuffer();
376 }
377
378 const OGLTexture& Texture() const { 380 const OGLTexture& Texture() const {
379 return texture; 381 return texture;
380 } 382 }
@@ -397,11 +399,12 @@ public:
397 } 399 }
398 400
399 // Read/Write data in Switch memory to/from gl_buffer 401 // Read/Write data in Switch memory to/from gl_buffer
400 void LoadGLBuffer(); 402 void LoadGLBuffer(RasterizerTemporaryMemory& res_cache_tmp_mem);
401 void FlushGLBuffer(); 403 void FlushGLBuffer(RasterizerTemporaryMemory& res_cache_tmp_mem);
402 404
403 // Upload data in gl_buffer to this surface's texture 405 // Upload data in gl_buffer to this surface's texture
404 void UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle); 406 void UploadGLTexture(RasterizerTemporaryMemory& res_cache_tmp_mem, GLuint read_fb_handle,
407 GLuint draw_fb_handle);
405 408
406 void UpdateSwizzle(Tegra::Texture::SwizzleSource swizzle_x, 409 void UpdateSwizzle(Tegra::Texture::SwizzleSource swizzle_x,
407 Tegra::Texture::SwizzleSource swizzle_y, 410 Tegra::Texture::SwizzleSource swizzle_y,
@@ -429,13 +432,13 @@ public:
429 } 432 }
430 433
431private: 434private:
432 void UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, GLuint draw_fb_handle); 435 void UploadGLMipmapTexture(RasterizerTemporaryMemory& res_cache_tmp_mem, u32 mip_map,
436 GLuint read_fb_handle, GLuint draw_fb_handle);
433 437
434 void EnsureTextureDiscrepantView(); 438 void EnsureTextureDiscrepantView();
435 439
436 OGLTexture texture; 440 OGLTexture texture;
437 OGLTexture discrepant_view; 441 OGLTexture discrepant_view;
438 std::vector<std::vector<u8>> gl_buffer;
439 SurfaceParams params{}; 442 SurfaceParams params{};
440 GLenum gl_target{}; 443 GLenum gl_target{};
441 GLenum gl_internal_format{}; 444 GLenum gl_internal_format{};
@@ -473,6 +476,11 @@ public:
473 void SignalPreDrawCall(); 476 void SignalPreDrawCall();
474 void SignalPostDrawCall(); 477 void SignalPostDrawCall();
475 478
479protected:
480 void FlushObjectInner(const Surface& object) override {
481 object->FlushGLBuffer(temporal_memory);
482 }
483
476private: 484private:
477 void LoadSurface(const Surface& surface); 485 void LoadSurface(const Surface& surface);
478 Surface GetSurface(const SurfaceParams& params, bool preserve_contents = true); 486 Surface GetSurface(const SurfaceParams& params, bool preserve_contents = true);
@@ -519,6 +527,8 @@ private:
519 std::array<Surface, Maxwell::NumRenderTargets> current_color_buffers; 527 std::array<Surface, Maxwell::NumRenderTargets> current_color_buffers;
520 Surface last_depth_buffer; 528 Surface last_depth_buffer;
521 529
530 RasterizerTemporaryMemory temporal_memory;
531
522 using SurfaceIntervalCache = boost::icl::interval_map<CacheAddr, Surface>; 532 using SurfaceIntervalCache = boost::icl::interval_map<CacheAddr, Surface>;
523 using SurfaceInterval = typename SurfaceIntervalCache::interval_type; 533 using SurfaceInterval = typename SurfaceIntervalCache::interval_type;
524 534
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index b1c8f7c35..f700dc89a 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -345,7 +345,7 @@ ShaderDiskCacheUsage CachedShader::GetUsage(GLenum primitive_mode,
345 345
346ShaderCacheOpenGL::ShaderCacheOpenGL(RasterizerOpenGL& rasterizer, Core::System& system, 346ShaderCacheOpenGL::ShaderCacheOpenGL(RasterizerOpenGL& rasterizer, Core::System& system,
347 const Device& device) 347 const Device& device)
348 : RasterizerCache{rasterizer}, disk_cache{system}, device{device} {} 348 : RasterizerCache{rasterizer}, device{device}, disk_cache{system} {}
349 349
350void ShaderCacheOpenGL::LoadDiskCache(const std::atomic_bool& stop_loading, 350void ShaderCacheOpenGL::LoadDiskCache(const std::atomic_bool& stop_loading,
351 const VideoCore::DiskResourceLoadCallback& callback) { 351 const VideoCore::DiskResourceLoadCallback& callback) {
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h
index a332087f8..31b979987 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.h
+++ b/src/video_core/renderer_opengl/gl_shader_cache.h
@@ -57,9 +57,6 @@ public:
57 return shader_length; 57 return shader_length;
58 } 58 }
59 59
60 // We do not have to flush this cache as things in it are never modified by us.
61 void Flush() override {}
62
63 /// Gets the shader entries for the shader 60 /// Gets the shader entries for the shader
64 const GLShader::ShaderEntries& GetShaderEntries() const { 61 const GLShader::ShaderEntries& GetShaderEntries() const {
65 return entries; 62 return entries;
@@ -123,6 +120,10 @@ public:
123 /// Gets the current specified shader stage program 120 /// Gets the current specified shader stage program
124 Shader GetStageProgram(Maxwell::ShaderProgram program); 121 Shader GetStageProgram(Maxwell::ShaderProgram program);
125 122
123protected:
124 // We do not have to flush this cache as things in it are never modified by us.
125 void FlushObjectInner(const Shader& object) override {}
126
126private: 127private:
127 std::unordered_map<u64, UnspecializedShader> GenerateUnspecializedShaders( 128 std::unordered_map<u64, UnspecializedShader> GenerateUnspecializedShaders(
128 const std::atomic_bool& stop_loading, const VideoCore::DiskResourceLoadCallback& callback, 129 const std::atomic_bool& stop_loading, const VideoCore::DiskResourceLoadCallback& callback,
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index ef1a1995f..1a62795e1 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -871,17 +871,6 @@ private:
871 return {}; 871 return {};
872 } 872 }
873 873
874 std::string Composite(Operation operation) {
875 std::string value = "vec4(";
876 for (std::size_t i = 0; i < 4; ++i) {
877 value += Visit(operation[i]);
878 if (i < 3)
879 value += ", ";
880 }
881 value += ')';
882 return value;
883 }
884
885 template <Type type> 874 template <Type type>
886 std::string Add(Operation operation) { 875 std::string Add(Operation operation) {
887 return GenerateBinaryInfix(operation, "+", type, type, type); 876 return GenerateBinaryInfix(operation, "+", type, type, type);
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp
index 6abf948f8..7ab0b4553 100644
--- a/src/video_core/renderer_opengl/gl_shader_gen.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp
@@ -33,14 +33,14 @@ layout (std140, binding = EMULATION_UBO_BINDING) uniform vs_config {
33}; 33};
34 34
35)"; 35)";
36 ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET); 36 const ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET);
37 ProgramResult program = 37 ProgramResult program =
38 Decompile(device, program_ir, Maxwell3D::Regs::ShaderStage::Vertex, "vertex"); 38 Decompile(device, program_ir, Maxwell3D::Regs::ShaderStage::Vertex, "vertex");
39 39
40 out += program.first; 40 out += program.first;
41 41
42 if (setup.IsDualProgram()) { 42 if (setup.IsDualProgram()) {
43 ShaderIR program_ir_b(setup.program.code_b, PROGRAM_OFFSET); 43 const ShaderIR program_ir_b(setup.program.code_b, PROGRAM_OFFSET);
44 ProgramResult program_b = 44 ProgramResult program_b =
45 Decompile(device, program_ir_b, Maxwell3D::Regs::ShaderStage::Vertex, "vertex_b"); 45 Decompile(device, program_ir_b, Maxwell3D::Regs::ShaderStage::Vertex, "vertex_b");
46 46
@@ -76,7 +76,7 @@ void main() {
76 } 76 }
77})"; 77})";
78 78
79 return {out, program.second}; 79 return {std::move(out), std::move(program.second)};
80} 80}
81 81
82ProgramResult GenerateGeometryShader(const Device& device, const ShaderSetup& setup) { 82ProgramResult GenerateGeometryShader(const Device& device, const ShaderSetup& setup) {
@@ -97,7 +97,7 @@ layout (std140, binding = EMULATION_UBO_BINDING) uniform gs_config {
97}; 97};
98 98
99)"; 99)";
100 ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET); 100 const ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET);
101 ProgramResult program = 101 ProgramResult program =
102 Decompile(device, program_ir, Maxwell3D::Regs::ShaderStage::Geometry, "geometry"); 102 Decompile(device, program_ir, Maxwell3D::Regs::ShaderStage::Geometry, "geometry");
103 out += program.first; 103 out += program.first;
@@ -107,7 +107,7 @@ void main() {
107 execute_geometry(); 107 execute_geometry();
108};)"; 108};)";
109 109
110 return {out, program.second}; 110 return {std::move(out), std::move(program.second)};
111} 111}
112 112
113ProgramResult GenerateFragmentShader(const Device& device, const ShaderSetup& setup) { 113ProgramResult GenerateFragmentShader(const Device& device, const ShaderSetup& setup) {
@@ -160,7 +160,7 @@ bool AlphaFunc(in float value) {
160} 160}
161 161
162)"; 162)";
163 ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET); 163 const ShaderIR program_ir(setup.program.code, PROGRAM_OFFSET);
164 ProgramResult program = 164 ProgramResult program =
165 Decompile(device, program_ir, Maxwell3D::Regs::ShaderStage::Fragment, "fragment"); 165 Decompile(device, program_ir, Maxwell3D::Regs::ShaderStage::Fragment, "fragment");
166 166
@@ -172,7 +172,7 @@ void main() {
172} 172}
173 173
174)"; 174)";
175 return {out, program.second}; 175 return {std::move(out), std::move(program.second)};
176} 176}
177 177
178} // namespace OpenGL::GLShader 178} // namespace OpenGL::GLShader
diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h
index 95b773135..ed7b5cff0 100644
--- a/src/video_core/renderer_opengl/maxwell_to_gl.h
+++ b/src/video_core/renderer_opengl/maxwell_to_gl.h
@@ -126,6 +126,8 @@ inline GLenum PrimitiveTopology(Maxwell::PrimitiveTopology topology) {
126 return GL_TRIANGLES; 126 return GL_TRIANGLES;
127 case Maxwell::PrimitiveTopology::TriangleStrip: 127 case Maxwell::PrimitiveTopology::TriangleStrip:
128 return GL_TRIANGLE_STRIP; 128 return GL_TRIANGLE_STRIP;
129 case Maxwell::PrimitiveTopology::TriangleFan:
130 return GL_TRIANGLE_FAN;
129 default: 131 default:
130 LOG_CRITICAL(Render_OpenGL, "Unimplemented topology={}", static_cast<u32>(topology)); 132 LOG_CRITICAL(Render_OpenGL, "Unimplemented topology={}", static_cast<u32>(topology));
131 UNREACHABLE(); 133 UNREACHABLE();
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h
index 08b786aad..3edf460df 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.h
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h
@@ -49,9 +49,6 @@ public:
49 return alignment; 49 return alignment;
50 } 50 }
51 51
52 // We do not have to flush this cache as things in it are never modified by us.
53 void Flush() override {}
54
55private: 52private:
56 VAddr cpu_addr{}; 53 VAddr cpu_addr{};
57 std::size_t size{}; 54 std::size_t size{};
@@ -87,6 +84,10 @@ public:
87 return buffer_handle; 84 return buffer_handle;
88 } 85 }
89 86
87protected:
88 // We do not have to flush this cache as things in it are never modified by us.
89 void FlushObjectInner(const std::shared_ptr<CachedBufferEntry>& object) override {}
90
90private: 91private:
91 void AlignBuffer(std::size_t alignment); 92 void AlignBuffer(std::size_t alignment);
92 93
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
index 23d9b10db..a11000f6b 100644
--- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
+++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
@@ -315,7 +315,6 @@ private:
315 constexpr std::array<const char*, INTERNAL_FLAGS_COUNT> names = {"zero", "sign", "carry", 315 constexpr std::array<const char*, INTERNAL_FLAGS_COUNT> names = {"zero", "sign", "carry",
316 "overflow"}; 316 "overflow"};
317 for (std::size_t flag = 0; flag < INTERNAL_FLAGS_COUNT; ++flag) { 317 for (std::size_t flag = 0; flag < INTERNAL_FLAGS_COUNT; ++flag) {
318 const auto flag_code = static_cast<InternalFlag>(flag);
319 const Id id = OpVariable(t_prv_bool, spv::StorageClass::Private, v_false); 318 const Id id = OpVariable(t_prv_bool, spv::StorageClass::Private, v_false);
320 internal_flags[flag] = AddGlobalVariable(Name(id, names[flag])); 319 internal_flags[flag] = AddGlobalVariable(Name(id, names[flag]));
321 } 320 }
diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp
index 8b574d4e5..5b033126d 100644
--- a/src/video_core/shader/decode/texture.cpp
+++ b/src/video_core/shader/decode/texture.cpp
@@ -540,7 +540,6 @@ Node4 ShaderIR::GetTexsCode(Instruction instr, TextureType texture_type,
540Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool depth_compare, 540Node4 ShaderIR::GetTld4Code(Instruction instr, TextureType texture_type, bool depth_compare,
541 bool is_array, bool is_aoffi) { 541 bool is_array, bool is_aoffi) {
542 const std::size_t coord_count = GetCoordCount(texture_type); 542 const std::size_t coord_count = GetCoordCount(texture_type);
543 const std::size_t total_coord_count = coord_count + (is_array ? 1 : 0);
544 543
545 // If enabled arrays index is always stored in the gpr8 field 544 // If enabled arrays index is always stored in the gpr8 field
546 const u64 array_register = instr.gpr8.Value(); 545 const u64 array_register = instr.gpr8.Value();
diff --git a/src/video_core/textures/astc.cpp b/src/video_core/textures/astc.cpp
index eafb6b73a..a9b8f69af 100644
--- a/src/video_core/textures/astc.cpp
+++ b/src/video_core/textures/astc.cpp
@@ -25,8 +25,8 @@
25 25
26class InputBitStream { 26class InputBitStream {
27public: 27public:
28 explicit InputBitStream(const unsigned char* ptr, int nBits = 0, int start_offset = 0) 28 explicit InputBitStream(const unsigned char* ptr, int start_offset = 0)
29 : m_NumBits(nBits), m_CurByte(ptr), m_NextBit(start_offset % 8) {} 29 : m_CurByte(ptr), m_NextBit(start_offset % 8) {}
30 30
31 ~InputBitStream() = default; 31 ~InputBitStream() = default;
32 32
@@ -55,12 +55,9 @@ public:
55 } 55 }
56 56
57private: 57private:
58 const int m_NumBits;
59 const unsigned char* m_CurByte; 58 const unsigned char* m_CurByte;
60 int m_NextBit = 0; 59 int m_NextBit = 0;
61 int m_BitsRead = 0; 60 int m_BitsRead = 0;
62
63 bool done = false;
64}; 61};
65 62
66class OutputBitStream { 63class OutputBitStream {
@@ -114,7 +111,6 @@ private:
114 const int m_NumBits; 111 const int m_NumBits;
115 unsigned char* m_CurByte; 112 unsigned char* m_CurByte;
116 int m_NextBit = 0; 113 int m_NextBit = 0;
117 int m_BitsRead = 0;
118 114
119 bool done = false; 115 bool done = false;
120}; 116};
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index 5138bd9a3..7e883991a 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -82,8 +82,6 @@ add_executable(yuzu
82 util/limitable_input_dialog.h 82 util/limitable_input_dialog.h
83 util/sequence_dialog/sequence_dialog.cpp 83 util/sequence_dialog/sequence_dialog.cpp
84 util/sequence_dialog/sequence_dialog.h 84 util/sequence_dialog/sequence_dialog.h
85 util/spinbox.cpp
86 util/spinbox.h
87 util/util.cpp 85 util/util.cpp
88 util/util.h 86 util/util.h
89 compatdb.cpp 87 compatdb.cpp
diff --git a/src/yuzu/about_dialog.cpp b/src/yuzu/about_dialog.cpp
index 3efa65a38..d39b3f07a 100644
--- a/src/yuzu/about_dialog.cpp
+++ b/src/yuzu/about_dialog.cpp
@@ -9,10 +9,10 @@
9 9
10AboutDialog::AboutDialog(QWidget* parent) : QDialog(parent), ui(new Ui::AboutDialog) { 10AboutDialog::AboutDialog(QWidget* parent) : QDialog(parent), ui(new Ui::AboutDialog) {
11 ui->setupUi(this); 11 ui->setupUi(this);
12 ui->labelLogo->setPixmap(QIcon::fromTheme("yuzu").pixmap(200)); 12 ui->labelLogo->setPixmap(QIcon::fromTheme(QStringLiteral("yuzu")).pixmap(200));
13 ui->labelBuildInfo->setText( 13 ui->labelBuildInfo->setText(ui->labelBuildInfo->text().arg(
14 ui->labelBuildInfo->text().arg(Common::g_build_fullname, Common::g_scm_branch, 14 QString::fromUtf8(Common::g_build_fullname), QString::fromUtf8(Common::g_scm_branch),
15 Common::g_scm_desc, QString(Common::g_build_date).left(10))); 15 QString::fromUtf8(Common::g_scm_desc), QString::fromUtf8(Common::g_build_date).left(10)));
16} 16}
17 17
18AboutDialog::~AboutDialog() = default; 18AboutDialog::~AboutDialog() = default;
diff --git a/src/yuzu/applets/error.cpp b/src/yuzu/applets/error.cpp
index 1fb2fe277..106dde9e2 100644
--- a/src/yuzu/applets/error.cpp
+++ b/src/yuzu/applets/error.cpp
@@ -54,6 +54,6 @@ void QtErrorDisplay::ShowCustomErrorText(ResultCode error, std::string dialog_te
54 54
55void QtErrorDisplay::MainWindowFinishedError() { 55void QtErrorDisplay::MainWindowFinishedError() {
56 // Acquire the HLE mutex 56 // Acquire the HLE mutex
57 std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock); 57 std::lock_guard lock{HLE::g_hle_lock};
58 callback(); 58 callback();
59} 59}
diff --git a/src/yuzu/applets/profile_select.cpp b/src/yuzu/applets/profile_select.cpp
index 743b24d76..7fbc9deeb 100644
--- a/src/yuzu/applets/profile_select.cpp
+++ b/src/yuzu/applets/profile_select.cpp
@@ -84,10 +84,10 @@ QtProfileSelectionDialog::QtProfileSelectionDialog(QWidget* parent)
84 tree_view->setContextMenuPolicy(Qt::NoContextMenu); 84 tree_view->setContextMenuPolicy(Qt::NoContextMenu);
85 85
86 item_model->insertColumns(0, 1); 86 item_model->insertColumns(0, 1);
87 item_model->setHeaderData(0, Qt::Horizontal, "Users"); 87 item_model->setHeaderData(0, Qt::Horizontal, tr("Users"));
88 88
89 // We must register all custom types with the Qt Automoc system so that we are able to use it 89 // We must register all custom types with the Qt Automoc system so that we are able to use it
90 // with signals/slots. In this case, QList falls under the umbrells of custom types. 90 // with signals/slots. In this case, QList falls under the umbrella of custom types.
91 qRegisterMetaType<QList<QStandardItem*>>("QList<QStandardItem*>"); 91 qRegisterMetaType<QList<QStandardItem*>>("QList<QStandardItem*>");
92 92
93 layout->setContentsMargins(0, 0, 0, 0); 93 layout->setContentsMargins(0, 0, 0, 0);
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 5c98636c5..810954b36 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -379,6 +379,7 @@ void GRenderWindow::InitRenderTarget() {
379 fmt.setVersion(4, 3); 379 fmt.setVersion(4, 3);
380 if (Settings::values.use_compatibility_profile) { 380 if (Settings::values.use_compatibility_profile) {
381 fmt.setProfile(QSurfaceFormat::CompatibilityProfile); 381 fmt.setProfile(QSurfaceFormat::CompatibilityProfile);
382 fmt.setOption(QSurfaceFormat::FormatOption::DeprecatedFunctions);
382 } else { 383 } else {
383 fmt.setProfile(QSurfaceFormat::CoreProfile); 384 fmt.setProfile(QSurfaceFormat::CoreProfile);
384 } 385 }
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp
index c299c0b5b..08ea41b0f 100644
--- a/src/yuzu/configuration/configure_graphics.cpp
+++ b/src/yuzu/configuration/configure_graphics.cpp
@@ -69,16 +69,20 @@ ConfigureGraphics::ConfigureGraphics(QWidget* parent)
69ConfigureGraphics::~ConfigureGraphics() = default; 69ConfigureGraphics::~ConfigureGraphics() = default;
70 70
71void ConfigureGraphics::setConfiguration() { 71void ConfigureGraphics::setConfiguration() {
72 const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn();
73
72 ui->resolution_factor_combobox->setCurrentIndex( 74 ui->resolution_factor_combobox->setCurrentIndex(
73 static_cast<int>(FromResolutionFactor(Settings::values.resolution_factor))); 75 static_cast<int>(FromResolutionFactor(Settings::values.resolution_factor)));
74 ui->toggle_frame_limit->setChecked(Settings::values.use_frame_limit); 76 ui->toggle_frame_limit->setChecked(Settings::values.use_frame_limit);
75 ui->frame_limit->setValue(Settings::values.frame_limit); 77 ui->frame_limit->setValue(Settings::values.frame_limit);
78 ui->use_compatibility_profile->setEnabled(runtime_lock);
76 ui->use_compatibility_profile->setChecked(Settings::values.use_compatibility_profile); 79 ui->use_compatibility_profile->setChecked(Settings::values.use_compatibility_profile);
80 ui->use_disk_shader_cache->setEnabled(runtime_lock);
77 ui->use_disk_shader_cache->setChecked(Settings::values.use_disk_shader_cache); 81 ui->use_disk_shader_cache->setChecked(Settings::values.use_disk_shader_cache);
78 ui->use_accurate_gpu_emulation->setChecked(Settings::values.use_accurate_gpu_emulation); 82 ui->use_accurate_gpu_emulation->setChecked(Settings::values.use_accurate_gpu_emulation);
79 ui->use_asynchronous_gpu_emulation->setEnabled(!Core::System::GetInstance().IsPoweredOn()); 83 ui->use_asynchronous_gpu_emulation->setEnabled(runtime_lock);
80 ui->use_asynchronous_gpu_emulation->setChecked(Settings::values.use_asynchronous_gpu_emulation); 84 ui->use_asynchronous_gpu_emulation->setChecked(Settings::values.use_asynchronous_gpu_emulation);
81 ui->force_30fps_mode->setEnabled(!Core::System::GetInstance().IsPoweredOn()); 85 ui->force_30fps_mode->setEnabled(runtime_lock);
82 ui->force_30fps_mode->setChecked(Settings::values.force_30fps_mode); 86 ui->force_30fps_mode->setChecked(Settings::values.force_30fps_mode);
83 UpdateBackgroundColorButton(QColor::fromRgbF(Settings::values.bg_red, Settings::values.bg_green, 87 UpdateBackgroundColorButton(QColor::fromRgbF(Settings::values.bg_red, Settings::values.bg_green,
84 Settings::values.bg_blue)); 88 Settings::values.bg_blue));
diff --git a/src/yuzu/debugger/graphics/graphics_breakpoints.cpp b/src/yuzu/debugger/graphics/graphics_breakpoints.cpp
index 67ed0ba6d..1c80082a4 100644
--- a/src/yuzu/debugger/graphics/graphics_breakpoints.cpp
+++ b/src/yuzu/debugger/graphics/graphics_breakpoints.cpp
@@ -135,7 +135,7 @@ GraphicsBreakPointsWidget::GraphicsBreakPointsWidget(
135 std::shared_ptr<Tegra::DebugContext> debug_context, QWidget* parent) 135 std::shared_ptr<Tegra::DebugContext> debug_context, QWidget* parent)
136 : QDockWidget(tr("Maxwell Breakpoints"), parent), Tegra::DebugContext::BreakPointObserver( 136 : QDockWidget(tr("Maxwell Breakpoints"), parent), Tegra::DebugContext::BreakPointObserver(
137 debug_context) { 137 debug_context) {
138 setObjectName("TegraBreakPointsWidget"); 138 setObjectName(QStringLiteral("TegraBreakPointsWidget"));
139 139
140 status_text = new QLabel(tr("Emulation running")); 140 status_text = new QLabel(tr("Emulation running"));
141 resume_button = new QPushButton(tr("Resume")); 141 resume_button = new QPushButton(tr("Resume"));
diff --git a/src/yuzu/debugger/profiler.cpp b/src/yuzu/debugger/profiler.cpp
index 86e03e46d..f594ef076 100644
--- a/src/yuzu/debugger/profiler.cpp
+++ b/src/yuzu/debugger/profiler.cpp
@@ -47,7 +47,7 @@ private:
47#endif 47#endif
48 48
49MicroProfileDialog::MicroProfileDialog(QWidget* parent) : QWidget(parent, Qt::Dialog) { 49MicroProfileDialog::MicroProfileDialog(QWidget* parent) : QWidget(parent, Qt::Dialog) {
50 setObjectName("MicroProfile"); 50 setObjectName(QStringLiteral("MicroProfile"));
51 setWindowTitle(tr("MicroProfile")); 51 setWindowTitle(tr("MicroProfile"));
52 resize(1000, 600); 52 resize(1000, 600);
53 // Remove the "?" button from the titlebar and enable the maximize button 53 // Remove the "?" button from the titlebar and enable the maximize button
@@ -191,7 +191,7 @@ void MicroProfileDrawText(int x, int y, u32 hex_color, const char* text, u32 tex
191 for (u32 i = 0; i < text_length; ++i) { 191 for (u32 i = 0; i < text_length; ++i) {
192 // Position the text baseline 1 pixel above the bottom of the text cell, this gives nice 192 // Position the text baseline 1 pixel above the bottom of the text cell, this gives nice
193 // vertical alignment of text for a wide range of tested fonts. 193 // vertical alignment of text for a wide range of tested fonts.
194 mp_painter->drawText(x, y + MICROPROFILE_TEXT_HEIGHT - 2, QChar(text[i])); 194 mp_painter->drawText(x, y + MICROPROFILE_TEXT_HEIGHT - 2, QString{QLatin1Char{text[i]}});
195 x += MICROPROFILE_TEXT_WIDTH + 1; 195 x += MICROPROFILE_TEXT_WIDTH + 1;
196 } 196 }
197} 197}
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index 85b095688..cd8180f8b 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -91,19 +91,19 @@ WaitTreeMutexInfo::WaitTreeMutexInfo(VAddr mutex_address, const Kernel::HandleTa
91WaitTreeMutexInfo::~WaitTreeMutexInfo() = default; 91WaitTreeMutexInfo::~WaitTreeMutexInfo() = default;
92 92
93QString WaitTreeMutexInfo::GetText() const { 93QString WaitTreeMutexInfo::GetText() const {
94 return tr("waiting for mutex 0x%1").arg(mutex_address, 16, 16, QLatin1Char('0')); 94 return tr("waiting for mutex 0x%1").arg(mutex_address, 16, 16, QLatin1Char{'0'});
95} 95}
96 96
97std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeMutexInfo::GetChildren() const { 97std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeMutexInfo::GetChildren() const {
98 std::vector<std::unique_ptr<WaitTreeItem>> list; 98 const bool has_waiters = (mutex_value & Kernel::Mutex::MutexHasWaitersFlag) != 0;
99
100 bool has_waiters = (mutex_value & Kernel::Mutex::MutexHasWaitersFlag) != 0;
101 99
100 std::vector<std::unique_ptr<WaitTreeItem>> list;
102 list.push_back(std::make_unique<WaitTreeText>(tr("has waiters: %1").arg(has_waiters))); 101 list.push_back(std::make_unique<WaitTreeText>(tr("has waiters: %1").arg(has_waiters)));
103 list.push_back(std::make_unique<WaitTreeText>( 102 list.push_back(std::make_unique<WaitTreeText>(
104 tr("owner handle: 0x%1").arg(owner_handle, 8, 16, QLatin1Char('0')))); 103 tr("owner handle: 0x%1").arg(owner_handle, 8, 16, QLatin1Char{'0'})));
105 if (owner != nullptr) 104 if (owner != nullptr) {
106 list.push_back(std::make_unique<WaitTreeThread>(*owner)); 105 list.push_back(std::make_unique<WaitTreeThread>(*owner));
106 }
107 return list; 107 return list;
108} 108}
109 109
@@ -121,11 +121,14 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeCallstack::GetChildren() cons
121 u64 base_pointer = thread.GetContext().cpu_registers[BaseRegister]; 121 u64 base_pointer = thread.GetContext().cpu_registers[BaseRegister];
122 122
123 while (base_pointer != 0) { 123 while (base_pointer != 0) {
124 u64 lr = Memory::Read64(base_pointer + sizeof(u64)); 124 const u64 lr = Memory::Read64(base_pointer + sizeof(u64));
125 if (lr == 0) 125 if (lr == 0) {
126 break; 126 break;
127 list.push_back( 127 }
128 std::make_unique<WaitTreeText>(tr("0x%1").arg(lr - sizeof(u32), 16, 16, QChar('0')))); 128
129 list.push_back(std::make_unique<WaitTreeText>(
130 tr("0x%1").arg(lr - sizeof(u32), 16, 16, QLatin1Char{'0'})));
131
129 base_pointer = Memory::Read64(base_pointer); 132 base_pointer = Memory::Read64(base_pointer);
130 } 133 }
131 134
@@ -174,10 +177,10 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeWaitObject::GetChildren() con
174 177
175QString WaitTreeWaitObject::GetResetTypeQString(Kernel::ResetType reset_type) { 178QString WaitTreeWaitObject::GetResetTypeQString(Kernel::ResetType reset_type) {
176 switch (reset_type) { 179 switch (reset_type) {
177 case Kernel::ResetType::OneShot: 180 case Kernel::ResetType::Automatic:
178 return tr("one shot"); 181 return tr("automatic reset");
179 case Kernel::ResetType::Sticky: 182 case Kernel::ResetType::Manual:
180 return tr("sticky"); 183 return tr("manual reset");
181 } 184 }
182 UNREACHABLE(); 185 UNREACHABLE();
183 return {}; 186 return {};
@@ -249,9 +252,9 @@ QString WaitTreeThread::GetText() const {
249 252
250 const auto& context = thread.GetContext(); 253 const auto& context = thread.GetContext();
251 const QString pc_info = tr(" PC = 0x%1 LR = 0x%2") 254 const QString pc_info = tr(" PC = 0x%1 LR = 0x%2")
252 .arg(context.pc, 8, 16, QLatin1Char('0')) 255 .arg(context.pc, 8, 16, QLatin1Char{'0'})
253 .arg(context.cpu_registers[30], 8, 16, QLatin1Char('0')); 256 .arg(context.cpu_registers[30], 8, 16, QLatin1Char{'0'});
254 return WaitTreeWaitObject::GetText() + pc_info + " (" + status + ") "; 257 return QStringLiteral("%1%2 (%3) ").arg(WaitTreeWaitObject::GetText(), pc_info, status);
255} 258}
256 259
257QColor WaitTreeThread::GetColor() const { 260QColor WaitTreeThread::GetColor() const {
@@ -424,7 +427,7 @@ void WaitTreeModel::InitItems() {
424} 427}
425 428
426WaitTreeWidget::WaitTreeWidget(QWidget* parent) : QDockWidget(tr("Wait Tree"), parent) { 429WaitTreeWidget::WaitTreeWidget(QWidget* parent) : QDockWidget(tr("Wait Tree"), parent) {
427 setObjectName("WaitTreeWidget"); 430 setObjectName(QStringLiteral("WaitTreeWidget"));
428 view = new QTreeView(this); 431 view = new QTreeView(this);
429 view->setHeaderHidden(true); 432 view->setHeaderHidden(true);
430 setWidget(view); 433 setWidget(view);
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index e33e3aaaf..a59abf6e8 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -198,11 +198,11 @@ GMainWindow::GMainWindow()
198 198
199 ConnectMenuEvents(); 199 ConnectMenuEvents();
200 ConnectWidgetEvents(); 200 ConnectWidgetEvents();
201
201 LOG_INFO(Frontend, "yuzu Version: {} | {}-{}", Common::g_build_fullname, Common::g_scm_branch, 202 LOG_INFO(Frontend, "yuzu Version: {} | {}-{}", Common::g_build_fullname, Common::g_scm_branch,
202 Common::g_scm_desc); 203 Common::g_scm_desc);
204 UpdateWindowTitle();
203 205
204 setWindowTitle(QString("yuzu %1| %2-%3")
205 .arg(Common::g_build_fullname, Common::g_scm_branch, Common::g_scm_desc));
206 show(); 206 show();
207 207
208 Core::System::GetInstance().SetContentProvider( 208 Core::System::GetInstance().SetContentProvider(
@@ -936,9 +936,7 @@ void GMainWindow::BootGame(const QString& filename) {
936 title_name = FileUtil::GetFilename(filename.toStdString()); 936 title_name = FileUtil::GetFilename(filename.toStdString());
937 } 937 }
938 938
939 setWindowTitle(QString("yuzu %1| %4 | %2-%3") 939 UpdateWindowTitle(QString::fromStdString(title_name));
940 .arg(Common::g_build_fullname, Common::g_scm_branch, Common::g_scm_desc,
941 QString::fromStdString(title_name)));
942 940
943 loading_screen->Prepare(Core::System::GetInstance().GetAppLoader()); 941 loading_screen->Prepare(Core::System::GetInstance().GetAppLoader());
944 loading_screen->show(); 942 loading_screen->show();
@@ -979,8 +977,8 @@ void GMainWindow::ShutdownGame() {
979 loading_screen->Clear(); 977 loading_screen->Clear();
980 game_list->show(); 978 game_list->show();
981 game_list->setFilterFocus(); 979 game_list->setFilterFocus();
982 setWindowTitle(QString("yuzu %1| %2-%3") 980
983 .arg(Common::g_build_fullname, Common::g_scm_branch, Common::g_scm_desc)); 981 UpdateWindowTitle();
984 982
985 // Disable status bar updates 983 // Disable status bar updates
986 status_bar_update_timer.stop(); 984 status_bar_update_timer.stop();
@@ -1767,6 +1765,19 @@ void GMainWindow::OnCaptureScreenshot() {
1767 OnStartGame(); 1765 OnStartGame();
1768} 1766}
1769 1767
1768void GMainWindow::UpdateWindowTitle(const QString& title_name) {
1769 const QString full_name = QString::fromUtf8(Common::g_build_fullname);
1770 const QString branch_name = QString::fromUtf8(Common::g_scm_branch);
1771 const QString description = QString::fromUtf8(Common::g_scm_desc);
1772
1773 if (title_name.isEmpty()) {
1774 setWindowTitle(QStringLiteral("yuzu %1| %2-%3").arg(full_name, branch_name, description));
1775 } else {
1776 setWindowTitle(QStringLiteral("yuzu %1| %4 | %2-%3")
1777 .arg(full_name, branch_name, description, title_name));
1778 }
1779}
1780
1770void GMainWindow::UpdateStatusBar() { 1781void GMainWindow::UpdateStatusBar() {
1771 if (emu_thread == nullptr) { 1782 if (emu_thread == nullptr) {
1772 status_bar_update_timer.stop(); 1783 status_bar_update_timer.stop();
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index fb2a193cb..7bf82e665 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -209,6 +209,7 @@ private slots:
209 209
210private: 210private:
211 std::optional<u64> SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id); 211 std::optional<u64> SelectRomFSDumpTarget(const FileSys::ContentProvider&, u64 program_id);
212 void UpdateWindowTitle(const QString& title_name = {});
212 void UpdateStatusBar(); 213 void UpdateStatusBar();
213 214
214 Ui::MainWindow ui; 215 Ui::MainWindow ui;
diff --git a/src/yuzu/util/spinbox.cpp b/src/yuzu/util/spinbox.cpp
deleted file mode 100644
index 14ef1e884..000000000
--- a/src/yuzu/util/spinbox.cpp
+++ /dev/null
@@ -1,278 +0,0 @@
1// Licensed under GPLv2 or any later version
2// Refer to the license.txt file included.
3
4// Copyright 2014 Tony Wasserka
5// All rights reserved.
6//
7// Redistribution and use in source and binary forms, with or without
8// modification, are permitted provided that the following conditions are met:
9//
10// * Redistributions of source code must retain the above copyright
11// notice, this list of conditions and the following disclaimer.
12// * Redistributions in binary form must reproduce the above copyright
13// notice, this list of conditions and the following disclaimer in the
14// documentation and/or other materials provided with the distribution.
15// * Neither the name of the owner nor the names of its contributors may
16// be used to endorse or promote products derived from this software
17// without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31#include <cstdlib>
32#include <QLineEdit>
33#include <QRegExpValidator>
34#include "common/assert.h"
35#include "yuzu/util/spinbox.h"
36
37CSpinBox::CSpinBox(QWidget* parent)
38 : QAbstractSpinBox(parent), min_value(-100), max_value(100), value(0), base(10), num_digits(0) {
39 // TODO: Might be nice to not immediately call the slot.
40 // Think of an address that is being replaced by a different one, in which case a lot
41 // invalid intermediate addresses would be read from during editing.
42 connect(lineEdit(), &QLineEdit::textEdited, this, &CSpinBox::OnEditingFinished);
43
44 UpdateText();
45}
46
47void CSpinBox::SetValue(qint64 val) {
48 auto old_value = value;
49 value = std::max(std::min(val, max_value), min_value);
50
51 if (old_value != value) {
52 UpdateText();
53 emit ValueChanged(value);
54 }
55}
56
57void CSpinBox::SetRange(qint64 min, qint64 max) {
58 min_value = min;
59 max_value = max;
60
61 SetValue(value);
62 UpdateText();
63}
64
65void CSpinBox::stepBy(int steps) {
66 auto new_value = value;
67 // Scale number of steps by the currently selected digit
68 // TODO: Move this code elsewhere and enable it.
69 // TODO: Support for num_digits==0, too
70 // TODO: Support base!=16, too
71 // TODO: Make the cursor not jump back to the end of the line...
72 /*if (base == 16 && num_digits > 0) {
73 int digit = num_digits - (lineEdit()->cursorPosition() - prefix.length()) - 1;
74 digit = std::max(0, std::min(digit, num_digits - 1));
75 steps <<= digit * 4;
76 }*/
77
78 // Increment "new_value" by "steps", and perform annoying overflow checks, too.
79 if (steps < 0 && new_value + steps > new_value) {
80 new_value = std::numeric_limits<qint64>::min();
81 } else if (steps > 0 && new_value + steps < new_value) {
82 new_value = std::numeric_limits<qint64>::max();
83 } else {
84 new_value += steps;
85 }
86
87 SetValue(new_value);
88 UpdateText();
89}
90
91QAbstractSpinBox::StepEnabled CSpinBox::stepEnabled() const {
92 StepEnabled ret = StepNone;
93
94 if (value > min_value)
95 ret |= StepDownEnabled;
96
97 if (value < max_value)
98 ret |= StepUpEnabled;
99
100 return ret;
101}
102
103void CSpinBox::SetBase(int base) {
104 this->base = base;
105
106 UpdateText();
107}
108
109void CSpinBox::SetNumDigits(int num_digits) {
110 this->num_digits = num_digits;
111
112 UpdateText();
113}
114
115void CSpinBox::SetPrefix(const QString& prefix) {
116 this->prefix = prefix;
117
118 UpdateText();
119}
120
121void CSpinBox::SetSuffix(const QString& suffix) {
122 this->suffix = suffix;
123
124 UpdateText();
125}
126
127static QString StringToInputMask(const QString& input) {
128 QString mask = input;
129
130 // ... replace any special characters by their escaped counterparts ...
131 mask.replace("\\", "\\\\");
132 mask.replace("A", "\\A");
133 mask.replace("a", "\\a");
134 mask.replace("N", "\\N");
135 mask.replace("n", "\\n");
136 mask.replace("X", "\\X");
137 mask.replace("x", "\\x");
138 mask.replace("9", "\\9");
139 mask.replace("0", "\\0");
140 mask.replace("D", "\\D");
141 mask.replace("d", "\\d");
142 mask.replace("#", "\\#");
143 mask.replace("H", "\\H");
144 mask.replace("h", "\\h");
145 mask.replace("B", "\\B");
146 mask.replace("b", "\\b");
147 mask.replace(">", "\\>");
148 mask.replace("<", "\\<");
149 mask.replace("!", "\\!");
150
151 return mask;
152}
153
154void CSpinBox::UpdateText() {
155 // If a fixed number of digits is used, we put the line edit in insertion mode by setting an
156 // input mask.
157 QString mask;
158 if (num_digits != 0) {
159 mask += StringToInputMask(prefix);
160
161 // For base 10 and negative range, demand a single sign character
162 if (HasSign())
163 mask += "X"; // identified as "-" or "+" in the validator
164
165 // Uppercase digits greater than 9.
166 mask += ">";
167
168 // Match num_digits digits
169 // Digits irrelevant to the chosen number base are filtered in the validator
170 mask += QString("H").repeated(std::max(num_digits, 1));
171
172 // Switch off case conversion
173 mask += "!";
174
175 mask += StringToInputMask(suffix);
176 }
177 lineEdit()->setInputMask(mask);
178
179 // Set new text without changing the cursor position. This will cause the cursor to briefly
180 // appear at the end of the line and then to jump back to its original position. That's
181 // a bit ugly, but better than having setText() move the cursor permanently all the time.
182 int cursor_position = lineEdit()->cursorPosition();
183 lineEdit()->setText(TextFromValue());
184 lineEdit()->setCursorPosition(cursor_position);
185}
186
187QString CSpinBox::TextFromValue() {
188 return prefix + QString(HasSign() ? ((value < 0) ? "-" : "+") : "") +
189 QString("%1").arg(std::abs(value), num_digits, base, QLatin1Char('0')).toUpper() +
190 suffix;
191}
192
193qint64 CSpinBox::ValueFromText() {
194 unsigned strpos = prefix.length();
195
196 QString num_string = text().mid(strpos, text().length() - strpos - suffix.length());
197 return num_string.toLongLong(nullptr, base);
198}
199
200bool CSpinBox::HasSign() const {
201 return base == 10 && min_value < 0;
202}
203
204void CSpinBox::OnEditingFinished() {
205 // Only update for valid input
206 QString input = lineEdit()->text();
207 int pos = 0;
208 if (QValidator::Acceptable == validate(input, pos))
209 SetValue(ValueFromText());
210}
211
212QValidator::State CSpinBox::validate(QString& input, int& pos) const {
213 if (!prefix.isEmpty() && input.left(prefix.length()) != prefix)
214 return QValidator::Invalid;
215
216 int strpos = prefix.length();
217
218 // Empty "numbers" allowed as intermediate values
219 if (strpos >= input.length() - HasSign() - suffix.length())
220 return QValidator::Intermediate;
221
222 DEBUG_ASSERT(base <= 10 || base == 16);
223 QString regexp;
224
225 // Demand sign character for negative ranges
226 if (HasSign())
227 regexp += "[+\\-]";
228
229 // Match digits corresponding to the chosen number base.
230 regexp += QString("[0-%1").arg(std::min(base, 9));
231 if (base == 16) {
232 regexp += "a-fA-F";
233 }
234 regexp += "]";
235
236 // Specify number of digits
237 if (num_digits > 0) {
238 regexp += QString("{%1}").arg(num_digits);
239 } else {
240 regexp += "+";
241 }
242
243 // Match string
244 QRegExp num_regexp(regexp);
245 int num_pos = strpos;
246 QString sub_input = input.mid(strpos, input.length() - strpos - suffix.length());
247
248 if (!num_regexp.exactMatch(sub_input) && num_regexp.matchedLength() == 0)
249 return QValidator::Invalid;
250
251 sub_input = sub_input.left(num_regexp.matchedLength());
252 bool ok;
253 qint64 val = sub_input.toLongLong(&ok, base);
254
255 if (!ok)
256 return QValidator::Invalid;
257
258 // Outside boundaries => don't accept
259 if (val < min_value || val > max_value)
260 return QValidator::Invalid;
261
262 // Make sure we are actually at the end of this string...
263 strpos += num_regexp.matchedLength();
264
265 if (!suffix.isEmpty() && input.mid(strpos) != suffix) {
266 return QValidator::Invalid;
267 } else {
268 strpos += suffix.length();
269 }
270
271 if (strpos != input.length())
272 return QValidator::Invalid;
273
274 // At this point we can say for sure that the input is fine. Let's fix it up a bit though
275 input.replace(num_pos, sub_input.length(), sub_input.toUpper());
276
277 return QValidator::Acceptable;
278}
diff --git a/src/yuzu/util/spinbox.h b/src/yuzu/util/spinbox.h
deleted file mode 100644
index 2fa1db3a4..000000000
--- a/src/yuzu/util/spinbox.h
+++ /dev/null
@@ -1,86 +0,0 @@
1// Licensed under GPLv2 or any later version
2// Refer to the license.txt file included.
3
4// Copyright 2014 Tony Wasserka
5// All rights reserved.
6//
7// Redistribution and use in source and binary forms, with or without
8// modification, are permitted provided that the following conditions are met:
9//
10// * Redistributions of source code must retain the above copyright
11// notice, this list of conditions and the following disclaimer.
12// * Redistributions in binary form must reproduce the above copyright
13// notice, this list of conditions and the following disclaimer in the
14// documentation and/or other materials provided with the distribution.
15// * Neither the name of the owner nor the names of its contributors may
16// be used to endorse or promote products derived from this software
17// without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31#pragma once
32
33#include <QAbstractSpinBox>
34#include <QtGlobal>
35
36class QVariant;
37
38/**
39 * A custom spin box widget with enhanced functionality over Qt's QSpinBox
40 */
41class CSpinBox : public QAbstractSpinBox {
42 Q_OBJECT
43
44public:
45 explicit CSpinBox(QWidget* parent = nullptr);
46
47 void stepBy(int steps) override;
48 StepEnabled stepEnabled() const override;
49
50 void SetValue(qint64 val);
51
52 void SetRange(qint64 min, qint64 max);
53
54 void SetBase(int base);
55
56 void SetPrefix(const QString& prefix);
57 void SetSuffix(const QString& suffix);
58
59 void SetNumDigits(int num_digits);
60
61 QValidator::State validate(QString& input, int& pos) const override;
62
63signals:
64 void ValueChanged(qint64 val);
65
66private slots:
67 void OnEditingFinished();
68
69private:
70 void UpdateText();
71
72 bool HasSign() const;
73
74 QString TextFromValue();
75 qint64 ValueFromText();
76
77 qint64 min_value, max_value;
78
79 qint64 value;
80
81 QString prefix, suffix;
82
83 int base;
84
85 int num_digits;
86};
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
index 68a176032..8f104062d 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
@@ -176,9 +176,13 @@ EmuWindow_SDL2::EmuWindow_SDL2(bool fullscreen) {
176 176
177 SDL_SetMainReady(); 177 SDL_SetMainReady();
178 178
179 const SDL_GLprofile profile = Settings::values.use_compatibility_profile
180 ? SDL_GL_CONTEXT_PROFILE_COMPATIBILITY
181 : SDL_GL_CONTEXT_PROFILE_CORE;
182
179 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); 183 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
180 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); 184 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
181 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); 185 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile);
182 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); 186 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
183 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); 187 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
184 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); 188 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp
index a1d7879b1..d3734927b 100644
--- a/src/yuzu_cmd/yuzu.cpp
+++ b/src/yuzu_cmd/yuzu.cpp
@@ -222,6 +222,7 @@ int main(int argc, char** argv) {
222 222
223 system.TelemetrySession().AddField(Telemetry::FieldType::App, "Frontend", "SDL"); 223 system.TelemetrySession().AddField(Telemetry::FieldType::App, "Frontend", "SDL");
224 224
225 emu_window->MakeCurrent();
225 system.Renderer().Rasterizer().LoadDiskResources(); 226 system.Renderer().Rasterizer().LoadDiskResources();
226 227
227 while (emu_window->IsOpen()) { 228 while (emu_window->IsOpen()) {