summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/hle/service/acc/acc_aa.cpp2
-rw-r--r--src/core/hle/service/acc/acc_aa.h1
-rw-r--r--src/core/hle/service/acc/acc_su.cpp2
-rw-r--r--src/core/hle/service/acc/acc_su.h1
-rw-r--r--src/core/hle/service/acc/acc_u0.cpp2
-rw-r--r--src/core/hle/service/acc/acc_u0.h1
-rw-r--r--src/core/hle/service/acc/acc_u1.cpp2
-rw-r--r--src/core/hle/service/acc/acc_u1.h1
-rw-r--r--src/core/hle/service/acc/profile_manager.cpp2
-rw-r--r--src/core/hle/service/acc/profile_manager.h2
-rw-r--r--src/core/hle/service/am/am.cpp23
-rw-r--r--src/core/hle/service/am/am.h12
-rw-r--r--src/core/hle/service/am/applet_ae.cpp2
-rw-r--r--src/core/hle/service/am/applet_ae.h2
-rw-r--r--src/core/hle/service/am/applet_oe.cpp2
-rw-r--r--src/core/hle/service/am/applet_oe.h2
-rw-r--r--src/core/hle/service/am/idle.cpp2
-rw-r--r--src/core/hle/service/am/idle.h1
-rw-r--r--src/core/hle/service/am/omm.cpp2
-rw-r--r--src/core/hle/service/am/omm.h1
-rw-r--r--src/core/hle/service/am/spsm.cpp2
-rw-r--r--src/core/hle/service/am/spsm.h1
-rw-r--r--src/core/hle/service/aoc/aoc_u.cpp2
-rw-r--r--src/core/hle/service/aoc/aoc_u.h2
-rw-r--r--src/core/hle/service/apm/apm.cpp3
-rw-r--r--src/core/hle/service/apm/apm.h4
-rw-r--r--src/core/hle/service/apm/interface.cpp4
-rw-r--r--src/core/hle/service/apm/interface.h3
-rw-r--r--src/core/hle/service/audio/audctl.cpp2
-rw-r--r--src/core/hle/service/audio/audctl.h1
-rw-r--r--src/core/hle/service/audio/auddbg.cpp2
-rw-r--r--src/core/hle/service/audio/auddbg.h1
-rw-r--r--src/core/hle/service/audio/audin_a.cpp2
-rw-r--r--src/core/hle/service/audio/audin_a.h1
-rw-r--r--src/core/hle/service/audio/audin_u.cpp2
-rw-r--r--src/core/hle/service/audio/audin_u.h2
-rw-r--r--src/core/hle/service/audio/audout_a.cpp2
-rw-r--r--src/core/hle/service/audio/audout_a.h1
-rw-r--r--src/core/hle/service/audio/audout_u.cpp2
-rw-r--r--src/core/hle/service/audio/audout_u.h2
-rw-r--r--src/core/hle/service/audio/audrec_a.cpp2
-rw-r--r--src/core/hle/service/audio/audrec_a.h1
-rw-r--r--src/core/hle/service/audio/audrec_u.cpp2
-rw-r--r--src/core/hle/service/audio/audrec_u.h2
-rw-r--r--src/core/hle/service/audio/audren_a.cpp2
-rw-r--r--src/core/hle/service/audio/audren_a.h1
-rw-r--r--src/core/hle/service/audio/audren_u.cpp2
-rw-r--r--src/core/hle/service/audio/audren_u.h2
-rw-r--r--src/core/hle/service/audio/codecctl.cpp2
-rw-r--r--src/core/hle/service/audio/codecctl.h2
-rw-r--r--src/core/hle/service/audio/hwopus.cpp2
-rw-r--r--src/core/hle/service/audio/hwopus.h2
-rw-r--r--src/core/hle/service/bcat/bcat.cpp2
-rw-r--r--src/core/hle/service/bcat/bcat.h1
-rw-r--r--src/core/hle/service/bcat/module.cpp2
-rw-r--r--src/core/hle/service/bcat/module.h1
-rw-r--r--src/core/hle/service/fatal/fatal.cpp2
-rw-r--r--src/core/hle/service/fatal/fatal.h1
-rw-r--r--src/core/hle/service/fatal/fatal_p.cpp2
-rw-r--r--src/core/hle/service/fatal/fatal_p.h1
-rw-r--r--src/core/hle/service/fatal/fatal_u.cpp2
-rw-r--r--src/core/hle/service/fatal/fatal_u.h1
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp2
-rw-r--r--src/core/hle/service/filesystem/filesystem.h1
-rw-r--r--src/core/hle/service/filesystem/fsp_ldr.cpp2
-rw-r--r--src/core/hle/service/filesystem/fsp_ldr.h1
-rw-r--r--src/core/hle/service/filesystem/fsp_pr.cpp2
-rw-r--r--src/core/hle/service/filesystem/fsp_pr.h1
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.cpp2
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.h2
-rw-r--r--src/core/hle/service/friend/friend.cpp2
-rw-r--r--src/core/hle/service/friend/friend.h1
-rw-r--r--src/core/hle/service/friend/interface.cpp2
-rw-r--r--src/core/hle/service/friend/interface.h1
-rw-r--r--src/core/hle/service/hid/hid.cpp8
-rw-r--r--src/core/hle/service/hid/irs.cpp4
-rw-r--r--src/core/hle/service/hid/irs.h2
-rw-r--r--src/core/hle/service/hid/xcd.cpp2
-rw-r--r--src/core/hle/service/hid/xcd.h1
-rw-r--r--src/core/hle/service/nfp/nfp.cpp2
-rw-r--r--src/core/hle/service/nfp/nfp.h1
-rw-r--r--src/core/hle/service/nfp/nfp_user.cpp2
-rw-r--r--src/core/hle/service/nfp/nfp_user.h1
-rw-r--r--src/core/hle/service/ns/pl_u.cpp28
-rw-r--r--src/core/hle/service/ns/pl_u.h2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp3
-rw-r--r--src/core/hle/service/nvdrv/devices/nvdisp_disp0.h4
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp5
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h5
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp3
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl.h4
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp3
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h4
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp29
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.h21
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp3
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec.h4
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp3
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h4
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_vic.cpp3
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_vic.h4
-rw-r--r--src/core/hle/service/nvdrv/devices/nvmap.cpp3
-rw-r--r--src/core/hle/service/nvdrv/devices/nvmap.h4
-rw-r--r--src/core/hle/service/nvdrv/interface.cpp2
-rw-r--r--src/core/hle/service/nvdrv/interface.h2
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.cpp2
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.h2
-rw-r--r--src/core/hle/service/nvdrv/nvmemp.cpp2
-rw-r--r--src/core/hle/service/nvdrv/nvmemp.h2
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.cpp2
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.h2
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.cpp3
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.h4
-rw-r--r--src/core/hle/service/pctl/module.cpp2
-rw-r--r--src/core/hle/service/pctl/module.h1
-rw-r--r--src/core/hle/service/pctl/pctl.cpp2
-rw-r--r--src/core/hle/service/pctl/pctl.h1
-rw-r--r--src/core/hle/service/service.cpp2
-rw-r--r--src/core/hle/service/set/set.cpp2
-rw-r--r--src/core/hle/service/set/set.h2
-rw-r--r--src/core/hle/service/set/set_cal.cpp2
-rw-r--r--src/core/hle/service/set/set_cal.h2
-rw-r--r--src/core/hle/service/set/set_fd.cpp2
-rw-r--r--src/core/hle/service/set/set_fd.h2
-rw-r--r--src/core/hle/service/sockets/bsd.cpp4
-rw-r--r--src/core/hle/service/sockets/bsd.h3
-rw-r--r--src/core/hle/service/sockets/ethc.cpp4
-rw-r--r--src/core/hle/service/sockets/ethc.h2
-rw-r--r--src/core/hle/service/sockets/nsd.cpp2
-rw-r--r--src/core/hle/service/sockets/nsd.h2
-rw-r--r--src/core/hle/service/sockets/sfdnsres.cpp2
-rw-r--r--src/core/hle/service/sockets/sfdnsres.h2
-rw-r--r--src/core/hle/service/spl/csrng.cpp2
-rw-r--r--src/core/hle/service/spl/csrng.h1
-rw-r--r--src/core/hle/service/spl/module.cpp2
-rw-r--r--src/core/hle/service/spl/module.h1
-rw-r--r--src/core/hle/service/spl/spl.cpp2
-rw-r--r--src/core/hle/service/spl/spl.h1
-rw-r--r--src/core/hle/service/time/interface.cpp2
-rw-r--r--src/core/hle/service/time/interface.h1
-rw-r--r--src/core/hle/service/time/time.cpp2
-rw-r--r--src/core/hle/service/time/time.h1
-rw-r--r--src/core/hle/service/vi/vi.cpp2
-rw-r--r--src/core/hle/service/vi/vi.h1
-rw-r--r--src/core/hle/service/vi/vi_m.cpp2
-rw-r--r--src/core/hle/service/vi/vi_m.h1
-rw-r--r--src/core/hle/service/vi/vi_s.cpp2
-rw-r--r--src/core/hle/service/vi/vi_s.h1
-rw-r--r--src/core/hle/service/vi/vi_u.cpp2
-rw-r--r--src/core/hle/service/vi/vi_u.h1
-rw-r--r--src/core/settings.h2
-rw-r--r--src/input_common/main.cpp12
-rw-r--r--src/input_common/main.h2
-rw-r--r--src/input_common/sdl/sdl.cpp387
-rw-r--r--src/input_common/sdl/sdl.h9
-rw-r--r--src/video_core/command_processor.cpp170
-rw-r--r--src/video_core/command_processor.h17
-rw-r--r--src/video_core/engines/maxwell_3d.cpp2
-rw-r--r--src/video_core/engines/maxwell_3d.h22
-rw-r--r--src/video_core/engines/maxwell_dma.cpp12
-rw-r--r--src/video_core/engines/shader_bytecode.h105
-rw-r--r--src/video_core/gpu.cpp1
-rw-r--r--src/video_core/gpu.h8
-rw-r--r--src/video_core/rasterizer_interface.h3
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp191
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h22
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp160
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.h21
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp8
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp316
-rw-r--r--src/video_core/renderer_opengl/gl_shader_gen.cpp9
-rw-r--r--src/video_core/renderer_opengl/gl_shader_util.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_stream_buffer.cpp2
-rw-r--r--src/yuzu/CMakeLists.txt2
-rw-r--r--src/yuzu/bootmanager.cpp1
-rw-r--r--src/yuzu/compatibility_list.cpp18
-rw-r--r--src/yuzu/compatibility_list.h17
-rw-r--r--src/yuzu/configuration/configure_general.cpp3
-rw-r--r--src/yuzu/configuration/configure_general.ui7
-rw-r--r--src/yuzu/configuration/configure_input.cpp22
-rw-r--r--src/yuzu/game_list.cpp1
-rw-r--r--src/yuzu/game_list.h10
-rw-r--r--src/yuzu/game_list_p.h11
-rw-r--r--src/yuzu/game_list_worker.cpp6
-rw-r--r--src/yuzu/game_list_worker.h8
-rw-r--r--src/yuzu/main.cpp12
-rw-r--r--src/yuzu/main.h6
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2.cpp9
-rw-r--r--src/yuzu_cmd/yuzu.cpp5
190 files changed, 1415 insertions, 623 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 7ddc87539..26f727d96 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -388,7 +388,7 @@ add_library(core STATIC
388create_target_directory_groups(core) 388create_target_directory_groups(core)
389 389
390target_link_libraries(core PUBLIC common PRIVATE audio_core video_core) 390target_link_libraries(core PUBLIC common PRIVATE audio_core video_core)
391target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt lz4_static mbedtls opus unicorn) 391target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt lz4_static mbedtls opus unicorn open_source_archives)
392 392
393if (ARCHITECTURE_x86_64) 393if (ARCHITECTURE_x86_64)
394 target_sources(core PRIVATE 394 target_sources(core PRIVATE
diff --git a/src/core/hle/service/acc/acc_aa.cpp b/src/core/hle/service/acc/acc_aa.cpp
index 9bd595a37..e84d9f7cf 100644
--- a/src/core/hle/service/acc/acc_aa.cpp
+++ b/src/core/hle/service/acc/acc_aa.cpp
@@ -18,4 +18,6 @@ ACC_AA::ACC_AA(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p
18 RegisterHandlers(functions); 18 RegisterHandlers(functions);
19} 19}
20 20
21ACC_AA::~ACC_AA() = default;
22
21} // namespace Service::Account 23} // namespace Service::Account
diff --git a/src/core/hle/service/acc/acc_aa.h b/src/core/hle/service/acc/acc_aa.h
index 2e08c781a..9edb0421b 100644
--- a/src/core/hle/service/acc/acc_aa.h
+++ b/src/core/hle/service/acc/acc_aa.h
@@ -12,6 +12,7 @@ class ACC_AA final : public Module::Interface {
12public: 12public:
13 explicit ACC_AA(std::shared_ptr<Module> module, 13 explicit ACC_AA(std::shared_ptr<Module> module,
14 std::shared_ptr<ProfileManager> profile_manager); 14 std::shared_ptr<ProfileManager> profile_manager);
15 ~ACC_AA() override;
15}; 16};
16 17
17} // namespace Service::Account 18} // namespace Service::Account
diff --git a/src/core/hle/service/acc/acc_su.cpp b/src/core/hle/service/acc/acc_su.cpp
index 0218ee859..ad455c3a7 100644
--- a/src/core/hle/service/acc/acc_su.cpp
+++ b/src/core/hle/service/acc/acc_su.cpp
@@ -51,4 +51,6 @@ ACC_SU::ACC_SU(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p
51 RegisterHandlers(functions); 51 RegisterHandlers(functions);
52} 52}
53 53
54ACC_SU::~ACC_SU() = default;
55
54} // namespace Service::Account 56} // namespace Service::Account
diff --git a/src/core/hle/service/acc/acc_su.h b/src/core/hle/service/acc/acc_su.h
index 79a47d88d..a3eb885bf 100644
--- a/src/core/hle/service/acc/acc_su.h
+++ b/src/core/hle/service/acc/acc_su.h
@@ -13,6 +13,7 @@ class ACC_SU final : public Module::Interface {
13public: 13public:
14 explicit ACC_SU(std::shared_ptr<Module> module, 14 explicit ACC_SU(std::shared_ptr<Module> module,
15 std::shared_ptr<ProfileManager> profile_manager); 15 std::shared_ptr<ProfileManager> profile_manager);
16 ~ACC_SU() override;
16}; 17};
17 18
18} // namespace Account 19} // namespace Account
diff --git a/src/core/hle/service/acc/acc_u0.cpp b/src/core/hle/service/acc/acc_u0.cpp
index 84a4d05b8..72d4adf35 100644
--- a/src/core/hle/service/acc/acc_u0.cpp
+++ b/src/core/hle/service/acc/acc_u0.cpp
@@ -31,4 +31,6 @@ ACC_U0::ACC_U0(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p
31 RegisterHandlers(functions); 31 RegisterHandlers(functions);
32} 32}
33 33
34ACC_U0::~ACC_U0() = default;
35
34} // namespace Service::Account 36} // namespace Service::Account
diff --git a/src/core/hle/service/acc/acc_u0.h b/src/core/hle/service/acc/acc_u0.h
index e8a114f99..a1290e0bd 100644
--- a/src/core/hle/service/acc/acc_u0.h
+++ b/src/core/hle/service/acc/acc_u0.h
@@ -12,6 +12,7 @@ class ACC_U0 final : public Module::Interface {
12public: 12public:
13 explicit ACC_U0(std::shared_ptr<Module> module, 13 explicit ACC_U0(std::shared_ptr<Module> module,
14 std::shared_ptr<ProfileManager> profile_manager); 14 std::shared_ptr<ProfileManager> profile_manager);
15 ~ACC_U0() override;
15}; 16};
16 17
17} // namespace Service::Account 18} // namespace Service::Account
diff --git a/src/core/hle/service/acc/acc_u1.cpp b/src/core/hle/service/acc/acc_u1.cpp
index 495693949..d480f08e5 100644
--- a/src/core/hle/service/acc/acc_u1.cpp
+++ b/src/core/hle/service/acc/acc_u1.cpp
@@ -38,4 +38,6 @@ ACC_U1::ACC_U1(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p
38 RegisterHandlers(functions); 38 RegisterHandlers(functions);
39} 39}
40 40
41ACC_U1::~ACC_U1() = default;
42
41} // namespace Service::Account 43} // namespace Service::Account
diff --git a/src/core/hle/service/acc/acc_u1.h b/src/core/hle/service/acc/acc_u1.h
index a77520e6f..9e79daee3 100644
--- a/src/core/hle/service/acc/acc_u1.h
+++ b/src/core/hle/service/acc/acc_u1.h
@@ -12,6 +12,7 @@ class ACC_U1 final : public Module::Interface {
12public: 12public:
13 explicit ACC_U1(std::shared_ptr<Module> module, 13 explicit ACC_U1(std::shared_ptr<Module> module,
14 std::shared_ptr<ProfileManager> profile_manager); 14 std::shared_ptr<ProfileManager> profile_manager);
15 ~ACC_U1() override;
15}; 16};
16 17
17} // namespace Service::Account 18} // namespace Service::Account
diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp
index e0b03d763..4ccebef23 100644
--- a/src/core/hle/service/acc/profile_manager.cpp
+++ b/src/core/hle/service/acc/profile_manager.cpp
@@ -29,6 +29,8 @@ ProfileManager::ProfileManager() {
29 OpenUser(user_uuid); 29 OpenUser(user_uuid);
30} 30}
31 31
32ProfileManager::~ProfileManager() = default;
33
32/// After a users creation it needs to be "registered" to the system. AddToProfiles handles the 34/// After a users creation it needs to be "registered" to the system. AddToProfiles handles the
33/// internal management of the users profiles 35/// internal management of the users profiles
34boost::optional<size_t> ProfileManager::AddToProfiles(const ProfileInfo& user) { 36boost::optional<size_t> ProfileManager::AddToProfiles(const ProfileInfo& user) {
diff --git a/src/core/hle/service/acc/profile_manager.h b/src/core/hle/service/acc/profile_manager.h
index 52967844d..cd8df93a5 100644
--- a/src/core/hle/service/acc/profile_manager.h
+++ b/src/core/hle/service/acc/profile_manager.h
@@ -82,6 +82,8 @@ static_assert(sizeof(ProfileBase) == 0x38, "ProfileBase is an invalid size");
82class ProfileManager { 82class ProfileManager {
83public: 83public:
84 ProfileManager(); // TODO(ogniK): Load from system save 84 ProfileManager(); // TODO(ogniK): Load from system save
85 ~ProfileManager();
86
85 ResultCode AddUser(const ProfileInfo& user); 87 ResultCode AddUser(const ProfileInfo& user);
86 ResultCode CreateNewUser(UUID uuid, const ProfileUsername& username); 88 ResultCode CreateNewUser(UUID uuid, const ProfileUsername& username);
87 ResultCode CreateNewUser(UUID uuid, const std::string& username); 89 ResultCode CreateNewUser(UUID uuid, const std::string& username);
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 818c03e0f..a57ed3042 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -35,6 +35,8 @@ IWindowController::IWindowController() : ServiceFramework("IWindowController") {
35 RegisterHandlers(functions); 35 RegisterHandlers(functions);
36} 36}
37 37
38IWindowController::~IWindowController() = default;
39
38void IWindowController::GetAppletResourceUserId(Kernel::HLERequestContext& ctx) { 40void IWindowController::GetAppletResourceUserId(Kernel::HLERequestContext& ctx) {
39 LOG_WARNING(Service_AM, "(STUBBED) called"); 41 LOG_WARNING(Service_AM, "(STUBBED) called");
40 IPC::ResponseBuilder rb{ctx, 4}; 42 IPC::ResponseBuilder rb{ctx, 4};
@@ -61,6 +63,8 @@ IAudioController::IAudioController() : ServiceFramework("IAudioController") {
61 RegisterHandlers(functions); 63 RegisterHandlers(functions);
62} 64}
63 65
66IAudioController::~IAudioController() = default;
67
64void IAudioController::SetExpectedMasterVolume(Kernel::HLERequestContext& ctx) { 68void IAudioController::SetExpectedMasterVolume(Kernel::HLERequestContext& ctx) {
65 LOG_WARNING(Service_AM, "(STUBBED) called"); 69 LOG_WARNING(Service_AM, "(STUBBED) called");
66 IPC::ResponseBuilder rb{ctx, 2}; 70 IPC::ResponseBuilder rb{ctx, 2};
@@ -116,7 +120,10 @@ IDisplayController::IDisplayController() : ServiceFramework("IDisplayController"
116 RegisterHandlers(functions); 120 RegisterHandlers(functions);
117} 121}
118 122
123IDisplayController::~IDisplayController() = default;
124
119IDebugFunctions::IDebugFunctions() : ServiceFramework("IDebugFunctions") {} 125IDebugFunctions::IDebugFunctions() : ServiceFramework("IDebugFunctions") {}
126IDebugFunctions::~IDebugFunctions() = default;
120 127
121ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger) 128ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger)
122 : ServiceFramework("ISelfController"), nvflinger(std::move(nvflinger)) { 129 : ServiceFramework("ISelfController"), nvflinger(std::move(nvflinger)) {
@@ -165,6 +172,8 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger
165 Kernel::Event::Create(kernel, Kernel::ResetType::Sticky, "ISelfController:LaunchableEvent"); 172 Kernel::Event::Create(kernel, Kernel::ResetType::Sticky, "ISelfController:LaunchableEvent");
166} 173}
167 174
175ISelfController::~ISelfController() = default;
176
168void ISelfController::SetFocusHandlingMode(Kernel::HLERequestContext& ctx) { 177void ISelfController::SetFocusHandlingMode(Kernel::HLERequestContext& ctx) {
169 // Takes 3 input u8s with each field located immediately after the previous u8, these are 178 // Takes 3 input u8s with each field located immediately after the previous u8, these are
170 // bool flags. No output. 179 // bool flags. No output.
@@ -337,6 +346,8 @@ ICommonStateGetter::ICommonStateGetter() : ServiceFramework("ICommonStateGetter"
337 event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "ICommonStateGetter:Event"); 346 event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "ICommonStateGetter:Event");
338} 347}
339 348
349ICommonStateGetter::~ICommonStateGetter() = default;
350
340void ICommonStateGetter::GetBootMode(Kernel::HLERequestContext& ctx) { 351void ICommonStateGetter::GetBootMode(Kernel::HLERequestContext& ctx) {
341 IPC::ResponseBuilder rb{ctx, 3}; 352 IPC::ResponseBuilder rb{ctx, 3};
342 rb.Push(RESULT_SUCCESS); 353 rb.Push(RESULT_SUCCESS);
@@ -573,6 +584,8 @@ ILibraryAppletCreator::ILibraryAppletCreator() : ServiceFramework("ILibraryApple
573 RegisterHandlers(functions); 584 RegisterHandlers(functions);
574} 585}
575 586
587ILibraryAppletCreator::~ILibraryAppletCreator() = default;
588
576void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx) { 589void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx) {
577 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 590 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
578 591
@@ -638,6 +651,8 @@ IApplicationFunctions::IApplicationFunctions() : ServiceFramework("IApplicationF
638 RegisterHandlers(functions); 651 RegisterHandlers(functions);
639} 652}
640 653
654IApplicationFunctions::~IApplicationFunctions() = default;
655
641void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) { 656void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) {
642 constexpr std::array<u8, 0x88> data{{ 657 constexpr std::array<u8, 0x88> data{{
643 0xca, 0x97, 0x94, 0xc7, // Magic 658 0xca, 0x97, 0x94, 0xc7, // Magic
@@ -760,6 +775,8 @@ IHomeMenuFunctions::IHomeMenuFunctions() : ServiceFramework("IHomeMenuFunctions"
760 RegisterHandlers(functions); 775 RegisterHandlers(functions);
761} 776}
762 777
778IHomeMenuFunctions::~IHomeMenuFunctions() = default;
779
763void IHomeMenuFunctions::RequestToGetForeground(Kernel::HLERequestContext& ctx) { 780void IHomeMenuFunctions::RequestToGetForeground(Kernel::HLERequestContext& ctx) {
764 IPC::ResponseBuilder rb{ctx, 2}; 781 IPC::ResponseBuilder rb{ctx, 2};
765 rb.Push(RESULT_SUCCESS); 782 rb.Push(RESULT_SUCCESS);
@@ -783,6 +800,8 @@ IGlobalStateController::IGlobalStateController() : ServiceFramework("IGlobalStat
783 RegisterHandlers(functions); 800 RegisterHandlers(functions);
784} 801}
785 802
803IGlobalStateController::~IGlobalStateController() = default;
804
786IApplicationCreator::IApplicationCreator() : ServiceFramework("IApplicationCreator") { 805IApplicationCreator::IApplicationCreator() : ServiceFramework("IApplicationCreator") {
787 static const FunctionInfo functions[] = { 806 static const FunctionInfo functions[] = {
788 {0, nullptr, "CreateApplication"}, 807 {0, nullptr, "CreateApplication"},
@@ -793,6 +812,8 @@ IApplicationCreator::IApplicationCreator() : ServiceFramework("IApplicationCreat
793 RegisterHandlers(functions); 812 RegisterHandlers(functions);
794} 813}
795 814
815IApplicationCreator::~IApplicationCreator() = default;
816
796IProcessWindingController::IProcessWindingController() 817IProcessWindingController::IProcessWindingController()
797 : ServiceFramework("IProcessWindingController") { 818 : ServiceFramework("IProcessWindingController") {
798 static const FunctionInfo functions[] = { 819 static const FunctionInfo functions[] = {
@@ -807,4 +828,6 @@ IProcessWindingController::IProcessWindingController()
807 }; 828 };
808 RegisterHandlers(functions); 829 RegisterHandlers(functions);
809} 830}
831
832IProcessWindingController::~IProcessWindingController() = default;
810} // namespace Service::AM 833} // namespace Service::AM
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index 9e8bb4e43..fd9ae296b 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -42,6 +42,7 @@ enum SystemLanguage {
42class IWindowController final : public ServiceFramework<IWindowController> { 42class IWindowController final : public ServiceFramework<IWindowController> {
43public: 43public:
44 IWindowController(); 44 IWindowController();
45 ~IWindowController() override;
45 46
46private: 47private:
47 void GetAppletResourceUserId(Kernel::HLERequestContext& ctx); 48 void GetAppletResourceUserId(Kernel::HLERequestContext& ctx);
@@ -51,6 +52,7 @@ private:
51class IAudioController final : public ServiceFramework<IAudioController> { 52class IAudioController final : public ServiceFramework<IAudioController> {
52public: 53public:
53 IAudioController(); 54 IAudioController();
55 ~IAudioController() override;
54 56
55private: 57private:
56 void SetExpectedMasterVolume(Kernel::HLERequestContext& ctx); 58 void SetExpectedMasterVolume(Kernel::HLERequestContext& ctx);
@@ -63,16 +65,19 @@ private:
63class IDisplayController final : public ServiceFramework<IDisplayController> { 65class IDisplayController final : public ServiceFramework<IDisplayController> {
64public: 66public:
65 IDisplayController(); 67 IDisplayController();
68 ~IDisplayController() override;
66}; 69};
67 70
68class IDebugFunctions final : public ServiceFramework<IDebugFunctions> { 71class IDebugFunctions final : public ServiceFramework<IDebugFunctions> {
69public: 72public:
70 IDebugFunctions(); 73 IDebugFunctions();
74 ~IDebugFunctions() override;
71}; 75};
72 76
73class ISelfController final : public ServiceFramework<ISelfController> { 77class ISelfController final : public ServiceFramework<ISelfController> {
74public: 78public:
75 explicit ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger); 79 explicit ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger);
80 ~ISelfController() override;
76 81
77private: 82private:
78 void SetFocusHandlingMode(Kernel::HLERequestContext& ctx); 83 void SetFocusHandlingMode(Kernel::HLERequestContext& ctx);
@@ -98,6 +103,7 @@ private:
98class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { 103class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> {
99public: 104public:
100 ICommonStateGetter(); 105 ICommonStateGetter();
106 ~ICommonStateGetter() override;
101 107
102private: 108private:
103 enum class FocusState : u8 { 109 enum class FocusState : u8 {
@@ -124,6 +130,7 @@ private:
124class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> { 130class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> {
125public: 131public:
126 ILibraryAppletCreator(); 132 ILibraryAppletCreator();
133 ~ILibraryAppletCreator() override;
127 134
128private: 135private:
129 void CreateLibraryApplet(Kernel::HLERequestContext& ctx); 136 void CreateLibraryApplet(Kernel::HLERequestContext& ctx);
@@ -133,6 +140,7 @@ private:
133class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> { 140class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
134public: 141public:
135 IApplicationFunctions(); 142 IApplicationFunctions();
143 ~IApplicationFunctions() override;
136 144
137private: 145private:
138 void PopLaunchParameter(Kernel::HLERequestContext& ctx); 146 void PopLaunchParameter(Kernel::HLERequestContext& ctx);
@@ -150,6 +158,7 @@ private:
150class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> { 158class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> {
151public: 159public:
152 IHomeMenuFunctions(); 160 IHomeMenuFunctions();
161 ~IHomeMenuFunctions() override;
153 162
154private: 163private:
155 void RequestToGetForeground(Kernel::HLERequestContext& ctx); 164 void RequestToGetForeground(Kernel::HLERequestContext& ctx);
@@ -158,16 +167,19 @@ private:
158class IGlobalStateController final : public ServiceFramework<IGlobalStateController> { 167class IGlobalStateController final : public ServiceFramework<IGlobalStateController> {
159public: 168public:
160 IGlobalStateController(); 169 IGlobalStateController();
170 ~IGlobalStateController() override;
161}; 171};
162 172
163class IApplicationCreator final : public ServiceFramework<IApplicationCreator> { 173class IApplicationCreator final : public ServiceFramework<IApplicationCreator> {
164public: 174public:
165 IApplicationCreator(); 175 IApplicationCreator();
176 ~IApplicationCreator() override;
166}; 177};
167 178
168class IProcessWindingController final : public ServiceFramework<IProcessWindingController> { 179class IProcessWindingController final : public ServiceFramework<IProcessWindingController> {
169public: 180public:
170 IProcessWindingController(); 181 IProcessWindingController();
182 ~IProcessWindingController() override;
171}; 183};
172 184
173/// Registers all AM services with the specified service manager. 185/// Registers all AM services with the specified service manager.
diff --git a/src/core/hle/service/am/applet_ae.cpp b/src/core/hle/service/am/applet_ae.cpp
index 7cebc918a..4296c255e 100644
--- a/src/core/hle/service/am/applet_ae.cpp
+++ b/src/core/hle/service/am/applet_ae.cpp
@@ -222,4 +222,6 @@ AppletAE::AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger)
222 RegisterHandlers(functions); 222 RegisterHandlers(functions);
223} 223}
224 224
225AppletAE::~AppletAE() = default;
226
225} // namespace Service::AM 227} // namespace Service::AM
diff --git a/src/core/hle/service/am/applet_ae.h b/src/core/hle/service/am/applet_ae.h
index bdc57b9bc..1ed77baa4 100644
--- a/src/core/hle/service/am/applet_ae.h
+++ b/src/core/hle/service/am/applet_ae.h
@@ -18,7 +18,7 @@ namespace AM {
18class AppletAE final : public ServiceFramework<AppletAE> { 18class AppletAE final : public ServiceFramework<AppletAE> {
19public: 19public:
20 explicit AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger); 20 explicit AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger);
21 ~AppletAE() = default; 21 ~AppletAE() override;
22 22
23private: 23private:
24 void OpenSystemAppletProxy(Kernel::HLERequestContext& ctx); 24 void OpenSystemAppletProxy(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/am/applet_oe.cpp b/src/core/hle/service/am/applet_oe.cpp
index beea7d19b..e45cf6e20 100644
--- a/src/core/hle/service/am/applet_oe.cpp
+++ b/src/core/hle/service/am/applet_oe.cpp
@@ -103,4 +103,6 @@ AppletOE::AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger)
103 RegisterHandlers(functions); 103 RegisterHandlers(functions);
104} 104}
105 105
106AppletOE::~AppletOE() = default;
107
106} // namespace Service::AM 108} // namespace Service::AM
diff --git a/src/core/hle/service/am/applet_oe.h b/src/core/hle/service/am/applet_oe.h
index c52e2a322..60cfdfd9d 100644
--- a/src/core/hle/service/am/applet_oe.h
+++ b/src/core/hle/service/am/applet_oe.h
@@ -18,7 +18,7 @@ namespace AM {
18class AppletOE final : public ServiceFramework<AppletOE> { 18class AppletOE final : public ServiceFramework<AppletOE> {
19public: 19public:
20 explicit AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger); 20 explicit AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger);
21 ~AppletOE() = default; 21 ~AppletOE() override;
22 22
23private: 23private:
24 void OpenApplicationProxy(Kernel::HLERequestContext& ctx); 24 void OpenApplicationProxy(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/am/idle.cpp b/src/core/hle/service/am/idle.cpp
index af46e9494..0e3088bc8 100644
--- a/src/core/hle/service/am/idle.cpp
+++ b/src/core/hle/service/am/idle.cpp
@@ -21,4 +21,6 @@ IdleSys::IdleSys() : ServiceFramework{"idle:sys"} {
21 RegisterHandlers(functions); 21 RegisterHandlers(functions);
22} 22}
23 23
24IdleSys::~IdleSys() = default;
25
24} // namespace Service::AM 26} // namespace Service::AM
diff --git a/src/core/hle/service/am/idle.h b/src/core/hle/service/am/idle.h
index 1eb68d2c9..c44e856b1 100644
--- a/src/core/hle/service/am/idle.h
+++ b/src/core/hle/service/am/idle.h
@@ -11,6 +11,7 @@ namespace Service::AM {
11class IdleSys final : public ServiceFramework<IdleSys> { 11class IdleSys final : public ServiceFramework<IdleSys> {
12public: 12public:
13 explicit IdleSys(); 13 explicit IdleSys();
14 ~IdleSys() override;
14}; 15};
15 16
16} // namespace Service::AM 17} // namespace Service::AM
diff --git a/src/core/hle/service/am/omm.cpp b/src/core/hle/service/am/omm.cpp
index 447fe8669..1c37f849f 100644
--- a/src/core/hle/service/am/omm.cpp
+++ b/src/core/hle/service/am/omm.cpp
@@ -39,4 +39,6 @@ OMM::OMM() : ServiceFramework{"omm"} {
39 RegisterHandlers(functions); 39 RegisterHandlers(functions);
40} 40}
41 41
42OMM::~OMM() = default;
43
42} // namespace Service::AM 44} // namespace Service::AM
diff --git a/src/core/hle/service/am/omm.h b/src/core/hle/service/am/omm.h
index 49e5d331c..59dc91b72 100644
--- a/src/core/hle/service/am/omm.h
+++ b/src/core/hle/service/am/omm.h
@@ -11,6 +11,7 @@ namespace Service::AM {
11class OMM final : public ServiceFramework<OMM> { 11class OMM final : public ServiceFramework<OMM> {
12public: 12public:
13 explicit OMM(); 13 explicit OMM();
14 ~OMM() override;
14}; 15};
15 16
16} // namespace Service::AM 17} // namespace Service::AM
diff --git a/src/core/hle/service/am/spsm.cpp b/src/core/hle/service/am/spsm.cpp
index a05d433d0..003ee8667 100644
--- a/src/core/hle/service/am/spsm.cpp
+++ b/src/core/hle/service/am/spsm.cpp
@@ -27,4 +27,6 @@ SPSM::SPSM() : ServiceFramework{"spsm"} {
27 RegisterHandlers(functions); 27 RegisterHandlers(functions);
28} 28}
29 29
30SPSM::~SPSM() = default;
31
30} // namespace Service::AM 32} // namespace Service::AM
diff --git a/src/core/hle/service/am/spsm.h b/src/core/hle/service/am/spsm.h
index 57dde62e1..3a0b979fa 100644
--- a/src/core/hle/service/am/spsm.h
+++ b/src/core/hle/service/am/spsm.h
@@ -11,6 +11,7 @@ namespace Service::AM {
11class SPSM final : public ServiceFramework<SPSM> { 11class SPSM final : public ServiceFramework<SPSM> {
12public: 12public:
13 explicit SPSM(); 13 explicit SPSM();
14 ~SPSM() override;
14}; 15};
15 16
16} // namespace Service::AM 17} // namespace Service::AM
diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp
index 6e7438580..d9eeac9ec 100644
--- a/src/core/hle/service/aoc/aoc_u.cpp
+++ b/src/core/hle/service/aoc/aoc_u.cpp
@@ -23,6 +23,8 @@ AOC_U::AOC_U() : ServiceFramework("aoc:u") {
23 RegisterHandlers(functions); 23 RegisterHandlers(functions);
24} 24}
25 25
26AOC_U::~AOC_U() = default;
27
26void AOC_U::CountAddOnContent(Kernel::HLERequestContext& ctx) { 28void AOC_U::CountAddOnContent(Kernel::HLERequestContext& ctx) {
27 IPC::ResponseBuilder rb{ctx, 4}; 29 IPC::ResponseBuilder rb{ctx, 4};
28 rb.Push(RESULT_SUCCESS); 30 rb.Push(RESULT_SUCCESS);
diff --git a/src/core/hle/service/aoc/aoc_u.h b/src/core/hle/service/aoc/aoc_u.h
index 17d48ef30..29ce8f488 100644
--- a/src/core/hle/service/aoc/aoc_u.h
+++ b/src/core/hle/service/aoc/aoc_u.h
@@ -11,7 +11,7 @@ namespace Service::AOC {
11class AOC_U final : public ServiceFramework<AOC_U> { 11class AOC_U final : public ServiceFramework<AOC_U> {
12public: 12public:
13 AOC_U(); 13 AOC_U();
14 ~AOC_U() = default; 14 ~AOC_U() override;
15 15
16private: 16private:
17 void CountAddOnContent(Kernel::HLERequestContext& ctx); 17 void CountAddOnContent(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/apm/apm.cpp b/src/core/hle/service/apm/apm.cpp
index 4109cb7f7..f3c09bbb1 100644
--- a/src/core/hle/service/apm/apm.cpp
+++ b/src/core/hle/service/apm/apm.cpp
@@ -9,6 +9,9 @@
9 9
10namespace Service::APM { 10namespace Service::APM {
11 11
12Module::Module() = default;
13Module::~Module() = default;
14
12void InstallInterfaces(SM::ServiceManager& service_manager) { 15void InstallInterfaces(SM::ServiceManager& service_manager) {
13 auto module_ = std::make_shared<Module>(); 16 auto module_ = std::make_shared<Module>();
14 std::make_shared<APM>(module_, "apm")->InstallAsService(service_manager); 17 std::make_shared<APM>(module_, "apm")->InstallAsService(service_manager);
diff --git a/src/core/hle/service/apm/apm.h b/src/core/hle/service/apm/apm.h
index 90a80d51b..4d7d5bb7c 100644
--- a/src/core/hle/service/apm/apm.h
+++ b/src/core/hle/service/apm/apm.h
@@ -15,8 +15,8 @@ enum class PerformanceMode : u8 {
15 15
16class Module final { 16class Module final {
17public: 17public:
18 Module() = default; 18 Module();
19 ~Module() = default; 19 ~Module();
20}; 20};
21 21
22/// Registers all AM services with the specified service manager. 22/// Registers all AM services with the specified service manager.
diff --git a/src/core/hle/service/apm/interface.cpp b/src/core/hle/service/apm/interface.cpp
index 4cd8132f5..c22bd3859 100644
--- a/src/core/hle/service/apm/interface.cpp
+++ b/src/core/hle/service/apm/interface.cpp
@@ -70,6 +70,8 @@ APM::APM(std::shared_ptr<Module> apm, const char* name)
70 RegisterHandlers(functions); 70 RegisterHandlers(functions);
71} 71}
72 72
73APM::~APM() = default;
74
73void APM::OpenSession(Kernel::HLERequestContext& ctx) { 75void APM::OpenSession(Kernel::HLERequestContext& ctx) {
74 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 76 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
75 rb.Push(RESULT_SUCCESS); 77 rb.Push(RESULT_SUCCESS);
@@ -93,6 +95,8 @@ APM_Sys::APM_Sys() : ServiceFramework{"apm:sys"} {
93 RegisterHandlers(functions); 95 RegisterHandlers(functions);
94} 96}
95 97
98APM_Sys::~APM_Sys() = default;
99
96void APM_Sys::GetPerformanceEvent(Kernel::HLERequestContext& ctx) { 100void APM_Sys::GetPerformanceEvent(Kernel::HLERequestContext& ctx) {
97 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 101 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
98 rb.Push(RESULT_SUCCESS); 102 rb.Push(RESULT_SUCCESS);
diff --git a/src/core/hle/service/apm/interface.h b/src/core/hle/service/apm/interface.h
index d14264ad7..773541aa4 100644
--- a/src/core/hle/service/apm/interface.h
+++ b/src/core/hle/service/apm/interface.h
@@ -11,7 +11,7 @@ namespace Service::APM {
11class APM final : public ServiceFramework<APM> { 11class APM final : public ServiceFramework<APM> {
12public: 12public:
13 explicit APM(std::shared_ptr<Module> apm, const char* name); 13 explicit APM(std::shared_ptr<Module> apm, const char* name);
14 ~APM() = default; 14 ~APM() override;
15 15
16private: 16private:
17 void OpenSession(Kernel::HLERequestContext& ctx); 17 void OpenSession(Kernel::HLERequestContext& ctx);
@@ -22,6 +22,7 @@ private:
22class APM_Sys final : public ServiceFramework<APM_Sys> { 22class APM_Sys final : public ServiceFramework<APM_Sys> {
23public: 23public:
24 explicit APM_Sys(); 24 explicit APM_Sys();
25 ~APM_Sys() override;
25 26
26private: 27private:
27 void GetPerformanceEvent(Kernel::HLERequestContext& ctx); 28 void GetPerformanceEvent(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/audio/audctl.cpp b/src/core/hle/service/audio/audctl.cpp
index 37c3fdcac..b6b71f966 100644
--- a/src/core/hle/service/audio/audctl.cpp
+++ b/src/core/hle/service/audio/audctl.cpp
@@ -42,4 +42,6 @@ AudCtl::AudCtl() : ServiceFramework{"audctl"} {
42 RegisterHandlers(functions); 42 RegisterHandlers(functions);
43} 43}
44 44
45AudCtl::~AudCtl() = default;
46
45} // namespace Service::Audio 47} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audctl.h b/src/core/hle/service/audio/audctl.h
index ed837bdf2..9d2d9e83b 100644
--- a/src/core/hle/service/audio/audctl.h
+++ b/src/core/hle/service/audio/audctl.h
@@ -11,6 +11,7 @@ namespace Service::Audio {
11class AudCtl final : public ServiceFramework<AudCtl> { 11class AudCtl final : public ServiceFramework<AudCtl> {
12public: 12public:
13 explicit AudCtl(); 13 explicit AudCtl();
14 ~AudCtl() override;
14}; 15};
15 16
16} // namespace Service::Audio 17} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/auddbg.cpp b/src/core/hle/service/audio/auddbg.cpp
index b08c21a20..8fff3e4b4 100644
--- a/src/core/hle/service/audio/auddbg.cpp
+++ b/src/core/hle/service/audio/auddbg.cpp
@@ -17,4 +17,6 @@ AudDbg::AudDbg(const char* name) : ServiceFramework{name} {
17 RegisterHandlers(functions); 17 RegisterHandlers(functions);
18} 18}
19 19
20AudDbg::~AudDbg() = default;
21
20} // namespace Service::Audio 22} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/auddbg.h b/src/core/hle/service/audio/auddbg.h
index a2f540b75..6689f4759 100644
--- a/src/core/hle/service/audio/auddbg.h
+++ b/src/core/hle/service/audio/auddbg.h
@@ -11,6 +11,7 @@ namespace Service::Audio {
11class AudDbg final : public ServiceFramework<AudDbg> { 11class AudDbg final : public ServiceFramework<AudDbg> {
12public: 12public:
13 explicit AudDbg(const char* name); 13 explicit AudDbg(const char* name);
14 ~AudDbg() override;
14}; 15};
15 16
16} // namespace Service::Audio 17} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audin_a.cpp b/src/core/hle/service/audio/audin_a.cpp
index a70d5bca4..ddd12f35e 100644
--- a/src/core/hle/service/audio/audin_a.cpp
+++ b/src/core/hle/service/audio/audin_a.cpp
@@ -19,4 +19,6 @@ AudInA::AudInA() : ServiceFramework{"audin:a"} {
19 RegisterHandlers(functions); 19 RegisterHandlers(functions);
20} 20}
21 21
22AudInA::~AudInA() = default;
23
22} // namespace Service::Audio 24} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audin_a.h b/src/core/hle/service/audio/audin_a.h
index e4c75510f..e7623bc29 100644
--- a/src/core/hle/service/audio/audin_a.h
+++ b/src/core/hle/service/audio/audin_a.h
@@ -11,6 +11,7 @@ namespace Service::Audio {
11class AudInA final : public ServiceFramework<AudInA> { 11class AudInA final : public ServiceFramework<AudInA> {
12public: 12public:
13 explicit AudInA(); 13 explicit AudInA();
14 ~AudInA() override;
14}; 15};
15 16
16} // namespace Service::Audio 17} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audin_u.cpp b/src/core/hle/service/audio/audin_u.cpp
index cbc49e55e..657010312 100644
--- a/src/core/hle/service/audio/audin_u.cpp
+++ b/src/core/hle/service/audio/audin_u.cpp
@@ -41,4 +41,6 @@ AudInU::AudInU() : ServiceFramework("audin:u") {
41 RegisterHandlers(functions); 41 RegisterHandlers(functions);
42} 42}
43 43
44AudInU::~AudInU() = default;
45
44} // namespace Service::Audio 46} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audin_u.h b/src/core/hle/service/audio/audin_u.h
index 2e65efb5b..0538b9560 100644
--- a/src/core/hle/service/audio/audin_u.h
+++ b/src/core/hle/service/audio/audin_u.h
@@ -15,7 +15,7 @@ namespace Service::Audio {
15class AudInU final : public ServiceFramework<AudInU> { 15class AudInU final : public ServiceFramework<AudInU> {
16public: 16public:
17 explicit AudInU(); 17 explicit AudInU();
18 ~AudInU() = default; 18 ~AudInU() override;
19}; 19};
20 20
21} // namespace Service::Audio 21} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audout_a.cpp b/src/core/hle/service/audio/audout_a.cpp
index bf8d40157..85febbca3 100644
--- a/src/core/hle/service/audio/audout_a.cpp
+++ b/src/core/hle/service/audio/audout_a.cpp
@@ -21,4 +21,6 @@ AudOutA::AudOutA() : ServiceFramework{"audout:a"} {
21 RegisterHandlers(functions); 21 RegisterHandlers(functions);
22} 22}
23 23
24AudOutA::~AudOutA() = default;
25
24} // namespace Service::Audio 26} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audout_a.h b/src/core/hle/service/audio/audout_a.h
index 91a069152..d65b66e8e 100644
--- a/src/core/hle/service/audio/audout_a.h
+++ b/src/core/hle/service/audio/audout_a.h
@@ -11,6 +11,7 @@ namespace Service::Audio {
11class AudOutA final : public ServiceFramework<AudOutA> { 11class AudOutA final : public ServiceFramework<AudOutA> {
12public: 12public:
13 explicit AudOutA(); 13 explicit AudOutA();
14 ~AudOutA() override;
14}; 15};
15 16
16} // namespace Service::Audio 17} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp
index 5f370bbdf..05100ca8f 100644
--- a/src/core/hle/service/audio/audout_u.cpp
+++ b/src/core/hle/service/audio/audout_u.cpp
@@ -218,4 +218,6 @@ AudOutU::AudOutU() : ServiceFramework("audout:u") {
218 audio_core = std::make_unique<AudioCore::AudioOut>(); 218 audio_core = std::make_unique<AudioCore::AudioOut>();
219} 219}
220 220
221AudOutU::~AudOutU() = default;
222
221} // namespace Service::Audio 223} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audout_u.h b/src/core/hle/service/audio/audout_u.h
index fd491f65d..aa52d3855 100644
--- a/src/core/hle/service/audio/audout_u.h
+++ b/src/core/hle/service/audio/audout_u.h
@@ -30,7 +30,7 @@ class IAudioOut;
30class AudOutU final : public ServiceFramework<AudOutU> { 30class AudOutU final : public ServiceFramework<AudOutU> {
31public: 31public:
32 AudOutU(); 32 AudOutU();
33 ~AudOutU() = default; 33 ~AudOutU() override;
34 34
35private: 35private:
36 std::shared_ptr<IAudioOut> audio_out_interface; 36 std::shared_ptr<IAudioOut> audio_out_interface;
diff --git a/src/core/hle/service/audio/audrec_a.cpp b/src/core/hle/service/audio/audrec_a.cpp
index 016eabf53..ce1bfb48d 100644
--- a/src/core/hle/service/audio/audrec_a.cpp
+++ b/src/core/hle/service/audio/audrec_a.cpp
@@ -17,4 +17,6 @@ AudRecA::AudRecA() : ServiceFramework{"audrec:a"} {
17 RegisterHandlers(functions); 17 RegisterHandlers(functions);
18} 18}
19 19
20AudRecA::~AudRecA() = default;
21
20} // namespace Service::Audio 22} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audrec_a.h b/src/core/hle/service/audio/audrec_a.h
index 9685047f2..384d24c69 100644
--- a/src/core/hle/service/audio/audrec_a.h
+++ b/src/core/hle/service/audio/audrec_a.h
@@ -11,6 +11,7 @@ namespace Service::Audio {
11class AudRecA final : public ServiceFramework<AudRecA> { 11class AudRecA final : public ServiceFramework<AudRecA> {
12public: 12public:
13 explicit AudRecA(); 13 explicit AudRecA();
14 ~AudRecA() override;
14}; 15};
15 16
16} // namespace Service::Audio 17} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audrec_u.cpp b/src/core/hle/service/audio/audrec_u.cpp
index 74909415c..34974afa9 100644
--- a/src/core/hle/service/audio/audrec_u.cpp
+++ b/src/core/hle/service/audio/audrec_u.cpp
@@ -36,4 +36,6 @@ AudRecU::AudRecU() : ServiceFramework("audrec:u") {
36 RegisterHandlers(functions); 36 RegisterHandlers(functions);
37} 37}
38 38
39AudRecU::~AudRecU() = default;
40
39} // namespace Service::Audio 41} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audrec_u.h b/src/core/hle/service/audio/audrec_u.h
index 46daa33a4..ca3d638e8 100644
--- a/src/core/hle/service/audio/audrec_u.h
+++ b/src/core/hle/service/audio/audrec_u.h
@@ -15,7 +15,7 @@ namespace Service::Audio {
15class AudRecU final : public ServiceFramework<AudRecU> { 15class AudRecU final : public ServiceFramework<AudRecU> {
16public: 16public:
17 explicit AudRecU(); 17 explicit AudRecU();
18 ~AudRecU() = default; 18 ~AudRecU() override;
19}; 19};
20 20
21} // namespace Service::Audio 21} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audren_a.cpp b/src/core/hle/service/audio/audren_a.cpp
index 616ff3dc4..edb66d985 100644
--- a/src/core/hle/service/audio/audren_a.cpp
+++ b/src/core/hle/service/audio/audren_a.cpp
@@ -23,4 +23,6 @@ AudRenA::AudRenA() : ServiceFramework{"audren:a"} {
23 RegisterHandlers(functions); 23 RegisterHandlers(functions);
24} 24}
25 25
26AudRenA::~AudRenA() = default;
27
26} // namespace Service::Audio 28} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audren_a.h b/src/core/hle/service/audio/audren_a.h
index 5ecf2e184..81fef0ffe 100644
--- a/src/core/hle/service/audio/audren_a.h
+++ b/src/core/hle/service/audio/audren_a.h
@@ -11,6 +11,7 @@ namespace Service::Audio {
11class AudRenA final : public ServiceFramework<AudRenA> { 11class AudRenA final : public ServiceFramework<AudRenA> {
12public: 12public:
13 explicit AudRenA(); 13 explicit AudRenA();
14 ~AudRenA() override;
14}; 15};
15 16
16} // namespace Service::Audio 17} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index 016db7c82..3870bec65 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -198,6 +198,8 @@ AudRenU::AudRenU() : ServiceFramework("audren:u") {
198 RegisterHandlers(functions); 198 RegisterHandlers(functions);
199} 199}
200 200
201AudRenU::~AudRenU() = default;
202
201void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) { 203void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) {
202 IPC::RequestParser rp{ctx}; 204 IPC::RequestParser rp{ctx};
203 auto params = rp.PopRaw<AudioCore::AudioRendererParameter>(); 205 auto params = rp.PopRaw<AudioCore::AudioRendererParameter>();
diff --git a/src/core/hle/service/audio/audren_u.h b/src/core/hle/service/audio/audren_u.h
index 8600ac6e4..85a995a2f 100644
--- a/src/core/hle/service/audio/audren_u.h
+++ b/src/core/hle/service/audio/audren_u.h
@@ -16,7 +16,7 @@ namespace Service::Audio {
16class AudRenU final : public ServiceFramework<AudRenU> { 16class AudRenU final : public ServiceFramework<AudRenU> {
17public: 17public:
18 explicit AudRenU(); 18 explicit AudRenU();
19 ~AudRenU() = default; 19 ~AudRenU() override;
20 20
21private: 21private:
22 void OpenAudioRenderer(Kernel::HLERequestContext& ctx); 22 void OpenAudioRenderer(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/audio/codecctl.cpp b/src/core/hle/service/audio/codecctl.cpp
index 212c8d448..c6864146d 100644
--- a/src/core/hle/service/audio/codecctl.cpp
+++ b/src/core/hle/service/audio/codecctl.cpp
@@ -28,4 +28,6 @@ CodecCtl::CodecCtl() : ServiceFramework("codecctl") {
28 RegisterHandlers(functions); 28 RegisterHandlers(functions);
29} 29}
30 30
31CodecCtl::~CodecCtl() = default;
32
31} // namespace Service::Audio 33} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/codecctl.h b/src/core/hle/service/audio/codecctl.h
index d9ac29b67..2fe75b6e2 100644
--- a/src/core/hle/service/audio/codecctl.h
+++ b/src/core/hle/service/audio/codecctl.h
@@ -15,7 +15,7 @@ namespace Service::Audio {
15class CodecCtl final : public ServiceFramework<CodecCtl> { 15class CodecCtl final : public ServiceFramework<CodecCtl> {
16public: 16public:
17 explicit CodecCtl(); 17 explicit CodecCtl();
18 ~CodecCtl() = default; 18 ~CodecCtl() override;
19}; 19};
20 20
21} // namespace Service::Audio 21} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp
index 371cd4997..341bfda42 100644
--- a/src/core/hle/service/audio/hwopus.cpp
+++ b/src/core/hle/service/audio/hwopus.cpp
@@ -151,4 +151,6 @@ HwOpus::HwOpus() : ServiceFramework("hwopus") {
151 RegisterHandlers(functions); 151 RegisterHandlers(functions);
152} 152}
153 153
154HwOpus::~HwOpus() = default;
155
154} // namespace Service::Audio 156} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/hwopus.h b/src/core/hle/service/audio/hwopus.h
index 5258d59f3..602ede8ba 100644
--- a/src/core/hle/service/audio/hwopus.h
+++ b/src/core/hle/service/audio/hwopus.h
@@ -11,7 +11,7 @@ namespace Service::Audio {
11class HwOpus final : public ServiceFramework<HwOpus> { 11class HwOpus final : public ServiceFramework<HwOpus> {
12public: 12public:
13 explicit HwOpus(); 13 explicit HwOpus();
14 ~HwOpus() = default; 14 ~HwOpus() override;
15 15
16private: 16private:
17 void OpenOpusDecoder(Kernel::HLERequestContext& ctx); 17 void OpenOpusDecoder(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/bcat/bcat.cpp b/src/core/hle/service/bcat/bcat.cpp
index 20ce692dc..179aa4949 100644
--- a/src/core/hle/service/bcat/bcat.cpp
+++ b/src/core/hle/service/bcat/bcat.cpp
@@ -13,4 +13,6 @@ BCAT::BCAT(std::shared_ptr<Module> module, const char* name)
13 }; 13 };
14 RegisterHandlers(functions); 14 RegisterHandlers(functions);
15} 15}
16
17BCAT::~BCAT() = default;
16} // namespace Service::BCAT 18} // namespace Service::BCAT
diff --git a/src/core/hle/service/bcat/bcat.h b/src/core/hle/service/bcat/bcat.h
index 6632996a0..802bd689a 100644
--- a/src/core/hle/service/bcat/bcat.h
+++ b/src/core/hle/service/bcat/bcat.h
@@ -11,6 +11,7 @@ namespace Service::BCAT {
11class BCAT final : public Module::Interface { 11class BCAT final : public Module::Interface {
12public: 12public:
13 explicit BCAT(std::shared_ptr<Module> module, const char* name); 13 explicit BCAT(std::shared_ptr<Module> module, const char* name);
14 ~BCAT() override;
14}; 15};
15 16
16} // namespace Service::BCAT 17} // namespace Service::BCAT
diff --git a/src/core/hle/service/bcat/module.cpp b/src/core/hle/service/bcat/module.cpp
index 35e024c3d..6e7b795fb 100644
--- a/src/core/hle/service/bcat/module.cpp
+++ b/src/core/hle/service/bcat/module.cpp
@@ -42,6 +42,8 @@ void Module::Interface::CreateBcatService(Kernel::HLERequestContext& ctx) {
42Module::Interface::Interface(std::shared_ptr<Module> module, const char* name) 42Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
43 : ServiceFramework(name), module(std::move(module)) {} 43 : ServiceFramework(name), module(std::move(module)) {}
44 44
45Module::Interface::~Interface() = default;
46
45void InstallInterfaces(SM::ServiceManager& service_manager) { 47void InstallInterfaces(SM::ServiceManager& service_manager) {
46 auto module = std::make_shared<Module>(); 48 auto module = std::make_shared<Module>();
47 std::make_shared<BCAT>(module, "bcat:a")->InstallAsService(service_manager); 49 std::make_shared<BCAT>(module, "bcat:a")->InstallAsService(service_manager);
diff --git a/src/core/hle/service/bcat/module.h b/src/core/hle/service/bcat/module.h
index 62f6f5f9d..f0d63cab0 100644
--- a/src/core/hle/service/bcat/module.h
+++ b/src/core/hle/service/bcat/module.h
@@ -13,6 +13,7 @@ public:
13 class Interface : public ServiceFramework<Interface> { 13 class Interface : public ServiceFramework<Interface> {
14 public: 14 public:
15 explicit Interface(std::shared_ptr<Module> module, const char* name); 15 explicit Interface(std::shared_ptr<Module> module, const char* name);
16 ~Interface() override;
16 17
17 void CreateBcatService(Kernel::HLERequestContext& ctx); 18 void CreateBcatService(Kernel::HLERequestContext& ctx);
18 19
diff --git a/src/core/hle/service/fatal/fatal.cpp b/src/core/hle/service/fatal/fatal.cpp
index 299b9474f..b436ce4e6 100644
--- a/src/core/hle/service/fatal/fatal.cpp
+++ b/src/core/hle/service/fatal/fatal.cpp
@@ -13,6 +13,8 @@ namespace Service::Fatal {
13Module::Interface::Interface(std::shared_ptr<Module> module, const char* name) 13Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
14 : ServiceFramework(name), module(std::move(module)) {} 14 : ServiceFramework(name), module(std::move(module)) {}
15 15
16Module::Interface::~Interface() = default;
17
16void Module::Interface::ThrowFatalWithPolicy(Kernel::HLERequestContext& ctx) { 18void Module::Interface::ThrowFatalWithPolicy(Kernel::HLERequestContext& ctx) {
17 IPC::RequestParser rp(ctx); 19 IPC::RequestParser rp(ctx);
18 u32 error_code = rp.Pop<u32>(); 20 u32 error_code = rp.Pop<u32>();
diff --git a/src/core/hle/service/fatal/fatal.h b/src/core/hle/service/fatal/fatal.h
index ca607e236..4d9a5be52 100644
--- a/src/core/hle/service/fatal/fatal.h
+++ b/src/core/hle/service/fatal/fatal.h
@@ -13,6 +13,7 @@ public:
13 class Interface : public ServiceFramework<Interface> { 13 class Interface : public ServiceFramework<Interface> {
14 public: 14 public:
15 explicit Interface(std::shared_ptr<Module> module, const char* name); 15 explicit Interface(std::shared_ptr<Module> module, const char* name);
16 ~Interface() override;
16 17
17 void ThrowFatalWithPolicy(Kernel::HLERequestContext& ctx); 18 void ThrowFatalWithPolicy(Kernel::HLERequestContext& ctx);
18 void ThrowFatalWithCpuContext(Kernel::HLERequestContext& ctx); 19 void ThrowFatalWithCpuContext(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/fatal/fatal_p.cpp b/src/core/hle/service/fatal/fatal_p.cpp
index a5254ac2f..9e5f872ff 100644
--- a/src/core/hle/service/fatal/fatal_p.cpp
+++ b/src/core/hle/service/fatal/fatal_p.cpp
@@ -9,4 +9,6 @@ namespace Service::Fatal {
9Fatal_P::Fatal_P(std::shared_ptr<Module> module) 9Fatal_P::Fatal_P(std::shared_ptr<Module> module)
10 : Module::Interface(std::move(module), "fatal:p") {} 10 : Module::Interface(std::move(module), "fatal:p") {}
11 11
12Fatal_P::~Fatal_P() = default;
13
12} // namespace Service::Fatal 14} // namespace Service::Fatal
diff --git a/src/core/hle/service/fatal/fatal_p.h b/src/core/hle/service/fatal/fatal_p.h
index bfd8c8b74..6e9c5979f 100644
--- a/src/core/hle/service/fatal/fatal_p.h
+++ b/src/core/hle/service/fatal/fatal_p.h
@@ -11,6 +11,7 @@ namespace Service::Fatal {
11class Fatal_P final : public Module::Interface { 11class Fatal_P final : public Module::Interface {
12public: 12public:
13 explicit Fatal_P(std::shared_ptr<Module> module); 13 explicit Fatal_P(std::shared_ptr<Module> module);
14 ~Fatal_P() override;
14}; 15};
15 16
16} // namespace Service::Fatal 17} // namespace Service::Fatal
diff --git a/src/core/hle/service/fatal/fatal_u.cpp b/src/core/hle/service/fatal/fatal_u.cpp
index f0631329e..befc307cf 100644
--- a/src/core/hle/service/fatal/fatal_u.cpp
+++ b/src/core/hle/service/fatal/fatal_u.cpp
@@ -15,4 +15,6 @@ Fatal_U::Fatal_U(std::shared_ptr<Module> module) : Module::Interface(std::move(m
15 RegisterHandlers(functions); 15 RegisterHandlers(functions);
16} 16}
17 17
18Fatal_U::~Fatal_U() = default;
19
18} // namespace Service::Fatal 20} // namespace Service::Fatal
diff --git a/src/core/hle/service/fatal/fatal_u.h b/src/core/hle/service/fatal/fatal_u.h
index 9b1a9e97a..72cb6d076 100644
--- a/src/core/hle/service/fatal/fatal_u.h
+++ b/src/core/hle/service/fatal/fatal_u.h
@@ -11,6 +11,7 @@ namespace Service::Fatal {
11class Fatal_U final : public Module::Interface { 11class Fatal_U final : public Module::Interface {
12public: 12public:
13 explicit Fatal_U(std::shared_ptr<Module> module); 13 explicit Fatal_U(std::shared_ptr<Module> module);
14 ~Fatal_U() override;
14}; 15};
15 16
16} // namespace Service::Fatal 17} // namespace Service::Fatal
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index 04c9d750f..5c4971724 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -40,6 +40,8 @@ static FileSys::VirtualDir GetDirectoryRelativeWrapped(FileSys::VirtualDir base,
40VfsDirectoryServiceWrapper::VfsDirectoryServiceWrapper(FileSys::VirtualDir backing_) 40VfsDirectoryServiceWrapper::VfsDirectoryServiceWrapper(FileSys::VirtualDir backing_)
41 : backing(std::move(backing_)) {} 41 : backing(std::move(backing_)) {}
42 42
43VfsDirectoryServiceWrapper::~VfsDirectoryServiceWrapper() = default;
44
43std::string VfsDirectoryServiceWrapper::GetName() const { 45std::string VfsDirectoryServiceWrapper::GetName() const {
44 return backing->GetName(); 46 return backing->GetName();
45} 47}
diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h
index 793a7b06f..aab65a2b8 100644
--- a/src/core/hle/service/filesystem/filesystem.h
+++ b/src/core/hle/service/filesystem/filesystem.h
@@ -64,6 +64,7 @@ void InstallInterfaces(SM::ServiceManager& service_manager, const FileSys::Virtu
64class VfsDirectoryServiceWrapper { 64class VfsDirectoryServiceWrapper {
65public: 65public:
66 explicit VfsDirectoryServiceWrapper(FileSys::VirtualDir backing); 66 explicit VfsDirectoryServiceWrapper(FileSys::VirtualDir backing);
67 ~VfsDirectoryServiceWrapper();
67 68
68 /** 69 /**
69 * Get a descriptive name for the archive (e.g. "RomFS", "SaveData", etc.) 70 * Get a descriptive name for the archive (e.g. "RomFS", "SaveData", etc.)
diff --git a/src/core/hle/service/filesystem/fsp_ldr.cpp b/src/core/hle/service/filesystem/fsp_ldr.cpp
index 0ab9c2606..fb487d5bc 100644
--- a/src/core/hle/service/filesystem/fsp_ldr.cpp
+++ b/src/core/hle/service/filesystem/fsp_ldr.cpp
@@ -19,4 +19,6 @@ FSP_LDR::FSP_LDR() : ServiceFramework{"fsp:ldr"} {
19 RegisterHandlers(functions); 19 RegisterHandlers(functions);
20} 20}
21 21
22FSP_LDR::~FSP_LDR() = default;
23
22} // namespace Service::FileSystem 24} // namespace Service::FileSystem
diff --git a/src/core/hle/service/filesystem/fsp_ldr.h b/src/core/hle/service/filesystem/fsp_ldr.h
index fa8e11b4c..8210b7729 100644
--- a/src/core/hle/service/filesystem/fsp_ldr.h
+++ b/src/core/hle/service/filesystem/fsp_ldr.h
@@ -11,6 +11,7 @@ namespace Service::FileSystem {
11class FSP_LDR final : public ServiceFramework<FSP_LDR> { 11class FSP_LDR final : public ServiceFramework<FSP_LDR> {
12public: 12public:
13 explicit FSP_LDR(); 13 explicit FSP_LDR();
14 ~FSP_LDR() override;
14}; 15};
15 16
16} // namespace Service::FileSystem 17} // namespace Service::FileSystem
diff --git a/src/core/hle/service/filesystem/fsp_pr.cpp b/src/core/hle/service/filesystem/fsp_pr.cpp
index 32b0ae454..378201610 100644
--- a/src/core/hle/service/filesystem/fsp_pr.cpp
+++ b/src/core/hle/service/filesystem/fsp_pr.cpp
@@ -20,4 +20,6 @@ FSP_PR::FSP_PR() : ServiceFramework{"fsp:pr"} {
20 RegisterHandlers(functions); 20 RegisterHandlers(functions);
21} 21}
22 22
23FSP_PR::~FSP_PR() = default;
24
23} // namespace Service::FileSystem 25} // namespace Service::FileSystem
diff --git a/src/core/hle/service/filesystem/fsp_pr.h b/src/core/hle/service/filesystem/fsp_pr.h
index 62edcd08a..556ae5ce9 100644
--- a/src/core/hle/service/filesystem/fsp_pr.h
+++ b/src/core/hle/service/filesystem/fsp_pr.h
@@ -11,6 +11,7 @@ namespace Service::FileSystem {
11class FSP_PR final : public ServiceFramework<FSP_PR> { 11class FSP_PR final : public ServiceFramework<FSP_PR> {
12public: 12public:
13 explicit FSP_PR(); 13 explicit FSP_PR();
14 ~FSP_PR() override;
14}; 15};
15 16
16} // namespace Service::FileSystem 17} // namespace Service::FileSystem
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp
index 3f8ff67e8..cabaf5a55 100644
--- a/src/core/hle/service/filesystem/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp_srv.cpp
@@ -520,6 +520,8 @@ FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") {
520 RegisterHandlers(functions); 520 RegisterHandlers(functions);
521} 521}
522 522
523FSP_SRV::~FSP_SRV() = default;
524
523void FSP_SRV::Initialize(Kernel::HLERequestContext& ctx) { 525void FSP_SRV::Initialize(Kernel::HLERequestContext& ctx) {
524 LOG_WARNING(Service_FS, "(STUBBED) called"); 526 LOG_WARNING(Service_FS, "(STUBBED) called");
525 527
diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp_srv.h
index 2b5c21abb..4aa0358cb 100644
--- a/src/core/hle/service/filesystem/fsp_srv.h
+++ b/src/core/hle/service/filesystem/fsp_srv.h
@@ -16,7 +16,7 @@ namespace Service::FileSystem {
16class FSP_SRV final : public ServiceFramework<FSP_SRV> { 16class FSP_SRV final : public ServiceFramework<FSP_SRV> {
17public: 17public:
18 explicit FSP_SRV(); 18 explicit FSP_SRV();
19 ~FSP_SRV() = default; 19 ~FSP_SRV() override;
20 20
21private: 21private:
22 void Initialize(Kernel::HLERequestContext& ctx); 22 void Initialize(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/friend/friend.cpp b/src/core/hle/service/friend/friend.cpp
index f2b0e509a..d9225d624 100644
--- a/src/core/hle/service/friend/friend.cpp
+++ b/src/core/hle/service/friend/friend.cpp
@@ -118,6 +118,8 @@ void Module::Interface::CreateFriendService(Kernel::HLERequestContext& ctx) {
118Module::Interface::Interface(std::shared_ptr<Module> module, const char* name) 118Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
119 : ServiceFramework(name), module(std::move(module)) {} 119 : ServiceFramework(name), module(std::move(module)) {}
120 120
121Module::Interface::~Interface() = default;
122
121void InstallInterfaces(SM::ServiceManager& service_manager) { 123void InstallInterfaces(SM::ServiceManager& service_manager) {
122 auto module = std::make_shared<Module>(); 124 auto module = std::make_shared<Module>();
123 std::make_shared<Friend>(module, "friend:a")->InstallAsService(service_manager); 125 std::make_shared<Friend>(module, "friend:a")->InstallAsService(service_manager);
diff --git a/src/core/hle/service/friend/friend.h b/src/core/hle/service/friend/friend.h
index c1b36518a..e762840cb 100644
--- a/src/core/hle/service/friend/friend.h
+++ b/src/core/hle/service/friend/friend.h
@@ -13,6 +13,7 @@ public:
13 class Interface : public ServiceFramework<Interface> { 13 class Interface : public ServiceFramework<Interface> {
14 public: 14 public:
15 explicit Interface(std::shared_ptr<Module> module, const char* name); 15 explicit Interface(std::shared_ptr<Module> module, const char* name);
16 ~Interface() override;
16 17
17 void CreateFriendService(Kernel::HLERequestContext& ctx); 18 void CreateFriendService(Kernel::HLERequestContext& ctx);
18 19
diff --git a/src/core/hle/service/friend/interface.cpp b/src/core/hle/service/friend/interface.cpp
index 27c6a09e2..5a6840af5 100644
--- a/src/core/hle/service/friend/interface.cpp
+++ b/src/core/hle/service/friend/interface.cpp
@@ -16,4 +16,6 @@ Friend::Friend(std::shared_ptr<Module> module, const char* name)
16 RegisterHandlers(functions); 16 RegisterHandlers(functions);
17} 17}
18 18
19Friend::~Friend() = default;
20
19} // namespace Service::Friend 21} // namespace Service::Friend
diff --git a/src/core/hle/service/friend/interface.h b/src/core/hle/service/friend/interface.h
index 89dae8471..1963def39 100644
--- a/src/core/hle/service/friend/interface.h
+++ b/src/core/hle/service/friend/interface.h
@@ -11,6 +11,7 @@ namespace Service::Friend {
11class Friend final : public Module::Interface { 11class Friend final : public Module::Interface {
12public: 12public:
13 explicit Friend(std::shared_ptr<Module> module, const char* name); 13 explicit Friend(std::shared_ptr<Module> module, const char* name);
14 ~Friend() override;
14}; 15};
15 16
16} // namespace Service::Friend 17} // namespace Service::Friend
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 0d31abe8b..a8e0c869f 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -2,7 +2,6 @@
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 <atomic>
6#include "common/logging/log.h" 5#include "common/logging/log.h"
7#include "core/core.h" 6#include "core/core.h"
8#include "core/core_timing.h" 7#include "core/core_timing.h"
@@ -78,7 +77,7 @@ private:
78 SharedMemory mem{}; 77 SharedMemory mem{};
79 std::memcpy(&mem, shared_mem->GetPointer(), sizeof(SharedMemory)); 78 std::memcpy(&mem, shared_mem->GetPointer(), sizeof(SharedMemory));
80 79
81 if (is_device_reload_pending.exchange(false)) 80 if (Settings::values.is_device_reload_pending.exchange(false))
82 LoadInputDevices(); 81 LoadInputDevices();
83 82
84 // Set up controllers as neon red+blue Joy-Con attached to console 83 // Set up controllers as neon red+blue Joy-Con attached to console
@@ -267,7 +266,6 @@ private:
267 CoreTiming::EventType* pad_update_event; 266 CoreTiming::EventType* pad_update_event;
268 267
269 // Stored input state info 268 // Stored input state info
270 std::atomic<bool> is_device_reload_pending{true};
271 std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID> 269 std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID>
272 buttons; 270 buttons;
273 std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID> sticks; 271 std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID> sticks;
@@ -797,7 +795,9 @@ public:
797 } 795 }
798}; 796};
799 797
800void ReloadInputDevices() {} 798void ReloadInputDevices() {
799 Settings::values.is_device_reload_pending.store(true);
800}
801 801
802void InstallInterfaces(SM::ServiceManager& service_manager) { 802void InstallInterfaces(SM::ServiceManager& service_manager) {
803 std::make_shared<Hid>()->InstallAsService(service_manager); 803 std::make_shared<Hid>()->InstallAsService(service_manager);
diff --git a/src/core/hle/service/hid/irs.cpp b/src/core/hle/service/hid/irs.cpp
index aaf311912..e587ad0d8 100644
--- a/src/core/hle/service/hid/irs.cpp
+++ b/src/core/hle/service/hid/irs.cpp
@@ -33,6 +33,8 @@ IRS::IRS() : ServiceFramework{"irs"} {
33 RegisterHandlers(functions); 33 RegisterHandlers(functions);
34} 34}
35 35
36IRS::~IRS() = default;
37
36IRS_SYS::IRS_SYS() : ServiceFramework{"irs:sys"} { 38IRS_SYS::IRS_SYS() : ServiceFramework{"irs:sys"} {
37 // clang-format off 39 // clang-format off
38 static const FunctionInfo functions[] = { 40 static const FunctionInfo functions[] = {
@@ -46,4 +48,6 @@ IRS_SYS::IRS_SYS() : ServiceFramework{"irs:sys"} {
46 RegisterHandlers(functions); 48 RegisterHandlers(functions);
47} 49}
48 50
51IRS_SYS::~IRS_SYS() = default;
52
49} // namespace Service::HID 53} // namespace Service::HID
diff --git a/src/core/hle/service/hid/irs.h b/src/core/hle/service/hid/irs.h
index a8be701c7..6fb16b45d 100644
--- a/src/core/hle/service/hid/irs.h
+++ b/src/core/hle/service/hid/irs.h
@@ -11,11 +11,13 @@ namespace Service::HID {
11class IRS final : public ServiceFramework<IRS> { 11class IRS final : public ServiceFramework<IRS> {
12public: 12public:
13 explicit IRS(); 13 explicit IRS();
14 ~IRS() override;
14}; 15};
15 16
16class IRS_SYS final : public ServiceFramework<IRS_SYS> { 17class IRS_SYS final : public ServiceFramework<IRS_SYS> {
17public: 18public:
18 explicit IRS_SYS(); 19 explicit IRS_SYS();
20 ~IRS_SYS() override;
19}; 21};
20 22
21} // namespace Service::HID 23} // namespace Service::HID
diff --git a/src/core/hle/service/hid/xcd.cpp b/src/core/hle/service/hid/xcd.cpp
index 49f733f60..c8e9125f6 100644
--- a/src/core/hle/service/hid/xcd.cpp
+++ b/src/core/hle/service/hid/xcd.cpp
@@ -34,4 +34,6 @@ XCD_SYS::XCD_SYS() : ServiceFramework{"xcd:sys"} {
34 RegisterHandlers(functions); 34 RegisterHandlers(functions);
35} 35}
36 36
37XCD_SYS::~XCD_SYS() = default;
38
37} // namespace Service::HID 39} // namespace Service::HID
diff --git a/src/core/hle/service/hid/xcd.h b/src/core/hle/service/hid/xcd.h
index 232a044df..fd506d303 100644
--- a/src/core/hle/service/hid/xcd.h
+++ b/src/core/hle/service/hid/xcd.h
@@ -11,6 +11,7 @@ namespace Service::HID {
11class XCD_SYS final : public ServiceFramework<XCD_SYS> { 11class XCD_SYS final : public ServiceFramework<XCD_SYS> {
12public: 12public:
13 explicit XCD_SYS(); 13 explicit XCD_SYS();
14 ~XCD_SYS() override;
14}; 15};
15 16
16} // namespace Service::HID 17} // namespace Service::HID
diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp
index 4f7543af5..f8d2127d9 100644
--- a/src/core/hle/service/nfp/nfp.cpp
+++ b/src/core/hle/service/nfp/nfp.cpp
@@ -14,6 +14,8 @@ namespace Service::NFP {
14Module::Interface::Interface(std::shared_ptr<Module> module, const char* name) 14Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
15 : ServiceFramework(name), module(std::move(module)) {} 15 : ServiceFramework(name), module(std::move(module)) {}
16 16
17Module::Interface::~Interface() = default;
18
17class IUser final : public ServiceFramework<IUser> { 19class IUser final : public ServiceFramework<IUser> {
18public: 20public:
19 IUser() : ServiceFramework("IUser") { 21 IUser() : ServiceFramework("IUser") {
diff --git a/src/core/hle/service/nfp/nfp.h b/src/core/hle/service/nfp/nfp.h
index 0cd7be3d5..77df343c4 100644
--- a/src/core/hle/service/nfp/nfp.h
+++ b/src/core/hle/service/nfp/nfp.h
@@ -13,6 +13,7 @@ public:
13 class Interface : public ServiceFramework<Interface> { 13 class Interface : public ServiceFramework<Interface> {
14 public: 14 public:
15 explicit Interface(std::shared_ptr<Module> module, const char* name); 15 explicit Interface(std::shared_ptr<Module> module, const char* name);
16 ~Interface() override;
16 17
17 void CreateUserInterface(Kernel::HLERequestContext& ctx); 18 void CreateUserInterface(Kernel::HLERequestContext& ctx);
18 19
diff --git a/src/core/hle/service/nfp/nfp_user.cpp b/src/core/hle/service/nfp/nfp_user.cpp
index b608fe693..784a87c1b 100644
--- a/src/core/hle/service/nfp/nfp_user.cpp
+++ b/src/core/hle/service/nfp/nfp_user.cpp
@@ -14,4 +14,6 @@ NFP_User::NFP_User(std::shared_ptr<Module> module)
14 RegisterHandlers(functions); 14 RegisterHandlers(functions);
15} 15}
16 16
17NFP_User::~NFP_User() = default;
18
17} // namespace Service::NFP 19} // namespace Service::NFP
diff --git a/src/core/hle/service/nfp/nfp_user.h b/src/core/hle/service/nfp/nfp_user.h
index 700043114..65d9aaf48 100644
--- a/src/core/hle/service/nfp/nfp_user.h
+++ b/src/core/hle/service/nfp/nfp_user.h
@@ -11,6 +11,7 @@ namespace Service::NFP {
11class NFP_User final : public Module::Interface { 11class NFP_User final : public Module::Interface {
12public: 12public:
13 explicit NFP_User(std::shared_ptr<Module> module); 13 explicit NFP_User(std::shared_ptr<Module> module);
14 ~NFP_User() override;
14}; 15};
15 16
16} // namespace Service::NFP 17} // namespace Service::NFP
diff --git a/src/core/hle/service/ns/pl_u.cpp b/src/core/hle/service/ns/pl_u.cpp
index 878bbe439..da1c46d59 100644
--- a/src/core/hle/service/ns/pl_u.cpp
+++ b/src/core/hle/service/ns/pl_u.cpp
@@ -2,6 +2,13 @@
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 <FontChineseSimplified.h>
6#include <FontChineseTraditional.h>
7#include <FontExtendedChineseSimplified.h>
8#include <FontKorean.h>
9#include <FontNintendoExtended.h>
10#include <FontStandard.h>
11
5#include "common/common_paths.h" 12#include "common/common_paths.h"
6#include "common/file_util.h" 13#include "common/file_util.h"
7#include "core/core.h" 14#include "core/core.h"
@@ -218,11 +225,30 @@ PL_U::PL_U() : ServiceFramework("pl:u") {
218 file.ReadBytes(shared_font->data(), shared_font->size()); 225 file.ReadBytes(shared_font->data(), shared_font->size());
219 BuildSharedFontsRawRegions(*shared_font); 226 BuildSharedFontsRawRegions(*shared_font);
220 } else { 227 } else {
221 LOG_WARNING(Service_NS, "Unable to load shared font: {}", filepath); 228 LOG_WARNING(Service_NS,
229 "Shared Font file missing. Loading open source replacement from memory");
230
231 const std::vector<std::vector<u8>> open_source_shared_fonts_ttf = {
232 {std::begin(FontChineseSimplified), std::end(FontChineseSimplified)},
233 {std::begin(FontChineseTraditional), std::end(FontChineseTraditional)},
234 {std::begin(FontExtendedChineseSimplified),
235 std::end(FontExtendedChineseSimplified)},
236 {std::begin(FontNintendoExtended), std::end(FontNintendoExtended)},
237 {std::begin(FontStandard), std::end(FontStandard)},
238 };
239
240 for (const std::vector<u8>& font_ttf : open_source_shared_fonts_ttf) {
241 const FontRegion region{static_cast<u32>(offset + 8),
242 static_cast<u32>(font_ttf.size())};
243 EncryptSharedFont(font_ttf, *shared_font, offset);
244 SHARED_FONT_REGIONS.push_back(region);
245 }
222 } 246 }
223 } 247 }
224} 248}
225 249
250PL_U::~PL_U() = default;
251
226void PL_U::RequestLoad(Kernel::HLERequestContext& ctx) { 252void PL_U::RequestLoad(Kernel::HLERequestContext& ctx) {
227 IPC::RequestParser rp{ctx}; 253 IPC::RequestParser rp{ctx};
228 const u32 shared_font_type{rp.Pop<u32>()}; 254 const u32 shared_font_type{rp.Pop<u32>()};
diff --git a/src/core/hle/service/ns/pl_u.h b/src/core/hle/service/ns/pl_u.h
index fcc2acab7..296c3db05 100644
--- a/src/core/hle/service/ns/pl_u.h
+++ b/src/core/hle/service/ns/pl_u.h
@@ -13,7 +13,7 @@ namespace Service::NS {
13class PL_U final : public ServiceFramework<PL_U> { 13class PL_U final : public ServiceFramework<PL_U> {
14public: 14public:
15 PL_U(); 15 PL_U();
16 ~PL_U() = default; 16 ~PL_U() override;
17 17
18private: 18private:
19 void RequestLoad(Kernel::HLERequestContext& ctx); 19 void RequestLoad(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
index 0b37098e1..92acc57b1 100644
--- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
@@ -13,6 +13,9 @@
13 13
14namespace Service::Nvidia::Devices { 14namespace Service::Nvidia::Devices {
15 15
16nvdisp_disp0::nvdisp_disp0(std::shared_ptr<nvmap> nvmap_dev) : nvmap_dev(std::move(nvmap_dev)) {}
17nvdisp_disp0 ::~nvdisp_disp0() = default;
18
16u32 nvdisp_disp0::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { 19u32 nvdisp_disp0::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
17 UNIMPLEMENTED_MSG("Unimplemented ioctl"); 20 UNIMPLEMENTED_MSG("Unimplemented ioctl");
18 return 0; 21 return 0;
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h
index 6f0697b58..a45086e45 100644
--- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h
+++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h
@@ -17,8 +17,8 @@ class nvmap;
17 17
18class nvdisp_disp0 final : public nvdevice { 18class nvdisp_disp0 final : public nvdevice {
19public: 19public:
20 explicit nvdisp_disp0(std::shared_ptr<nvmap> nvmap_dev) : nvmap_dev(std::move(nvmap_dev)) {} 20 explicit nvdisp_disp0(std::shared_ptr<nvmap> nvmap_dev);
21 ~nvdisp_disp0() = default; 21 ~nvdisp_disp0();
22 22
23 u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override; 23 u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
24 24
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
index 75487c4e8..25d5a93fa 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
@@ -3,6 +3,8 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <cstring> 5#include <cstring>
6#include <utility>
7
6#include "common/assert.h" 8#include "common/assert.h"
7#include "common/logging/log.h" 9#include "common/logging/log.h"
8#include "core/core.h" 10#include "core/core.h"
@@ -14,6 +16,9 @@
14 16
15namespace Service::Nvidia::Devices { 17namespace Service::Nvidia::Devices {
16 18
19nvhost_as_gpu::nvhost_as_gpu(std::shared_ptr<nvmap> nvmap_dev) : nvmap_dev(std::move(nvmap_dev)) {}
20nvhost_as_gpu::~nvhost_as_gpu() = default;
21
17u32 nvhost_as_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { 22u32 nvhost_as_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
18 LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}", 23 LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
19 command.raw, input.size(), output.size()); 24 command.raw, input.size(), output.size());
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h
index 9f8999d9c..eb14b1da8 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h
@@ -6,7 +6,6 @@
6 6
7#include <memory> 7#include <memory>
8#include <unordered_map> 8#include <unordered_map>
9#include <utility>
10#include <vector> 9#include <vector>
11#include "common/common_types.h" 10#include "common/common_types.h"
12#include "common/swap.h" 11#include "common/swap.h"
@@ -18,8 +17,8 @@ class nvmap;
18 17
19class nvhost_as_gpu final : public nvdevice { 18class nvhost_as_gpu final : public nvdevice {
20public: 19public:
21 explicit nvhost_as_gpu(std::shared_ptr<nvmap> nvmap_dev) : nvmap_dev(std::move(nvmap_dev)) {} 20 explicit nvhost_as_gpu(std::shared_ptr<nvmap> nvmap_dev);
22 ~nvhost_as_gpu() override = default; 21 ~nvhost_as_gpu() override;
23 22
24 u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override; 23 u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
25 24
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
index 5685eb2be..b39fb9ef9 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
@@ -11,6 +11,9 @@
11 11
12namespace Service::Nvidia::Devices { 12namespace Service::Nvidia::Devices {
13 13
14nvhost_ctrl::nvhost_ctrl() = default;
15nvhost_ctrl::~nvhost_ctrl() = default;
16
14u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { 17u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
15 LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}", 18 LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
16 command.raw, input.size(), output.size()); 19 command.raw, input.size(), output.size());
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
index 6b496e9fe..6d0de2212 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
@@ -13,8 +13,8 @@ namespace Service::Nvidia::Devices {
13 13
14class nvhost_ctrl final : public nvdevice { 14class nvhost_ctrl final : public nvdevice {
15public: 15public:
16 nvhost_ctrl() = default; 16 nvhost_ctrl();
17 ~nvhost_ctrl() override = default; 17 ~nvhost_ctrl() override;
18 18
19 u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override; 19 u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
20 20
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
index ae421247d..7a88ae029 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
@@ -9,6 +9,9 @@
9 9
10namespace Service::Nvidia::Devices { 10namespace Service::Nvidia::Devices {
11 11
12nvhost_ctrl_gpu::nvhost_ctrl_gpu() = default;
13nvhost_ctrl_gpu::~nvhost_ctrl_gpu() = default;
14
12u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { 15u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
13 LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}", 16 LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
14 command.raw, input.size(), output.size()); 17 command.raw, input.size(), output.size());
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h
index f09113e67..3bbf028ad 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h
@@ -13,8 +13,8 @@ namespace Service::Nvidia::Devices {
13 13
14class nvhost_ctrl_gpu final : public nvdevice { 14class nvhost_ctrl_gpu final : public nvdevice {
15public: 15public:
16 nvhost_ctrl_gpu() = default; 16 nvhost_ctrl_gpu();
17 ~nvhost_ctrl_gpu() override = default; 17 ~nvhost_ctrl_gpu() override;
18 18
19 u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override; 19 u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
20 20
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
index 4cdf7f613..874d5e1c3 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
@@ -8,11 +8,15 @@
8#include "core/core.h" 8#include "core/core.h"
9#include "core/hle/service/nvdrv/devices/nvhost_gpu.h" 9#include "core/hle/service/nvdrv/devices/nvhost_gpu.h"
10#include "core/memory.h" 10#include "core/memory.h"
11#include "video_core/command_processor.h"
11#include "video_core/gpu.h" 12#include "video_core/gpu.h"
12#include "video_core/memory_manager.h" 13#include "video_core/memory_manager.h"
13 14
14namespace Service::Nvidia::Devices { 15namespace Service::Nvidia::Devices {
15 16
17nvhost_gpu::nvhost_gpu(std::shared_ptr<nvmap> nvmap_dev) : nvmap_dev(std::move(nvmap_dev)) {}
18nvhost_gpu::~nvhost_gpu() = default;
19
16u32 nvhost_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { 20u32 nvhost_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
17 LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}", 21 LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
18 command.raw, input.size(), output.size()); 22 command.raw, input.size(), output.size());
@@ -134,17 +138,16 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& outp
134 LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}", 138 LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}",
135 params.address, params.num_entries, params.flags); 139 params.address, params.num_entries, params.flags);
136 140
137 ASSERT_MSG(input.size() == 141 ASSERT_MSG(input.size() == sizeof(IoctlSubmitGpfifo) +
138 sizeof(IoctlSubmitGpfifo) + params.num_entries * sizeof(IoctlGpfifoEntry), 142 params.num_entries * sizeof(Tegra::CommandListHeader),
139 "Incorrect input size"); 143 "Incorrect input size");
140 144
141 std::vector<IoctlGpfifoEntry> entries(params.num_entries); 145 std::vector<Tegra::CommandListHeader> entries(params.num_entries);
142 std::memcpy(entries.data(), &input[sizeof(IoctlSubmitGpfifo)], 146 std::memcpy(entries.data(), &input[sizeof(IoctlSubmitGpfifo)],
143 params.num_entries * sizeof(IoctlGpfifoEntry)); 147 params.num_entries * sizeof(Tegra::CommandListHeader));
144 for (auto entry : entries) { 148
145 Tegra::GPUVAddr va_addr = entry.Address(); 149 Core::System::GetInstance().GPU().ProcessCommandLists(entries);
146 Core::System::GetInstance().GPU().ProcessCommandList(va_addr, entry.sz); 150
147 }
148 params.fence_out.id = 0; 151 params.fence_out.id = 0;
149 params.fence_out.value = 0; 152 params.fence_out.value = 0;
150 std::memcpy(output.data(), &params, sizeof(IoctlSubmitGpfifo)); 153 std::memcpy(output.data(), &params, sizeof(IoctlSubmitGpfifo));
@@ -160,14 +163,12 @@ u32 nvhost_gpu::KickoffPB(const std::vector<u8>& input, std::vector<u8>& output)
160 LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}", 163 LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}",
161 params.address, params.num_entries, params.flags); 164 params.address, params.num_entries, params.flags);
162 165
163 std::vector<IoctlGpfifoEntry> entries(params.num_entries); 166 std::vector<Tegra::CommandListHeader> entries(params.num_entries);
164 Memory::ReadBlock(params.address, entries.data(), 167 Memory::ReadBlock(params.address, entries.data(),
165 params.num_entries * sizeof(IoctlGpfifoEntry)); 168 params.num_entries * sizeof(Tegra::CommandListHeader));
169
170 Core::System::GetInstance().GPU().ProcessCommandLists(entries);
166 171
167 for (auto entry : entries) {
168 Tegra::GPUVAddr va_addr = entry.Address();
169 Core::System::GetInstance().GPU().ProcessCommandList(va_addr, entry.sz);
170 }
171 params.fence_out.id = 0; 172 params.fence_out.id = 0;
172 params.fence_out.value = 0; 173 params.fence_out.value = 0;
173 std::memcpy(output.data(), &params, output.size()); 174 std::memcpy(output.data(), &params, output.size());
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
index 03b7356d0..62beb5c0c 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
@@ -10,7 +10,6 @@
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "common/swap.h" 11#include "common/swap.h"
12#include "core/hle/service/nvdrv/devices/nvdevice.h" 12#include "core/hle/service/nvdrv/devices/nvdevice.h"
13#include "video_core/memory_manager.h"
14 13
15namespace Service::Nvidia::Devices { 14namespace Service::Nvidia::Devices {
16 15
@@ -21,8 +20,8 @@ constexpr u32 NVGPU_IOCTL_CHANNEL_KICKOFF_PB(0x1b);
21 20
22class nvhost_gpu final : public nvdevice { 21class nvhost_gpu final : public nvdevice {
23public: 22public:
24 explicit nvhost_gpu(std::shared_ptr<nvmap> nvmap_dev) : nvmap_dev(std::move(nvmap_dev)) {} 23 explicit nvhost_gpu(std::shared_ptr<nvmap> nvmap_dev);
25 ~nvhost_gpu() override = default; 24 ~nvhost_gpu() override;
26 25
27 u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override; 26 u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
28 27
@@ -151,22 +150,6 @@ private:
151 }; 150 };
152 static_assert(sizeof(IoctlAllocObjCtx) == 16, "IoctlAllocObjCtx is incorrect size"); 151 static_assert(sizeof(IoctlAllocObjCtx) == 16, "IoctlAllocObjCtx is incorrect size");
153 152
154 struct IoctlGpfifoEntry {
155 u32_le entry0; // gpu_va_lo
156 union {
157 u32_le entry1; // gpu_va_hi | (unk_0x02 << 0x08) | (size << 0x0A) | (unk_0x01 << 0x1F)
158 BitField<0, 8, u32_le> gpu_va_hi;
159 BitField<8, 2, u32_le> unk1;
160 BitField<10, 21, u32_le> sz;
161 BitField<31, 1, u32_le> unk2;
162 };
163
164 Tegra::GPUVAddr Address() const {
165 return (static_cast<Tegra::GPUVAddr>(gpu_va_hi) << 32) | entry0;
166 }
167 };
168 static_assert(sizeof(IoctlGpfifoEntry) == 8, "IoctlGpfifoEntry is incorrect size");
169
170 struct IoctlSubmitGpfifo { 153 struct IoctlSubmitGpfifo {
171 u64_le address; // pointer to gpfifo entry structs 154 u64_le address; // pointer to gpfifo entry structs
172 u32_le num_entries; // number of fence objects being submitted 155 u32_le num_entries; // number of fence objects being submitted
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
index 364619e67..46dbbc37c 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
@@ -10,6 +10,9 @@
10 10
11namespace Service::Nvidia::Devices { 11namespace Service::Nvidia::Devices {
12 12
13nvhost_nvdec::nvhost_nvdec() = default;
14nvhost_nvdec::~nvhost_nvdec() = default;
15
13u32 nvhost_nvdec::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { 16u32 nvhost_nvdec::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
14 LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}", 17 LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
15 command.raw, input.size(), output.size()); 18 command.raw, input.size(), output.size());
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h
index 6ad74421b..0e7b284f8 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h
@@ -13,8 +13,8 @@ namespace Service::Nvidia::Devices {
13 13
14class nvhost_nvdec final : public nvdevice { 14class nvhost_nvdec final : public nvdevice {
15public: 15public:
16 nvhost_nvdec() = default; 16 nvhost_nvdec();
17 ~nvhost_nvdec() override = default; 17 ~nvhost_nvdec() override;
18 18
19 u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override; 19 u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
20 20
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp
index 51f01077b..c67f934f6 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp
@@ -10,6 +10,9 @@
10 10
11namespace Service::Nvidia::Devices { 11namespace Service::Nvidia::Devices {
12 12
13nvhost_nvjpg::nvhost_nvjpg() = default;
14nvhost_nvjpg::~nvhost_nvjpg() = default;
15
13u32 nvhost_nvjpg::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { 16u32 nvhost_nvjpg::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
14 LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}", 17 LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
15 command.raw, input.size(), output.size()); 18 command.raw, input.size(), output.size());
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h
index 2b0eb43ee..89fd5e95e 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h
@@ -13,8 +13,8 @@ namespace Service::Nvidia::Devices {
13 13
14class nvhost_nvjpg final : public nvdevice { 14class nvhost_nvjpg final : public nvdevice {
15public: 15public:
16 nvhost_nvjpg() = default; 16 nvhost_nvjpg();
17 ~nvhost_nvjpg() override = default; 17 ~nvhost_nvjpg() override;
18 18
19 u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override; 19 u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
20 20
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
index fcb488d50..727b9fee4 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
@@ -10,6 +10,9 @@
10 10
11namespace Service::Nvidia::Devices { 11namespace Service::Nvidia::Devices {
12 12
13nvhost_vic::nvhost_vic() = default;
14nvhost_vic::~nvhost_vic() = default;
15
13u32 nvhost_vic::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { 16u32 nvhost_vic::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
14 LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}", 17 LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
15 command.raw, input.size(), output.size()); 18 command.raw, input.size(), output.size());
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.h b/src/core/hle/service/nvdrv/devices/nvhost_vic.h
index c7d681e52..fc24c3f9c 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_vic.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.h
@@ -13,8 +13,8 @@ namespace Service::Nvidia::Devices {
13 13
14class nvhost_vic final : public nvdevice { 14class nvhost_vic final : public nvdevice {
15public: 15public:
16 nvhost_vic() = default; 16 nvhost_vic();
17 ~nvhost_vic() override = default; 17 ~nvhost_vic() override;
18 18
19 u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override; 19 u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
20 20
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp
index e9305bfb3..a2287cc1b 100644
--- a/src/core/hle/service/nvdrv/devices/nvmap.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp
@@ -11,6 +11,9 @@
11 11
12namespace Service::Nvidia::Devices { 12namespace Service::Nvidia::Devices {
13 13
14nvmap::nvmap() = default;
15nvmap::~nvmap() = default;
16
14VAddr nvmap::GetObjectAddress(u32 handle) const { 17VAddr nvmap::GetObjectAddress(u32 handle) const {
15 auto object = GetObject(handle); 18 auto object = GetObject(handle);
16 ASSERT(object); 19 ASSERT(object);
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.h b/src/core/hle/service/nvdrv/devices/nvmap.h
index f2eec6409..396230c19 100644
--- a/src/core/hle/service/nvdrv/devices/nvmap.h
+++ b/src/core/hle/service/nvdrv/devices/nvmap.h
@@ -16,8 +16,8 @@ namespace Service::Nvidia::Devices {
16 16
17class nvmap final : public nvdevice { 17class nvmap final : public nvdevice {
18public: 18public:
19 nvmap() = default; 19 nvmap();
20 ~nvmap() override = default; 20 ~nvmap() override;
21 21
22 /// Returns the allocated address of an nvmap object given its handle. 22 /// Returns the allocated address of an nvmap object given its handle.
23 VAddr GetObjectAddress(u32 handle) const; 23 VAddr GetObjectAddress(u32 handle) const;
diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp
index 634ab9196..ac3859353 100644
--- a/src/core/hle/service/nvdrv/interface.cpp
+++ b/src/core/hle/service/nvdrv/interface.cpp
@@ -112,4 +112,6 @@ NVDRV::NVDRV(std::shared_ptr<Module> nvdrv, const char* name)
112 query_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "NVDRV::query_event"); 112 query_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "NVDRV::query_event");
113} 113}
114 114
115NVDRV::~NVDRV() = default;
116
115} // namespace Service::Nvidia 117} // namespace Service::Nvidia
diff --git a/src/core/hle/service/nvdrv/interface.h b/src/core/hle/service/nvdrv/interface.h
index 1c3529bb6..d340893c2 100644
--- a/src/core/hle/service/nvdrv/interface.h
+++ b/src/core/hle/service/nvdrv/interface.h
@@ -14,7 +14,7 @@ namespace Service::Nvidia {
14class NVDRV final : public ServiceFramework<NVDRV> { 14class NVDRV final : public ServiceFramework<NVDRV> {
15public: 15public:
16 NVDRV(std::shared_ptr<Module> nvdrv, const char* name); 16 NVDRV(std::shared_ptr<Module> nvdrv, const char* name);
17 ~NVDRV() = default; 17 ~NVDRV();
18 18
19private: 19private:
20 void Open(Kernel::HLERequestContext& ctx); 20 void Open(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp
index 2de39822f..6e4b8f2c6 100644
--- a/src/core/hle/service/nvdrv/nvdrv.cpp
+++ b/src/core/hle/service/nvdrv/nvdrv.cpp
@@ -45,6 +45,8 @@ Module::Module() {
45 devices["/dev/nvhost-vic"] = std::make_shared<Devices::nvhost_vic>(); 45 devices["/dev/nvhost-vic"] = std::make_shared<Devices::nvhost_vic>();
46} 46}
47 47
48Module::~Module() = default;
49
48u32 Module::Open(const std::string& device_name) { 50u32 Module::Open(const std::string& device_name) {
49 ASSERT_MSG(devices.find(device_name) != devices.end(), "Trying to open unknown device {}", 51 ASSERT_MSG(devices.find(device_name) != devices.end(), "Trying to open unknown device {}",
50 device_name); 52 device_name);
diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h
index 99eb1128a..53564f696 100644
--- a/src/core/hle/service/nvdrv/nvdrv.h
+++ b/src/core/hle/service/nvdrv/nvdrv.h
@@ -30,7 +30,7 @@ static_assert(sizeof(IoctlFence) == 8, "IoctlFence has wrong size");
30class Module final { 30class Module final {
31public: 31public:
32 Module(); 32 Module();
33 ~Module() = default; 33 ~Module();
34 34
35 /// Returns a pointer to one of the available devices, identified by its name. 35 /// Returns a pointer to one of the available devices, identified by its name.
36 template <typename T> 36 template <typename T>
diff --git a/src/core/hle/service/nvdrv/nvmemp.cpp b/src/core/hle/service/nvdrv/nvmemp.cpp
index 0e8e21bad..b7b8b7a1b 100644
--- a/src/core/hle/service/nvdrv/nvmemp.cpp
+++ b/src/core/hle/service/nvdrv/nvmemp.cpp
@@ -16,6 +16,8 @@ NVMEMP::NVMEMP() : ServiceFramework("nvmemp") {
16 RegisterHandlers(functions); 16 RegisterHandlers(functions);
17} 17}
18 18
19NVMEMP::~NVMEMP() = default;
20
19void NVMEMP::Cmd0(Kernel::HLERequestContext& ctx) { 21void NVMEMP::Cmd0(Kernel::HLERequestContext& ctx) {
20 UNIMPLEMENTED(); 22 UNIMPLEMENTED();
21} 23}
diff --git a/src/core/hle/service/nvdrv/nvmemp.h b/src/core/hle/service/nvdrv/nvmemp.h
index dfdcabf4a..5a4dfc1f9 100644
--- a/src/core/hle/service/nvdrv/nvmemp.h
+++ b/src/core/hle/service/nvdrv/nvmemp.h
@@ -11,7 +11,7 @@ namespace Service::Nvidia {
11class NVMEMP final : public ServiceFramework<NVMEMP> { 11class NVMEMP final : public ServiceFramework<NVMEMP> {
12public: 12public:
13 NVMEMP(); 13 NVMEMP();
14 ~NVMEMP() = default; 14 ~NVMEMP();
15 15
16private: 16private:
17 void Cmd0(Kernel::HLERequestContext& ctx); 17 void Cmd0(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp
index 8d8962276..34f98fe5a 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.cpp
+++ b/src/core/hle/service/nvflinger/buffer_queue.cpp
@@ -18,6 +18,8 @@ BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) {
18 Kernel::Event::Create(kernel, Kernel::ResetType::Sticky, "BufferQueue NativeHandle"); 18 Kernel::Event::Create(kernel, Kernel::ResetType::Sticky, "BufferQueue NativeHandle");
19} 19}
20 20
21BufferQueue::~BufferQueue() = default;
22
21void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer) { 23void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer) {
22 Buffer buffer{}; 24 Buffer buffer{};
23 buffer.slot = slot; 25 buffer.slot = slot;
diff --git a/src/core/hle/service/nvflinger/buffer_queue.h b/src/core/hle/service/nvflinger/buffer_queue.h
index db2e17c0c..17c81928a 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.h
+++ b/src/core/hle/service/nvflinger/buffer_queue.h
@@ -46,7 +46,7 @@ public:
46 }; 46 };
47 47
48 BufferQueue(u32 id, u64 layer_id); 48 BufferQueue(u32 id, u64 layer_id);
49 ~BufferQueue() = default; 49 ~BufferQueue();
50 50
51 enum class BufferTransformFlags : u32 { 51 enum class BufferTransformFlags : u32 {
52 /// No transform flags are set 52 /// No transform flags are set
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index 06040da6f..7455ddd19 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -160,10 +160,13 @@ void NVFlinger::Compose() {
160} 160}
161 161
162Layer::Layer(u64 id, std::shared_ptr<BufferQueue> queue) : id(id), buffer_queue(std::move(queue)) {} 162Layer::Layer(u64 id, std::shared_ptr<BufferQueue> queue) : id(id), buffer_queue(std::move(queue)) {}
163Layer::~Layer() = default;
163 164
164Display::Display(u64 id, std::string name) : id(id), name(std::move(name)) { 165Display::Display(u64 id, std::string name) : id(id), name(std::move(name)) {
165 auto& kernel = Core::System::GetInstance().Kernel(); 166 auto& kernel = Core::System::GetInstance().Kernel();
166 vsync_event = Kernel::Event::Create(kernel, Kernel::ResetType::Pulse, "Display VSync Event"); 167 vsync_event = Kernel::Event::Create(kernel, Kernel::ResetType::Pulse, "Display VSync Event");
167} 168}
168 169
170Display::~Display() = default;
171
169} // namespace Service::NVFlinger 172} // namespace Service::NVFlinger
diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h
index f7112949f..3dc69e69b 100644
--- a/src/core/hle/service/nvflinger/nvflinger.h
+++ b/src/core/hle/service/nvflinger/nvflinger.h
@@ -26,7 +26,7 @@ class BufferQueue;
26 26
27struct Layer { 27struct Layer {
28 Layer(u64 id, std::shared_ptr<BufferQueue> queue); 28 Layer(u64 id, std::shared_ptr<BufferQueue> queue);
29 ~Layer() = default; 29 ~Layer();
30 30
31 u64 id; 31 u64 id;
32 std::shared_ptr<BufferQueue> buffer_queue; 32 std::shared_ptr<BufferQueue> buffer_queue;
@@ -34,7 +34,7 @@ struct Layer {
34 34
35struct Display { 35struct Display {
36 Display(u64 id, std::string name); 36 Display(u64 id, std::string name);
37 ~Display() = default; 37 ~Display();
38 38
39 u64 id; 39 u64 id;
40 std::string name; 40 std::string name;
diff --git a/src/core/hle/service/pctl/module.cpp b/src/core/hle/service/pctl/module.cpp
index 6cc3b1992..4fd185f69 100644
--- a/src/core/hle/service/pctl/module.cpp
+++ b/src/core/hle/service/pctl/module.cpp
@@ -142,6 +142,8 @@ void Module::Interface::CreateServiceWithoutInitialize(Kernel::HLERequestContext
142Module::Interface::Interface(std::shared_ptr<Module> module, const char* name) 142Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
143 : ServiceFramework(name), module(std::move(module)) {} 143 : ServiceFramework(name), module(std::move(module)) {}
144 144
145Module::Interface::~Interface() = default;
146
145void InstallInterfaces(SM::ServiceManager& service_manager) { 147void InstallInterfaces(SM::ServiceManager& service_manager) {
146 auto module = std::make_shared<Module>(); 148 auto module = std::make_shared<Module>();
147 std::make_shared<PCTL>(module, "pctl")->InstallAsService(service_manager); 149 std::make_shared<PCTL>(module, "pctl")->InstallAsService(service_manager);
diff --git a/src/core/hle/service/pctl/module.h b/src/core/hle/service/pctl/module.h
index e7d492760..3e449110d 100644
--- a/src/core/hle/service/pctl/module.h
+++ b/src/core/hle/service/pctl/module.h
@@ -13,6 +13,7 @@ public:
13 class Interface : public ServiceFramework<Interface> { 13 class Interface : public ServiceFramework<Interface> {
14 public: 14 public:
15 explicit Interface(std::shared_ptr<Module> module, const char* name); 15 explicit Interface(std::shared_ptr<Module> module, const char* name);
16 ~Interface() override;
16 17
17 void CreateService(Kernel::HLERequestContext& ctx); 18 void CreateService(Kernel::HLERequestContext& ctx);
18 void CreateServiceWithoutInitialize(Kernel::HLERequestContext& ctx); 19 void CreateServiceWithoutInitialize(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/pctl/pctl.cpp b/src/core/hle/service/pctl/pctl.cpp
index de2741d66..af9d1433a 100644
--- a/src/core/hle/service/pctl/pctl.cpp
+++ b/src/core/hle/service/pctl/pctl.cpp
@@ -14,4 +14,6 @@ PCTL::PCTL(std::shared_ptr<Module> module, const char* name)
14 }; 14 };
15 RegisterHandlers(functions); 15 RegisterHandlers(functions);
16} 16}
17
18PCTL::~PCTL() = default;
17} // namespace Service::PCTL 19} // namespace Service::PCTL
diff --git a/src/core/hle/service/pctl/pctl.h b/src/core/hle/service/pctl/pctl.h
index 8ddf69128..c33ea80b6 100644
--- a/src/core/hle/service/pctl/pctl.h
+++ b/src/core/hle/service/pctl/pctl.h
@@ -11,6 +11,7 @@ namespace Service::PCTL {
11class PCTL final : public Module::Interface { 11class PCTL final : public Module::Interface {
12public: 12public:
13 explicit PCTL(std::shared_ptr<Module> module, const char* name); 13 explicit PCTL(std::shared_ptr<Module> module, const char* name);
14 ~PCTL() override;
14}; 15};
15 16
16} // namespace Service::PCTL 17} // namespace Service::PCTL
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 9d804652e..9bb7c7b26 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -74,8 +74,6 @@ using Kernel::SharedPtr;
74 74
75namespace Service { 75namespace Service {
76 76
77std::unordered_map<std::string, SharedPtr<ClientPort>> g_kernel_named_ports;
78
79/** 77/**
80 * Creates a function string for logging, complete with the name (or header code, depending 78 * Creates a function string for logging, complete with the name (or header code, depending
81 * on what's passed in) the port name, and all the cmd_buff arguments. 79 * on what's passed in) the port name, and all the cmd_buff arguments.
diff --git a/src/core/hle/service/set/set.cpp b/src/core/hle/service/set/set.cpp
index 92b0640e8..59eb20155 100644
--- a/src/core/hle/service/set/set.cpp
+++ b/src/core/hle/service/set/set.cpp
@@ -112,4 +112,6 @@ SET::SET() : ServiceFramework("set") {
112 RegisterHandlers(functions); 112 RegisterHandlers(functions);
113} 113}
114 114
115SET::~SET() = default;
116
115} // namespace Service::Set 117} // namespace Service::Set
diff --git a/src/core/hle/service/set/set.h b/src/core/hle/service/set/set.h
index 669e740b7..5f0214359 100644
--- a/src/core/hle/service/set/set.h
+++ b/src/core/hle/service/set/set.h
@@ -33,7 +33,7 @@ LanguageCode GetLanguageCodeFromIndex(size_t idx);
33class SET final : public ServiceFramework<SET> { 33class SET final : public ServiceFramework<SET> {
34public: 34public:
35 explicit SET(); 35 explicit SET();
36 ~SET() = default; 36 ~SET() override;
37 37
38private: 38private:
39 void GetLanguageCode(Kernel::HLERequestContext& ctx); 39 void GetLanguageCode(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/set/set_cal.cpp b/src/core/hle/service/set/set_cal.cpp
index 7066ef725..5af356d10 100644
--- a/src/core/hle/service/set/set_cal.cpp
+++ b/src/core/hle/service/set/set_cal.cpp
@@ -44,4 +44,6 @@ SET_CAL::SET_CAL() : ServiceFramework("set:cal") {
44 RegisterHandlers(functions); 44 RegisterHandlers(functions);
45} 45}
46 46
47SET_CAL::~SET_CAL() = default;
48
47} // namespace Service::Set 49} // namespace Service::Set
diff --git a/src/core/hle/service/set/set_cal.h b/src/core/hle/service/set/set_cal.h
index bb50336aa..583036eac 100644
--- a/src/core/hle/service/set/set_cal.h
+++ b/src/core/hle/service/set/set_cal.h
@@ -11,7 +11,7 @@ namespace Service::Set {
11class SET_CAL final : public ServiceFramework<SET_CAL> { 11class SET_CAL final : public ServiceFramework<SET_CAL> {
12public: 12public:
13 explicit SET_CAL(); 13 explicit SET_CAL();
14 ~SET_CAL() = default; 14 ~SET_CAL();
15}; 15};
16 16
17} // namespace Service::Set 17} // namespace Service::Set
diff --git a/src/core/hle/service/set/set_fd.cpp b/src/core/hle/service/set/set_fd.cpp
index c9f938716..cac6af86d 100644
--- a/src/core/hle/service/set/set_fd.cpp
+++ b/src/core/hle/service/set/set_fd.cpp
@@ -20,4 +20,6 @@ SET_FD::SET_FD() : ServiceFramework("set:fd") {
20 RegisterHandlers(functions); 20 RegisterHandlers(functions);
21} 21}
22 22
23SET_FD::~SET_FD() = default;
24
23} // namespace Service::Set 25} // namespace Service::Set
diff --git a/src/core/hle/service/set/set_fd.h b/src/core/hle/service/set/set_fd.h
index dbd850bc7..216e65f1f 100644
--- a/src/core/hle/service/set/set_fd.h
+++ b/src/core/hle/service/set/set_fd.h
@@ -11,7 +11,7 @@ namespace Service::Set {
11class SET_FD final : public ServiceFramework<SET_FD> { 11class SET_FD final : public ServiceFramework<SET_FD> {
12public: 12public:
13 explicit SET_FD(); 13 explicit SET_FD();
14 ~SET_FD() = default; 14 ~SET_FD() override;
15}; 15};
16 16
17} // namespace Service::Set 17} // namespace Service::Set
diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp
index 3211a8346..4342f3b2d 100644
--- a/src/core/hle/service/sockets/bsd.cpp
+++ b/src/core/hle/service/sockets/bsd.cpp
@@ -109,6 +109,8 @@ BSD::BSD(const char* name) : ServiceFramework(name) {
109 RegisterHandlers(functions); 109 RegisterHandlers(functions);
110} 110}
111 111
112BSD::~BSD() = default;
113
112BSDCFG::BSDCFG() : ServiceFramework{"bsdcfg"} { 114BSDCFG::BSDCFG() : ServiceFramework{"bsdcfg"} {
113 // clang-format off 115 // clang-format off
114 static const FunctionInfo functions[] = { 116 static const FunctionInfo functions[] = {
@@ -131,4 +133,6 @@ BSDCFG::BSDCFG() : ServiceFramework{"bsdcfg"} {
131 RegisterHandlers(functions); 133 RegisterHandlers(functions);
132} 134}
133 135
136BSDCFG::~BSDCFG() = default;
137
134} // namespace Service::Sockets 138} // namespace Service::Sockets
diff --git a/src/core/hle/service/sockets/bsd.h b/src/core/hle/service/sockets/bsd.h
index c1da59b24..0fe0e65c6 100644
--- a/src/core/hle/service/sockets/bsd.h
+++ b/src/core/hle/service/sockets/bsd.h
@@ -12,7 +12,7 @@ namespace Service::Sockets {
12class BSD final : public ServiceFramework<BSD> { 12class BSD final : public ServiceFramework<BSD> {
13public: 13public:
14 explicit BSD(const char* name); 14 explicit BSD(const char* name);
15 ~BSD() = default; 15 ~BSD() override;
16 16
17private: 17private:
18 void RegisterClient(Kernel::HLERequestContext& ctx); 18 void RegisterClient(Kernel::HLERequestContext& ctx);
@@ -29,6 +29,7 @@ private:
29class BSDCFG final : public ServiceFramework<BSDCFG> { 29class BSDCFG final : public ServiceFramework<BSDCFG> {
30public: 30public:
31 explicit BSDCFG(); 31 explicit BSDCFG();
32 ~BSDCFG() override;
32}; 33};
33 34
34} // namespace Service::Sockets 35} // namespace Service::Sockets
diff --git a/src/core/hle/service/sockets/ethc.cpp b/src/core/hle/service/sockets/ethc.cpp
index d53c25eec..abbeb4c50 100644
--- a/src/core/hle/service/sockets/ethc.cpp
+++ b/src/core/hle/service/sockets/ethc.cpp
@@ -21,6 +21,8 @@ ETHC_C::ETHC_C() : ServiceFramework{"ethc:c"} {
21 RegisterHandlers(functions); 21 RegisterHandlers(functions);
22} 22}
23 23
24ETHC_C::~ETHC_C() = default;
25
24ETHC_I::ETHC_I() : ServiceFramework{"ethc:i"} { 26ETHC_I::ETHC_I() : ServiceFramework{"ethc:i"} {
25 // clang-format off 27 // clang-format off
26 static const FunctionInfo functions[] = { 28 static const FunctionInfo functions[] = {
@@ -35,4 +37,6 @@ ETHC_I::ETHC_I() : ServiceFramework{"ethc:i"} {
35 RegisterHandlers(functions); 37 RegisterHandlers(functions);
36} 38}
37 39
40ETHC_I::~ETHC_I() = default;
41
38} // namespace Service::Sockets 42} // namespace Service::Sockets
diff --git a/src/core/hle/service/sockets/ethc.h b/src/core/hle/service/sockets/ethc.h
index 9a3c88100..da2c7f741 100644
--- a/src/core/hle/service/sockets/ethc.h
+++ b/src/core/hle/service/sockets/ethc.h
@@ -11,11 +11,13 @@ namespace Service::Sockets {
11class ETHC_C final : public ServiceFramework<ETHC_C> { 11class ETHC_C final : public ServiceFramework<ETHC_C> {
12public: 12public:
13 explicit ETHC_C(); 13 explicit ETHC_C();
14 ~ETHC_C() override;
14}; 15};
15 16
16class ETHC_I final : public ServiceFramework<ETHC_I> { 17class ETHC_I final : public ServiceFramework<ETHC_I> {
17public: 18public:
18 explicit ETHC_I(); 19 explicit ETHC_I();
20 ~ETHC_I() override;
19}; 21};
20 22
21} // namespace Service::Sockets 23} // namespace Service::Sockets
diff --git a/src/core/hle/service/sockets/nsd.cpp b/src/core/hle/service/sockets/nsd.cpp
index 8682dc2e0..e6d73065e 100644
--- a/src/core/hle/service/sockets/nsd.cpp
+++ b/src/core/hle/service/sockets/nsd.cpp
@@ -29,4 +29,6 @@ NSD::NSD(const char* name) : ServiceFramework(name) {
29 RegisterHandlers(functions); 29 RegisterHandlers(functions);
30} 30}
31 31
32NSD::~NSD() = default;
33
32} // namespace Service::Sockets 34} // namespace Service::Sockets
diff --git a/src/core/hle/service/sockets/nsd.h b/src/core/hle/service/sockets/nsd.h
index 3b7edfc43..d842e3232 100644
--- a/src/core/hle/service/sockets/nsd.h
+++ b/src/core/hle/service/sockets/nsd.h
@@ -12,7 +12,7 @@ namespace Service::Sockets {
12class NSD final : public ServiceFramework<NSD> { 12class NSD final : public ServiceFramework<NSD> {
13public: 13public:
14 explicit NSD(const char* name); 14 explicit NSD(const char* name);
15 ~NSD() = default; 15 ~NSD() override;
16}; 16};
17 17
18} // namespace Service::Sockets 18} // namespace Service::Sockets
diff --git a/src/core/hle/service/sockets/sfdnsres.cpp b/src/core/hle/service/sockets/sfdnsres.cpp
index d235c4cfd..13ab1d31e 100644
--- a/src/core/hle/service/sockets/sfdnsres.cpp
+++ b/src/core/hle/service/sockets/sfdnsres.cpp
@@ -34,4 +34,6 @@ SFDNSRES::SFDNSRES() : ServiceFramework("sfdnsres") {
34 RegisterHandlers(functions); 34 RegisterHandlers(functions);
35} 35}
36 36
37SFDNSRES::~SFDNSRES() = default;
38
37} // namespace Service::Sockets 39} // namespace Service::Sockets
diff --git a/src/core/hle/service/sockets/sfdnsres.h b/src/core/hle/service/sockets/sfdnsres.h
index 62c7e35bf..eda432903 100644
--- a/src/core/hle/service/sockets/sfdnsres.h
+++ b/src/core/hle/service/sockets/sfdnsres.h
@@ -12,7 +12,7 @@ namespace Service::Sockets {
12class SFDNSRES final : public ServiceFramework<SFDNSRES> { 12class SFDNSRES final : public ServiceFramework<SFDNSRES> {
13public: 13public:
14 explicit SFDNSRES(); 14 explicit SFDNSRES();
15 ~SFDNSRES() = default; 15 ~SFDNSRES() override;
16 16
17private: 17private:
18 void GetAddrInfo(Kernel::HLERequestContext& ctx); 18 void GetAddrInfo(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/spl/csrng.cpp b/src/core/hle/service/spl/csrng.cpp
index b9e6b799d..674928798 100644
--- a/src/core/hle/service/spl/csrng.cpp
+++ b/src/core/hle/service/spl/csrng.cpp
@@ -13,4 +13,6 @@ CSRNG::CSRNG(std::shared_ptr<Module> module) : Module::Interface(std::move(modul
13 RegisterHandlers(functions); 13 RegisterHandlers(functions);
14} 14}
15 15
16CSRNG::~CSRNG() = default;
17
16} // namespace Service::SPL 18} // namespace Service::SPL
diff --git a/src/core/hle/service/spl/csrng.h b/src/core/hle/service/spl/csrng.h
index 3f849b5a7..764d5ceb0 100644
--- a/src/core/hle/service/spl/csrng.h
+++ b/src/core/hle/service/spl/csrng.h
@@ -11,6 +11,7 @@ namespace Service::SPL {
11class CSRNG final : public Module::Interface { 11class CSRNG final : public Module::Interface {
12public: 12public:
13 explicit CSRNG(std::shared_ptr<Module> module); 13 explicit CSRNG(std::shared_ptr<Module> module);
14 ~CSRNG() override;
14}; 15};
15 16
16} // namespace Service::SPL 17} // namespace Service::SPL
diff --git a/src/core/hle/service/spl/module.cpp b/src/core/hle/service/spl/module.cpp
index 3f5a342a7..0d8441fb1 100644
--- a/src/core/hle/service/spl/module.cpp
+++ b/src/core/hle/service/spl/module.cpp
@@ -16,6 +16,8 @@ namespace Service::SPL {
16Module::Interface::Interface(std::shared_ptr<Module> module, const char* name) 16Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
17 : ServiceFramework(name), module(std::move(module)) {} 17 : ServiceFramework(name), module(std::move(module)) {}
18 18
19Module::Interface::~Interface() = default;
20
19void Module::Interface::GetRandomBytes(Kernel::HLERequestContext& ctx) { 21void Module::Interface::GetRandomBytes(Kernel::HLERequestContext& ctx) {
20 IPC::RequestParser rp{ctx}; 22 IPC::RequestParser rp{ctx};
21 23
diff --git a/src/core/hle/service/spl/module.h b/src/core/hle/service/spl/module.h
index f24d998e8..48fda6099 100644
--- a/src/core/hle/service/spl/module.h
+++ b/src/core/hle/service/spl/module.h
@@ -13,6 +13,7 @@ public:
13 class Interface : public ServiceFramework<Interface> { 13 class Interface : public ServiceFramework<Interface> {
14 public: 14 public:
15 explicit Interface(std::shared_ptr<Module> module, const char* name); 15 explicit Interface(std::shared_ptr<Module> module, const char* name);
16 ~Interface() override;
16 17
17 void GetRandomBytes(Kernel::HLERequestContext& ctx); 18 void GetRandomBytes(Kernel::HLERequestContext& ctx);
18 19
diff --git a/src/core/hle/service/spl/spl.cpp b/src/core/hle/service/spl/spl.cpp
index bb1e03342..70cb41905 100644
--- a/src/core/hle/service/spl/spl.cpp
+++ b/src/core/hle/service/spl/spl.cpp
@@ -42,4 +42,6 @@ SPL::SPL(std::shared_ptr<Module> module) : Module::Interface(std::move(module),
42 RegisterHandlers(functions); 42 RegisterHandlers(functions);
43} 43}
44 44
45SPL::~SPL() = default;
46
45} // namespace Service::SPL 47} // namespace Service::SPL
diff --git a/src/core/hle/service/spl/spl.h b/src/core/hle/service/spl/spl.h
index 69c4c1747..3637d1623 100644
--- a/src/core/hle/service/spl/spl.h
+++ b/src/core/hle/service/spl/spl.h
@@ -11,6 +11,7 @@ namespace Service::SPL {
11class SPL final : public Module::Interface { 11class SPL final : public Module::Interface {
12public: 12public:
13 explicit SPL(std::shared_ptr<Module> module); 13 explicit SPL(std::shared_ptr<Module> module);
14 ~SPL() override;
14}; 15};
15 16
16} // namespace Service::SPL 17} // namespace Service::SPL
diff --git a/src/core/hle/service/time/interface.cpp b/src/core/hle/service/time/interface.cpp
index 048d5b077..18a5d71d5 100644
--- a/src/core/hle/service/time/interface.cpp
+++ b/src/core/hle/service/time/interface.cpp
@@ -29,4 +29,6 @@ Time::Time(std::shared_ptr<Module> time, const char* name)
29 RegisterHandlers(functions); 29 RegisterHandlers(functions);
30} 30}
31 31
32Time::~Time() = default;
33
32} // namespace Service::Time 34} // namespace Service::Time
diff --git a/src/core/hle/service/time/interface.h b/src/core/hle/service/time/interface.h
index 183a53db1..cd6b44dec 100644
--- a/src/core/hle/service/time/interface.h
+++ b/src/core/hle/service/time/interface.h
@@ -11,6 +11,7 @@ namespace Service::Time {
11class Time final : public Module::Interface { 11class Time final : public Module::Interface {
12public: 12public:
13 explicit Time(std::shared_ptr<Module> time, const char* name); 13 explicit Time(std::shared_ptr<Module> time, const char* name);
14 ~Time() override;
14}; 15};
15 16
16} // namespace Service::Time 17} // namespace Service::Time
diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp
index 2172c681b..28fd8debc 100644
--- a/src/core/hle/service/time/time.cpp
+++ b/src/core/hle/service/time/time.cpp
@@ -210,6 +210,8 @@ void Module::Interface::GetStandardLocalSystemClock(Kernel::HLERequestContext& c
210Module::Interface::Interface(std::shared_ptr<Module> time, const char* name) 210Module::Interface::Interface(std::shared_ptr<Module> time, const char* name)
211 : ServiceFramework(name), time(std::move(time)) {} 211 : ServiceFramework(name), time(std::move(time)) {}
212 212
213Module::Interface::~Interface() = default;
214
213void InstallInterfaces(SM::ServiceManager& service_manager) { 215void InstallInterfaces(SM::ServiceManager& service_manager) {
214 auto time = std::make_shared<Module>(); 216 auto time = std::make_shared<Module>();
215 std::make_shared<Time>(time, "time:a")->InstallAsService(service_manager); 217 std::make_shared<Time>(time, "time:a")->InstallAsService(service_manager);
diff --git a/src/core/hle/service/time/time.h b/src/core/hle/service/time/time.h
index 8dde28a94..5659ecad3 100644
--- a/src/core/hle/service/time/time.h
+++ b/src/core/hle/service/time/time.h
@@ -58,6 +58,7 @@ public:
58 class Interface : public ServiceFramework<Interface> { 58 class Interface : public ServiceFramework<Interface> {
59 public: 59 public:
60 explicit Interface(std::shared_ptr<Module> time, const char* name); 60 explicit Interface(std::shared_ptr<Module> time, const char* name);
61 ~Interface() override;
61 62
62 void GetStandardUserSystemClock(Kernel::HLERequestContext& ctx); 63 void GetStandardUserSystemClock(Kernel::HLERequestContext& ctx);
63 void GetStandardNetworkSystemClock(Kernel::HLERequestContext& ctx); 64 void GetStandardNetworkSystemClock(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index 993f1e65a..85244ac3b 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -984,6 +984,8 @@ Module::Interface::Interface(std::shared_ptr<Module> module, const char* name,
984 std::shared_ptr<NVFlinger::NVFlinger> nv_flinger) 984 std::shared_ptr<NVFlinger::NVFlinger> nv_flinger)
985 : ServiceFramework(name), module(std::move(module)), nv_flinger(std::move(nv_flinger)) {} 985 : ServiceFramework(name), module(std::move(module)), nv_flinger(std::move(nv_flinger)) {}
986 986
987Module::Interface::~Interface() = default;
988
987void Module::Interface::GetDisplayService(Kernel::HLERequestContext& ctx) { 989void Module::Interface::GetDisplayService(Kernel::HLERequestContext& ctx) {
988 LOG_WARNING(Service_VI, "(STUBBED) called"); 990 LOG_WARNING(Service_VI, "(STUBBED) called");
989 991
diff --git a/src/core/hle/service/vi/vi.h b/src/core/hle/service/vi/vi.h
index 92f5b6059..c2dc83605 100644
--- a/src/core/hle/service/vi/vi.h
+++ b/src/core/hle/service/vi/vi.h
@@ -26,6 +26,7 @@ public:
26 public: 26 public:
27 explicit Interface(std::shared_ptr<Module> module, const char* name, 27 explicit Interface(std::shared_ptr<Module> module, const char* name,
28 std::shared_ptr<NVFlinger::NVFlinger> nv_flinger); 28 std::shared_ptr<NVFlinger::NVFlinger> nv_flinger);
29 ~Interface() override;
29 30
30 void GetDisplayService(Kernel::HLERequestContext& ctx); 31 void GetDisplayService(Kernel::HLERequestContext& ctx);
31 32
diff --git a/src/core/hle/service/vi/vi_m.cpp b/src/core/hle/service/vi/vi_m.cpp
index d47da565b..207c06b16 100644
--- a/src/core/hle/service/vi/vi_m.cpp
+++ b/src/core/hle/service/vi/vi_m.cpp
@@ -15,4 +15,6 @@ VI_M::VI_M(std::shared_ptr<Module> module, std::shared_ptr<NVFlinger::NVFlinger>
15 RegisterHandlers(functions); 15 RegisterHandlers(functions);
16} 16}
17 17
18VI_M::~VI_M() = default;
19
18} // namespace Service::VI 20} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi_m.h b/src/core/hle/service/vi/vi_m.h
index 6abb9b3a3..487d58d50 100644
--- a/src/core/hle/service/vi/vi_m.h
+++ b/src/core/hle/service/vi/vi_m.h
@@ -11,6 +11,7 @@ namespace Service::VI {
11class VI_M final : public Module::Interface { 11class VI_M final : public Module::Interface {
12public: 12public:
13 explicit VI_M(std::shared_ptr<Module> module, std::shared_ptr<NVFlinger::NVFlinger> nv_flinger); 13 explicit VI_M(std::shared_ptr<Module> module, std::shared_ptr<NVFlinger::NVFlinger> nv_flinger);
14 ~VI_M() override;
14}; 15};
15 16
16} // namespace Service::VI 17} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi_s.cpp b/src/core/hle/service/vi/vi_s.cpp
index 8f82e797f..920e6a1f6 100644
--- a/src/core/hle/service/vi/vi_s.cpp
+++ b/src/core/hle/service/vi/vi_s.cpp
@@ -15,4 +15,6 @@ VI_S::VI_S(std::shared_ptr<Module> module, std::shared_ptr<NVFlinger::NVFlinger>
15 RegisterHandlers(functions); 15 RegisterHandlers(functions);
16} 16}
17 17
18VI_S::~VI_S() = default;
19
18} // namespace Service::VI 20} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi_s.h b/src/core/hle/service/vi/vi_s.h
index 8f16f804f..bbc31148f 100644
--- a/src/core/hle/service/vi/vi_s.h
+++ b/src/core/hle/service/vi/vi_s.h
@@ -11,6 +11,7 @@ namespace Service::VI {
11class VI_S final : public Module::Interface { 11class VI_S final : public Module::Interface {
12public: 12public:
13 explicit VI_S(std::shared_ptr<Module> module, std::shared_ptr<NVFlinger::NVFlinger> nv_flinger); 13 explicit VI_S(std::shared_ptr<Module> module, std::shared_ptr<NVFlinger::NVFlinger> nv_flinger);
14 ~VI_S() override;
14}; 15};
15 16
16} // namespace Service::VI 17} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi_u.cpp b/src/core/hle/service/vi/vi_u.cpp
index b84aed1d5..d81e410d6 100644
--- a/src/core/hle/service/vi/vi_u.cpp
+++ b/src/core/hle/service/vi/vi_u.cpp
@@ -14,4 +14,6 @@ VI_U::VI_U(std::shared_ptr<Module> module, std::shared_ptr<NVFlinger::NVFlinger>
14 RegisterHandlers(functions); 14 RegisterHandlers(functions);
15} 15}
16 16
17VI_U::~VI_U() = default;
18
17} // namespace Service::VI 19} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi_u.h b/src/core/hle/service/vi/vi_u.h
index e9b4f76b2..b92f28c92 100644
--- a/src/core/hle/service/vi/vi_u.h
+++ b/src/core/hle/service/vi/vi_u.h
@@ -11,6 +11,7 @@ namespace Service::VI {
11class VI_U final : public Module::Interface { 11class VI_U final : public Module::Interface {
12public: 12public:
13 explicit VI_U(std::shared_ptr<Module> module, std::shared_ptr<NVFlinger::NVFlinger> nv_flinger); 13 explicit VI_U(std::shared_ptr<Module> module, std::shared_ptr<NVFlinger::NVFlinger> nv_flinger);
14 ~VI_U() override;
14}; 15};
15 16
16} // namespace Service::VI 17} // namespace Service::VI
diff --git a/src/core/settings.h b/src/core/settings.h
index 5bf1863e6..08a16ef2c 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -5,6 +5,7 @@
5#pragma once 5#pragma once
6 6
7#include <array> 7#include <array>
8#include <atomic>
8#include <string> 9#include <string>
9#include "common/common_types.h" 10#include "common/common_types.h"
10 11
@@ -120,6 +121,7 @@ struct Values {
120 std::array<std::string, NativeAnalog::NumAnalogs> analogs; 121 std::array<std::string, NativeAnalog::NumAnalogs> analogs;
121 std::string motion_device; 122 std::string motion_device;
122 std::string touch_device; 123 std::string touch_device;
124 std::atomic_bool is_device_reload_pending{true};
123 125
124 // Core 126 // Core
125 bool use_cpu_jit; 127 bool use_cpu_jit;
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp
index b12623d55..37f572853 100644
--- a/src/input_common/main.cpp
+++ b/src/input_common/main.cpp
@@ -3,6 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <memory> 5#include <memory>
6#include <thread>
6#include "common/param_package.h" 7#include "common/param_package.h"
7#include "input_common/analog_from_button.h" 8#include "input_common/analog_from_button.h"
8#include "input_common/keyboard.h" 9#include "input_common/keyboard.h"
@@ -17,6 +18,10 @@ namespace InputCommon {
17static std::shared_ptr<Keyboard> keyboard; 18static std::shared_ptr<Keyboard> keyboard;
18static std::shared_ptr<MotionEmu> motion_emu; 19static std::shared_ptr<MotionEmu> motion_emu;
19 20
21#ifdef HAVE_SDL2
22static std::thread poll_thread;
23#endif
24
20void Init() { 25void Init() {
21 keyboard = std::make_shared<Keyboard>(); 26 keyboard = std::make_shared<Keyboard>();
22 Input::RegisterFactory<Input::ButtonDevice>("keyboard", keyboard); 27 Input::RegisterFactory<Input::ButtonDevice>("keyboard", keyboard);
@@ -30,6 +35,12 @@ void Init() {
30#endif 35#endif
31} 36}
32 37
38void StartJoystickEventHandler() {
39#ifdef HAVE_SDL2
40 poll_thread = std::thread(SDL::PollLoop);
41#endif
42}
43
33void Shutdown() { 44void Shutdown() {
34 Input::UnregisterFactory<Input::ButtonDevice>("keyboard"); 45 Input::UnregisterFactory<Input::ButtonDevice>("keyboard");
35 keyboard.reset(); 46 keyboard.reset();
@@ -39,6 +50,7 @@ void Shutdown() {
39 50
40#ifdef HAVE_SDL2 51#ifdef HAVE_SDL2
41 SDL::Shutdown(); 52 SDL::Shutdown();
53 poll_thread.join();
42#endif 54#endif
43} 55}
44 56
diff --git a/src/input_common/main.h b/src/input_common/main.h
index 77a0ce90b..9eb13106e 100644
--- a/src/input_common/main.h
+++ b/src/input_common/main.h
@@ -20,6 +20,8 @@ void Init();
20/// Deregisters all built-in input device factories and shuts them down. 20/// Deregisters all built-in input device factories and shuts them down.
21void Shutdown(); 21void Shutdown();
22 22
23void StartJoystickEventHandler();
24
23class Keyboard; 25class Keyboard;
24 26
25/// Gets the keyboard button device factory. 27/// Gets the keyboard button device factory.
diff --git a/src/input_common/sdl/sdl.cpp b/src/input_common/sdl/sdl.cpp
index d1b960fd7..faf3c1fa3 100644
--- a/src/input_common/sdl/sdl.cpp
+++ b/src/input_common/sdl/sdl.cpp
@@ -2,15 +2,24 @@
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 <algorithm>
6#include <atomic>
5#include <cmath> 7#include <cmath>
8#include <functional>
9#include <iterator>
10#include <mutex>
6#include <string> 11#include <string>
12#include <thread>
7#include <tuple> 13#include <tuple>
8#include <unordered_map> 14#include <unordered_map>
9#include <utility> 15#include <utility>
16#include <vector>
10#include <SDL.h> 17#include <SDL.h>
18#include "common/assert.h"
11#include "common/logging/log.h" 19#include "common/logging/log.h"
12#include "common/math_util.h" 20#include "common/math_util.h"
13#include "common/param_package.h" 21#include "common/param_package.h"
22#include "common/threadsafe_queue.h"
14#include "input_common/main.h" 23#include "input_common/main.h"
15#include "input_common/sdl/sdl.h" 24#include "input_common/sdl/sdl.h"
16 25
@@ -21,33 +30,51 @@ namespace SDL {
21class SDLJoystick; 30class SDLJoystick;
22class SDLButtonFactory; 31class SDLButtonFactory;
23class SDLAnalogFactory; 32class SDLAnalogFactory;
24static std::unordered_map<int, std::weak_ptr<SDLJoystick>> joystick_list; 33
34/// Map of GUID of a list of corresponding virtual Joysticks
35static std::unordered_map<std::string, std::vector<std::shared_ptr<SDLJoystick>>> joystick_map;
36static std::mutex joystick_map_mutex;
37
25static std::shared_ptr<SDLButtonFactory> button_factory; 38static std::shared_ptr<SDLButtonFactory> button_factory;
26static std::shared_ptr<SDLAnalogFactory> analog_factory; 39static std::shared_ptr<SDLAnalogFactory> analog_factory;
27 40
28static bool initialized = false; 41/// Used by the Pollers during config
42static std::atomic<bool> polling;
43static Common::SPSCQueue<SDL_Event> event_queue;
44
45static std::atomic<bool> initialized = false;
46
47static std::string GetGUID(SDL_Joystick* joystick) {
48 SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
49 char guid_str[33];
50 SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str));
51 return guid_str;
52}
29 53
30class SDLJoystick { 54class SDLJoystick {
31public: 55public:
32 explicit SDLJoystick(int joystick_index) 56 SDLJoystick(std::string guid_, int port_, SDL_Joystick* joystick,
33 : joystick{SDL_JoystickOpen(joystick_index), SDL_JoystickClose} { 57 decltype(&SDL_JoystickClose) deleter = &SDL_JoystickClose)
34 if (!joystick) { 58 : guid{std::move(guid_)}, port{port_}, sdl_joystick{joystick, deleter} {}
35 LOG_ERROR(Input, "failed to open joystick {}", joystick_index); 59
36 } 60 void SetButton(int button, bool value) {
61 std::lock_guard<std::mutex> lock(mutex);
62 state.buttons[button] = value;
37 } 63 }
38 64
39 bool GetButton(int button) const { 65 bool GetButton(int button) const {
40 if (!joystick) 66 std::lock_guard<std::mutex> lock(mutex);
41 return {}; 67 return state.buttons.at(button);
42 SDL_JoystickUpdate(); 68 }
43 return SDL_JoystickGetButton(joystick.get(), button) == 1; 69
70 void SetAxis(int axis, Sint16 value) {
71 std::lock_guard<std::mutex> lock(mutex);
72 state.axes[axis] = value;
44 } 73 }
45 74
46 float GetAxis(int axis) const { 75 float GetAxis(int axis) const {
47 if (!joystick) 76 std::lock_guard<std::mutex> lock(mutex);
48 return {}; 77 return state.axes.at(axis) / 32767.0f;
49 SDL_JoystickUpdate();
50 return SDL_JoystickGetAxis(joystick.get(), axis) / 32767.0f;
51 } 78 }
52 79
53 std::tuple<float, float> GetAnalog(int axis_x, int axis_y) const { 80 std::tuple<float, float> GetAnalog(int axis_x, int axis_y) const {
@@ -67,18 +94,213 @@ public:
67 return std::make_tuple(x, y); 94 return std::make_tuple(x, y);
68 } 95 }
69 96
97 void SetHat(int hat, Uint8 direction) {
98 std::lock_guard<std::mutex> lock(mutex);
99 state.hats[hat] = direction;
100 }
101
70 bool GetHatDirection(int hat, Uint8 direction) const { 102 bool GetHatDirection(int hat, Uint8 direction) const {
71 return (SDL_JoystickGetHat(joystick.get(), hat) & direction) != 0; 103 std::lock_guard<std::mutex> lock(mutex);
104 return (state.hats.at(hat) & direction) != 0;
105 }
106 /**
107 * The guid of the joystick
108 */
109 const std::string& GetGUID() const {
110 return guid;
111 }
112
113 /**
114 * The number of joystick from the same type that were connected before this joystick
115 */
116 int GetPort() const {
117 return port;
118 }
119
120 SDL_Joystick* GetSDLJoystick() const {
121 return sdl_joystick.get();
72 } 122 }
73 123
74 SDL_JoystickID GetJoystickID() const { 124 void SetSDLJoystick(SDL_Joystick* joystick,
75 return SDL_JoystickInstanceID(joystick.get()); 125 decltype(&SDL_JoystickClose) deleter = &SDL_JoystickClose) {
126 sdl_joystick =
127 std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)>(joystick, deleter);
76 } 128 }
77 129
78private: 130private:
79 std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> joystick; 131 struct State {
132 std::unordered_map<int, bool> buttons;
133 std::unordered_map<int, Sint16> axes;
134 std::unordered_map<int, Uint8> hats;
135 } state;
136 std::string guid;
137 int port;
138 std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick;
139 mutable std::mutex mutex;
80}; 140};
81 141
142/**
143 * Get the nth joystick with the corresponding GUID
144 */
145static std::shared_ptr<SDLJoystick> GetSDLJoystickByGUID(const std::string& guid, int port) {
146 std::lock_guard<std::mutex> lock(joystick_map_mutex);
147 const auto it = joystick_map.find(guid);
148 if (it != joystick_map.end()) {
149 while (it->second.size() <= port) {
150 auto joystick = std::make_shared<SDLJoystick>(guid, it->second.size(), nullptr,
151 [](SDL_Joystick*) {});
152 it->second.emplace_back(std::move(joystick));
153 }
154 return it->second[port];
155 }
156 auto joystick = std::make_shared<SDLJoystick>(guid, 0, nullptr, [](SDL_Joystick*) {});
157 return joystick_map[guid].emplace_back(std::move(joystick));
158}
159
160/**
161 * Check how many identical joysticks (by guid) were connected before the one with sdl_id and so tie
162 * it to a SDLJoystick with the same guid and that port
163 */
164static std::shared_ptr<SDLJoystick> GetSDLJoystickBySDLID(SDL_JoystickID sdl_id) {
165 std::lock_guard<std::mutex> lock(joystick_map_mutex);
166 auto sdl_joystick = SDL_JoystickFromInstanceID(sdl_id);
167 const std::string guid = GetGUID(sdl_joystick);
168 auto map_it = joystick_map.find(guid);
169 if (map_it != joystick_map.end()) {
170 auto vec_it = std::find_if(map_it->second.begin(), map_it->second.end(),
171 [&sdl_joystick](const std::shared_ptr<SDLJoystick>& joystick) {
172 return sdl_joystick == joystick->GetSDLJoystick();
173 });
174 if (vec_it != map_it->second.end()) {
175 // This is the common case: There is already an existing SDL_Joystick maped to a
176 // SDLJoystick. return the SDLJoystick
177 return *vec_it;
178 }
179 // Search for a SDLJoystick without a mapped SDL_Joystick...
180 auto nullptr_it = std::find_if(map_it->second.begin(), map_it->second.end(),
181 [](const std::shared_ptr<SDLJoystick>& joystick) {
182 return !joystick->GetSDLJoystick();
183 });
184 if (nullptr_it != map_it->second.end()) {
185 // ... and map it
186 (*nullptr_it)->SetSDLJoystick(sdl_joystick);
187 return *nullptr_it;
188 }
189 // There is no SDLJoystick without a mapped SDL_Joystick
190 // Create a new SDLJoystick
191 auto joystick = std::make_shared<SDLJoystick>(guid, map_it->second.size(), sdl_joystick);
192 return map_it->second.emplace_back(std::move(joystick));
193 }
194 auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick);
195 return joystick_map[guid].emplace_back(std::move(joystick));
196}
197
198void InitJoystick(int joystick_index) {
199 std::lock_guard<std::mutex> lock(joystick_map_mutex);
200 SDL_Joystick* sdl_joystick = SDL_JoystickOpen(joystick_index);
201 if (!sdl_joystick) {
202 LOG_ERROR(Input, "failed to open joystick {}", joystick_index);
203 return;
204 }
205 std::string guid = GetGUID(sdl_joystick);
206 if (joystick_map.find(guid) == joystick_map.end()) {
207 auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick);
208 joystick_map[guid].emplace_back(std::move(joystick));
209 return;
210 }
211 auto& joystick_guid_list = joystick_map[guid];
212 const auto it = std::find_if(
213 joystick_guid_list.begin(), joystick_guid_list.end(),
214 [](const std::shared_ptr<SDLJoystick>& joystick) { return !joystick->GetSDLJoystick(); });
215 if (it != joystick_guid_list.end()) {
216 (*it)->SetSDLJoystick(sdl_joystick);
217 return;
218 }
219 auto joystick = std::make_shared<SDLJoystick>(guid, joystick_guid_list.size(), sdl_joystick);
220 joystick_guid_list.emplace_back(std::move(joystick));
221}
222
223void CloseJoystick(SDL_Joystick* sdl_joystick) {
224 std::lock_guard<std::mutex> lock(joystick_map_mutex);
225 std::string guid = GetGUID(sdl_joystick);
226 // This call to guid is save since the joystick is guranteed to be in that map
227 auto& joystick_guid_list = joystick_map[guid];
228 const auto joystick_it =
229 std::find_if(joystick_guid_list.begin(), joystick_guid_list.end(),
230 [&sdl_joystick](const std::shared_ptr<SDLJoystick>& joystick) {
231 return joystick->GetSDLJoystick() == sdl_joystick;
232 });
233 (*joystick_it)->SetSDLJoystick(nullptr, [](SDL_Joystick*) {});
234}
235
236void HandleGameControllerEvent(const SDL_Event& event) {
237 switch (event.type) {
238 case SDL_JOYBUTTONUP: {
239 auto joystick = GetSDLJoystickBySDLID(event.jbutton.which);
240 if (joystick) {
241 joystick->SetButton(event.jbutton.button, false);
242 }
243 break;
244 }
245 case SDL_JOYBUTTONDOWN: {
246 auto joystick = GetSDLJoystickBySDLID(event.jbutton.which);
247 if (joystick) {
248 joystick->SetButton(event.jbutton.button, true);
249 }
250 break;
251 }
252 case SDL_JOYHATMOTION: {
253 auto joystick = GetSDLJoystickBySDLID(event.jhat.which);
254 if (joystick) {
255 joystick->SetHat(event.jhat.hat, event.jhat.value);
256 }
257 break;
258 }
259 case SDL_JOYAXISMOTION: {
260 auto joystick = GetSDLJoystickBySDLID(event.jaxis.which);
261 if (joystick) {
262 joystick->SetAxis(event.jaxis.axis, event.jaxis.value);
263 }
264 break;
265 }
266 case SDL_JOYDEVICEREMOVED:
267 LOG_DEBUG(Input, "Controller removed with Instance_ID {}", event.jdevice.which);
268 CloseJoystick(SDL_JoystickFromInstanceID(event.jdevice.which));
269 break;
270 case SDL_JOYDEVICEADDED:
271 LOG_DEBUG(Input, "Controller connected with device index {}", event.jdevice.which);
272 InitJoystick(event.jdevice.which);
273 break;
274 }
275}
276
277void CloseSDLJoysticks() {
278 std::lock_guard<std::mutex> lock(joystick_map_mutex);
279 joystick_map.clear();
280}
281
282void PollLoop() {
283 if (SDL_Init(SDL_INIT_JOYSTICK) < 0) {
284 LOG_CRITICAL(Input, "SDL_Init(SDL_INIT_JOYSTICK) failed with: {}", SDL_GetError());
285 return;
286 }
287
288 SDL_Event event;
289 while (initialized) {
290 // Wait for 10 ms or until an event happens
291 if (SDL_WaitEventTimeout(&event, 10)) {
292 // Don't handle the event if we are configuring
293 if (polling) {
294 event_queue.Push(event);
295 } else {
296 HandleGameControllerEvent(event);
297 }
298 }
299 }
300 CloseSDLJoysticks();
301 SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
302}
303
82class SDLButton final : public Input::ButtonDevice { 304class SDLButton final : public Input::ButtonDevice {
83public: 305public:
84 explicit SDLButton(std::shared_ptr<SDLJoystick> joystick_, int button_) 306 explicit SDLButton(std::shared_ptr<SDLJoystick> joystick_, int button_)
@@ -144,22 +366,14 @@ private:
144 int axis_y; 366 int axis_y;
145}; 367};
146 368
147static std::shared_ptr<SDLJoystick> GetJoystick(int joystick_index) {
148 std::shared_ptr<SDLJoystick> joystick = joystick_list[joystick_index].lock();
149 if (!joystick) {
150 joystick = std::make_shared<SDLJoystick>(joystick_index);
151 joystick_list[joystick_index] = joystick;
152 }
153 return joystick;
154}
155
156/// A button device factory that creates button devices from SDL joystick 369/// A button device factory that creates button devices from SDL joystick
157class SDLButtonFactory final : public Input::Factory<Input::ButtonDevice> { 370class SDLButtonFactory final : public Input::Factory<Input::ButtonDevice> {
158public: 371public:
159 /** 372 /**
160 * Creates a button device from a joystick button 373 * Creates a button device from a joystick button
161 * @param params contains parameters for creating the device: 374 * @param params contains parameters for creating the device:
162 * - "joystick": the index of the joystick to bind 375 * - "guid": the guid of the joystick to bind
376 * - "port": the nth joystick of the same type to bind
163 * - "button"(optional): the index of the button to bind 377 * - "button"(optional): the index of the button to bind
164 * - "hat"(optional): the index of the hat to bind as direction buttons 378 * - "hat"(optional): the index of the hat to bind as direction buttons
165 * - "axis"(optional): the index of the axis to bind 379 * - "axis"(optional): the index of the axis to bind
@@ -167,12 +381,15 @@ public:
167 * "down", "left" or "right" 381 * "down", "left" or "right"
168 * - "threshold"(only used for axis): a float value in (-1.0, 1.0) which the button is 382 * - "threshold"(only used for axis): a float value in (-1.0, 1.0) which the button is
169 * triggered if the axis value crosses 383 * triggered if the axis value crosses
170 * - "direction"(only used for axis): "+" means the button is triggered when the axis value 384 * - "direction"(only used for axis): "+" means the button is triggered when the axis
171 * is greater than the threshold; "-" means the button is triggered when the axis value 385 * value is greater than the threshold; "-" means the button is triggered when the axis
172 * is smaller than the threshold 386 * value is smaller than the threshold
173 */ 387 */
174 std::unique_ptr<Input::ButtonDevice> Create(const Common::ParamPackage& params) override { 388 std::unique_ptr<Input::ButtonDevice> Create(const Common::ParamPackage& params) override {
175 const int joystick_index = params.Get("joystick", 0); 389 const std::string guid = params.Get("guid", "0");
390 const int port = params.Get("port", 0);
391
392 auto joystick = GetSDLJoystickByGUID(guid, port);
176 393
177 if (params.Has("hat")) { 394 if (params.Has("hat")) {
178 const int hat = params.Get("hat", 0); 395 const int hat = params.Get("hat", 0);
@@ -189,8 +406,9 @@ public:
189 } else { 406 } else {
190 direction = 0; 407 direction = 0;
191 } 408 }
192 return std::make_unique<SDLDirectionButton>(GetJoystick(joystick_index), hat, 409 // This is necessary so accessing GetHat with hat won't crash
193 direction); 410 joystick->SetHat(hat, SDL_HAT_CENTERED);
411 return std::make_unique<SDLDirectionButton>(joystick, hat, direction);
194 } 412 }
195 413
196 if (params.Has("axis")) { 414 if (params.Has("axis")) {
@@ -206,12 +424,15 @@ public:
206 trigger_if_greater = true; 424 trigger_if_greater = true;
207 LOG_ERROR(Input, "Unknown direction '{}'", direction_name); 425 LOG_ERROR(Input, "Unknown direction '{}'", direction_name);
208 } 426 }
209 return std::make_unique<SDLAxisButton>(GetJoystick(joystick_index), axis, threshold, 427 // This is necessary so accessing GetAxis with axis won't crash
210 trigger_if_greater); 428 joystick->SetAxis(axis, 0);
429 return std::make_unique<SDLAxisButton>(joystick, axis, threshold, trigger_if_greater);
211 } 430 }
212 431
213 const int button = params.Get("button", 0); 432 const int button = params.Get("button", 0);
214 return std::make_unique<SDLButton>(GetJoystick(joystick_index), button); 433 // This is necessary so accessing GetButton with button won't crash
434 joystick->SetButton(button, false);
435 return std::make_unique<SDLButton>(joystick, button);
215 } 436 }
216}; 437};
217 438
@@ -221,27 +442,32 @@ public:
221 /** 442 /**
222 * Creates analog device from joystick axes 443 * Creates analog device from joystick axes
223 * @param params contains parameters for creating the device: 444 * @param params contains parameters for creating the device:
224 * - "joystick": the index of the joystick to bind 445 * - "guid": the guid of the joystick to bind
446 * - "port": the nth joystick of the same type
225 * - "axis_x": the index of the axis to be bind as x-axis 447 * - "axis_x": the index of the axis to be bind as x-axis
226 * - "axis_y": the index of the axis to be bind as y-axis 448 * - "axis_y": the index of the axis to be bind as y-axis
227 */ 449 */
228 std::unique_ptr<Input::AnalogDevice> Create(const Common::ParamPackage& params) override { 450 std::unique_ptr<Input::AnalogDevice> Create(const Common::ParamPackage& params) override {
229 const int joystick_index = params.Get("joystick", 0); 451 const std::string guid = params.Get("guid", "0");
452 const int port = params.Get("port", 0);
230 const int axis_x = params.Get("axis_x", 0); 453 const int axis_x = params.Get("axis_x", 0);
231 const int axis_y = params.Get("axis_y", 1); 454 const int axis_y = params.Get("axis_y", 1);
232 return std::make_unique<SDLAnalog>(GetJoystick(joystick_index), axis_x, axis_y); 455
456 auto joystick = GetSDLJoystickByGUID(guid, port);
457
458 // This is necessary so accessing GetAxis with axis_x and axis_y won't crash
459 joystick->SetAxis(axis_x, 0);
460 joystick->SetAxis(axis_y, 0);
461 return std::make_unique<SDLAnalog>(joystick, axis_x, axis_y);
233 } 462 }
234}; 463};
235 464
236void Init() { 465void Init() {
237 if (SDL_Init(SDL_INIT_JOYSTICK) < 0) { 466 using namespace Input;
238 LOG_CRITICAL(Input, "SDL_Init(SDL_INIT_JOYSTICK) failed with: {}", SDL_GetError()); 467 RegisterFactory<ButtonDevice>("sdl", std::make_shared<SDLButtonFactory>());
239 } else { 468 RegisterFactory<AnalogDevice>("sdl", std::make_shared<SDLAnalogFactory>());
240 using namespace Input; 469 polling = false;
241 RegisterFactory<ButtonDevice>("sdl", std::make_shared<SDLButtonFactory>()); 470 initialized = true;
242 RegisterFactory<AnalogDevice>("sdl", std::make_shared<SDLAnalogFactory>());
243 initialized = true;
244 }
245} 471}
246 472
247void Shutdown() { 473void Shutdown() {
@@ -249,30 +475,17 @@ void Shutdown() {
249 using namespace Input; 475 using namespace Input;
250 UnregisterFactory<ButtonDevice>("sdl"); 476 UnregisterFactory<ButtonDevice>("sdl");
251 UnregisterFactory<AnalogDevice>("sdl"); 477 UnregisterFactory<AnalogDevice>("sdl");
252 SDL_QuitSubSystem(SDL_INIT_JOYSTICK); 478 initialized = false;
253 } 479 }
254} 480}
255 481
256/**
257 * This function converts a joystick ID used in SDL events to the device index. This is necessary
258 * because Citra opens joysticks using their indices, not their IDs.
259 */
260static int JoystickIDToDeviceIndex(SDL_JoystickID id) {
261 int num_joysticks = SDL_NumJoysticks();
262 for (int i = 0; i < num_joysticks; i++) {
263 auto joystick = GetJoystick(i);
264 if (joystick->GetJoystickID() == id) {
265 return i;
266 }
267 }
268 return -1;
269}
270
271Common::ParamPackage SDLEventToButtonParamPackage(const SDL_Event& event) { 482Common::ParamPackage SDLEventToButtonParamPackage(const SDL_Event& event) {
272 Common::ParamPackage params({{"engine", "sdl"}}); 483 Common::ParamPackage params({{"engine", "sdl"}});
273 switch (event.type) { 484 switch (event.type) {
274 case SDL_JOYAXISMOTION: 485 case SDL_JOYAXISMOTION: {
275 params.Set("joystick", JoystickIDToDeviceIndex(event.jaxis.which)); 486 auto joystick = GetSDLJoystickBySDLID(event.jaxis.which);
487 params.Set("port", joystick->GetPort());
488 params.Set("guid", joystick->GetGUID());
276 params.Set("axis", event.jaxis.axis); 489 params.Set("axis", event.jaxis.axis);
277 if (event.jaxis.value > 0) { 490 if (event.jaxis.value > 0) {
278 params.Set("direction", "+"); 491 params.Set("direction", "+");
@@ -282,12 +495,18 @@ Common::ParamPackage SDLEventToButtonParamPackage(const SDL_Event& event) {
282 params.Set("threshold", "-0.5"); 495 params.Set("threshold", "-0.5");
283 } 496 }
284 break; 497 break;
285 case SDL_JOYBUTTONUP: 498 }
286 params.Set("joystick", JoystickIDToDeviceIndex(event.jbutton.which)); 499 case SDL_JOYBUTTONUP: {
500 auto joystick = GetSDLJoystickBySDLID(event.jbutton.which);
501 params.Set("port", joystick->GetPort());
502 params.Set("guid", joystick->GetGUID());
287 params.Set("button", event.jbutton.button); 503 params.Set("button", event.jbutton.button);
288 break; 504 break;
289 case SDL_JOYHATMOTION: 505 }
290 params.Set("joystick", JoystickIDToDeviceIndex(event.jhat.which)); 506 case SDL_JOYHATMOTION: {
507 auto joystick = GetSDLJoystickBySDLID(event.jhat.which);
508 params.Set("port", joystick->GetPort());
509 params.Set("guid", joystick->GetGUID());
291 params.Set("hat", event.jhat.hat); 510 params.Set("hat", event.jhat.hat);
292 switch (event.jhat.value) { 511 switch (event.jhat.value) {
293 case SDL_HAT_UP: 512 case SDL_HAT_UP:
@@ -307,6 +526,7 @@ Common::ParamPackage SDLEventToButtonParamPackage(const SDL_Event& event) {
307 } 526 }
308 break; 527 break;
309 } 528 }
529 }
310 return params; 530 return params;
311} 531}
312 532
@@ -315,31 +535,20 @@ namespace Polling {
315class SDLPoller : public InputCommon::Polling::DevicePoller { 535class SDLPoller : public InputCommon::Polling::DevicePoller {
316public: 536public:
317 void Start() override { 537 void Start() override {
318 // SDL joysticks must be opened, otherwise they don't generate events 538 event_queue.Clear();
319 SDL_JoystickUpdate(); 539 polling = true;
320 int num_joysticks = SDL_NumJoysticks();
321 for (int i = 0; i < num_joysticks; i++) {
322 joysticks_opened.emplace_back(GetJoystick(i));
323 }
324 // Empty event queue to get rid of old events. citra-qt doesn't use the queue
325 SDL_Event dummy;
326 while (SDL_PollEvent(&dummy)) {
327 }
328 } 540 }
329 541
330 void Stop() override { 542 void Stop() override {
331 joysticks_opened.clear(); 543 polling = false;
332 } 544 }
333
334private:
335 std::vector<std::shared_ptr<SDLJoystick>> joysticks_opened;
336}; 545};
337 546
338class SDLButtonPoller final : public SDLPoller { 547class SDLButtonPoller final : public SDLPoller {
339public: 548public:
340 Common::ParamPackage GetNextInput() override { 549 Common::ParamPackage GetNextInput() override {
341 SDL_Event event; 550 SDL_Event event;
342 while (SDL_PollEvent(&event)) { 551 while (event_queue.Pop(event)) {
343 switch (event.type) { 552 switch (event.type) {
344 case SDL_JOYAXISMOTION: 553 case SDL_JOYAXISMOTION:
345 if (std::abs(event.jaxis.value / 32767.0) < 0.5) { 554 if (std::abs(event.jaxis.value / 32767.0) < 0.5) {
@@ -367,7 +576,7 @@ public:
367 576
368 Common::ParamPackage GetNextInput() override { 577 Common::ParamPackage GetNextInput() override {
369 SDL_Event event; 578 SDL_Event event;
370 while (SDL_PollEvent(&event)) { 579 while (event_queue.Pop(event)) {
371 if (event.type != SDL_JOYAXISMOTION || std::abs(event.jaxis.value / 32767.0) < 0.5) { 580 if (event.type != SDL_JOYAXISMOTION || std::abs(event.jaxis.value / 32767.0) < 0.5) {
372 continue; 581 continue;
373 } 582 }
@@ -384,8 +593,10 @@ public:
384 } 593 }
385 Common::ParamPackage params; 594 Common::ParamPackage params;
386 if (analog_xaxis != -1 && analog_yaxis != -1) { 595 if (analog_xaxis != -1 && analog_yaxis != -1) {
596 auto joystick = GetSDLJoystickBySDLID(event.jaxis.which);
387 params.Set("engine", "sdl"); 597 params.Set("engine", "sdl");
388 params.Set("joystick", JoystickIDToDeviceIndex(analog_axes_joystick)); 598 params.Set("port", joystick->GetPort());
599 params.Set("guid", joystick->GetGUID());
389 params.Set("axis_x", analog_xaxis); 600 params.Set("axis_x", analog_xaxis);
390 params.Set("axis_y", analog_yaxis); 601 params.Set("axis_y", analog_yaxis);
391 analog_xaxis = -1; 602 analog_xaxis = -1;
diff --git a/src/input_common/sdl/sdl.h b/src/input_common/sdl/sdl.h
index 7934099d4..0206860d3 100644
--- a/src/input_common/sdl/sdl.h
+++ b/src/input_common/sdl/sdl.h
@@ -28,6 +28,15 @@ void Init();
28/// Unresisters SDL device factories and shut them down. 28/// Unresisters SDL device factories and shut them down.
29void Shutdown(); 29void Shutdown();
30 30
31/// Needs to be called before SDL_QuitSubSystem.
32void CloseSDLJoysticks();
33
34/// Handle SDL_Events for joysticks from SDL_PollEvent
35void HandleGameControllerEvent(const SDL_Event& event);
36
37/// A Loop that calls HandleGameControllerEvent until Shutdown is called
38void PollLoop();
39
31/// Creates a ParamPackage from an SDL_Event that can directly be used to create a ButtonDevice 40/// Creates a ParamPackage from an SDL_Event that can directly be used to create a ButtonDevice
32Common::ParamPackage SDLEventToButtonParamPackage(const SDL_Event& event); 41Common::ParamPackage SDLEventToButtonParamPackage(const SDL_Event& event);
33 42
diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp
index d5831e752..2625ddfdc 100644
--- a/src/video_core/command_processor.cpp
+++ b/src/video_core/command_processor.cpp
@@ -28,98 +28,106 @@ enum class BufferMethods {
28 CountBufferMethods = 0x40, 28 CountBufferMethods = 0x40,
29}; 29};
30 30
31void GPU::WriteReg(u32 method, u32 subchannel, u32 value, u32 remaining_params) { 31MICROPROFILE_DEFINE(ProcessCommandLists, "GPU", "Execute command buffer", MP_RGB(128, 128, 192));
32 LOG_TRACE(HW_GPU,
33 "Processing method {:08X} on subchannel {} value "
34 "{:08X} remaining params {}",
35 method, subchannel, value, remaining_params);
36
37 ASSERT(subchannel < bound_engines.size());
38
39 if (method == static_cast<u32>(BufferMethods::BindObject)) {
40 // Bind the current subchannel to the desired engine id.
41 LOG_DEBUG(HW_GPU, "Binding subchannel {} to engine {}", subchannel, value);
42 bound_engines[subchannel] = static_cast<EngineID>(value);
43 return;
44 }
45 32
46 if (method < static_cast<u32>(BufferMethods::CountBufferMethods)) { 33void GPU::ProcessCommandLists(const std::vector<CommandListHeader>& commands) {
47 // TODO(Subv): Research and implement these methods. 34 MICROPROFILE_SCOPE(ProcessCommandLists);
48 LOG_ERROR(HW_GPU, "Special buffer methods other than Bind are not implemented");
49 return;
50 }
51 35
52 const EngineID engine = bound_engines[subchannel]; 36 auto WriteReg = [this](u32 method, u32 subchannel, u32 value, u32 remaining_params) {
53 37 LOG_TRACE(HW_GPU,
54 switch (engine) { 38 "Processing method {:08X} on subchannel {} value "
55 case EngineID::FERMI_TWOD_A: 39 "{:08X} remaining params {}",
56 fermi_2d->WriteReg(method, value); 40 method, subchannel, value, remaining_params);
57 break;
58 case EngineID::MAXWELL_B:
59 maxwell_3d->WriteReg(method, value, remaining_params);
60 break;
61 case EngineID::MAXWELL_COMPUTE_B:
62 maxwell_compute->WriteReg(method, value);
63 break;
64 case EngineID::MAXWELL_DMA_COPY_A:
65 maxwell_dma->WriteReg(method, value);
66 break;
67 default:
68 UNIMPLEMENTED_MSG("Unimplemented engine");
69 }
70}
71 41
72void GPU::ProcessCommandList(GPUVAddr address, u32 size) { 42 ASSERT(subchannel < bound_engines.size());
73 const boost::optional<VAddr> head_address = memory_manager->GpuToCpuAddress(address); 43
74 VAddr current_addr = *head_address; 44 if (method == static_cast<u32>(BufferMethods::BindObject)) {
75 while (current_addr < *head_address + size * sizeof(CommandHeader)) { 45 // Bind the current subchannel to the desired engine id.
76 const CommandHeader header = {Memory::Read32(current_addr)}; 46 LOG_DEBUG(HW_GPU, "Binding subchannel {} to engine {}", subchannel, value);
77 current_addr += sizeof(u32); 47 bound_engines[subchannel] = static_cast<EngineID>(value);
78 48 return;
79 switch (header.mode.Value()) {
80 case SubmissionMode::IncreasingOld:
81 case SubmissionMode::Increasing: {
82 // Increase the method value with each argument.
83 for (unsigned i = 0; i < header.arg_count; ++i) {
84 WriteReg(header.method + i, header.subchannel, Memory::Read32(current_addr),
85 header.arg_count - i - 1);
86 current_addr += sizeof(u32);
87 }
88 break;
89 } 49 }
90 case SubmissionMode::NonIncreasingOld: 50
91 case SubmissionMode::NonIncreasing: { 51 if (method < static_cast<u32>(BufferMethods::CountBufferMethods)) {
92 // Use the same method value for all arguments. 52 // TODO(Subv): Research and implement these methods.
93 for (unsigned i = 0; i < header.arg_count; ++i) { 53 LOG_ERROR(HW_GPU, "Special buffer methods other than Bind are not implemented");
94 WriteReg(header.method, header.subchannel, Memory::Read32(current_addr), 54 return;
95 header.arg_count - i - 1); 55 }
96 current_addr += sizeof(u32); 56
97 } 57 const EngineID engine = bound_engines[subchannel];
58
59 switch (engine) {
60 case EngineID::FERMI_TWOD_A:
61 fermi_2d->WriteReg(method, value);
62 break;
63 case EngineID::MAXWELL_B:
64 maxwell_3d->WriteReg(method, value, remaining_params);
98 break; 65 break;
66 case EngineID::MAXWELL_COMPUTE_B:
67 maxwell_compute->WriteReg(method, value);
68 break;
69 case EngineID::MAXWELL_DMA_COPY_A:
70 maxwell_dma->WriteReg(method, value);
71 break;
72 default:
73 UNIMPLEMENTED_MSG("Unimplemented engine");
99 } 74 }
100 case SubmissionMode::IncreaseOnce: { 75 };
101 ASSERT(header.arg_count.Value() >= 1);
102 76
103 // Use the original method for the first argument and then the next method for all other 77 for (auto entry : commands) {
104 // arguments. 78 Tegra::GPUVAddr address = entry.Address();
105 WriteReg(header.method, header.subchannel, Memory::Read32(current_addr), 79 u32 size = entry.sz;
106 header.arg_count - 1); 80 const boost::optional<VAddr> head_address = memory_manager->GpuToCpuAddress(address);
81 VAddr current_addr = *head_address;
82 while (current_addr < *head_address + size * sizeof(CommandHeader)) {
83 const CommandHeader header = {Memory::Read32(current_addr)};
107 current_addr += sizeof(u32); 84 current_addr += sizeof(u32);
108 85
109 for (unsigned i = 1; i < header.arg_count; ++i) { 86 switch (header.mode.Value()) {
110 WriteReg(header.method + 1, header.subchannel, Memory::Read32(current_addr), 87 case SubmissionMode::IncreasingOld:
111 header.arg_count - i - 1); 88 case SubmissionMode::Increasing: {
89 // Increase the method value with each argument.
90 for (unsigned i = 0; i < header.arg_count; ++i) {
91 WriteReg(header.method + i, header.subchannel, Memory::Read32(current_addr),
92 header.arg_count - i - 1);
93 current_addr += sizeof(u32);
94 }
95 break;
96 }
97 case SubmissionMode::NonIncreasingOld:
98 case SubmissionMode::NonIncreasing: {
99 // Use the same method value for all arguments.
100 for (unsigned i = 0; i < header.arg_count; ++i) {
101 WriteReg(header.method, header.subchannel, Memory::Read32(current_addr),
102 header.arg_count - i - 1);
103 current_addr += sizeof(u32);
104 }
105 break;
106 }
107 case SubmissionMode::IncreaseOnce: {
108 ASSERT(header.arg_count.Value() >= 1);
109
110 // Use the original method for the first argument and then the next method for all
111 // other arguments.
112 WriteReg(header.method, header.subchannel, Memory::Read32(current_addr),
113 header.arg_count - 1);
112 current_addr += sizeof(u32); 114 current_addr += sizeof(u32);
115
116 for (unsigned i = 1; i < header.arg_count; ++i) {
117 WriteReg(header.method + 1, header.subchannel, Memory::Read32(current_addr),
118 header.arg_count - i - 1);
119 current_addr += sizeof(u32);
120 }
121 break;
122 }
123 case SubmissionMode::Inline: {
124 // The register value is stored in the bits 16-28 as an immediate
125 WriteReg(header.method, header.subchannel, header.inline_data, 0);
126 break;
127 }
128 default:
129 UNIMPLEMENTED();
113 } 130 }
114 break;
115 }
116 case SubmissionMode::Inline: {
117 // The register value is stored in the bits 16-28 as an immediate
118 WriteReg(header.method, header.subchannel, header.inline_data, 0);
119 break;
120 }
121 default:
122 UNIMPLEMENTED();
123 } 131 }
124 } 132 }
125} 133}
diff --git a/src/video_core/command_processor.h b/src/video_core/command_processor.h
index a01153e0b..bd766e77a 100644
--- a/src/video_core/command_processor.h
+++ b/src/video_core/command_processor.h
@@ -7,6 +7,7 @@
7#include <type_traits> 7#include <type_traits>
8#include "common/bit_field.h" 8#include "common/bit_field.h"
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "video_core/memory_manager.h"
10 11
11namespace Tegra { 12namespace Tegra {
12 13
@@ -19,6 +20,22 @@ enum class SubmissionMode : u32 {
19 IncreaseOnce = 5 20 IncreaseOnce = 5
20}; 21};
21 22
23struct CommandListHeader {
24 u32 entry0; // gpu_va_lo
25 union {
26 u32 entry1; // gpu_va_hi | (unk_0x02 << 0x08) | (size << 0x0A) | (unk_0x01 << 0x1F)
27 BitField<0, 8, u32> gpu_va_hi;
28 BitField<8, 2, u32> unk1;
29 BitField<10, 21, u32> sz;
30 BitField<31, 1, u32> unk2;
31 };
32
33 GPUVAddr Address() const {
34 return (static_cast<GPUVAddr>(gpu_va_hi) << 32) | entry0;
35 }
36};
37static_assert(sizeof(CommandListHeader) == 8, "CommandListHeader is incorrect size");
38
22union CommandHeader { 39union CommandHeader {
23 u32 hex; 40 u32 hex;
24 41
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index 1308080b5..329079ddd 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -135,8 +135,6 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) {
135 break; 135 break;
136 } 136 }
137 137
138 rasterizer.NotifyMaxwellRegisterChanged(method);
139
140 if (debug_context) { 138 if (debug_context) {
141 debug_context->OnEvent(Tegra::DebugContext::Event::MaxwellCommandProcessed, nullptr); 139 debug_context->OnEvent(Tegra::DebugContext::Event::MaxwellCommandProcessed, nullptr);
142 } 140 }
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index f59d01738..d3be900a4 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -533,7 +533,11 @@ public:
533 u32 stencil_back_mask; 533 u32 stencil_back_mask;
534 u32 stencil_back_func_mask; 534 u32 stencil_back_func_mask;
535 535
536 INSERT_PADDING_WORDS(0x20); 536 INSERT_PADDING_WORDS(0x13);
537
538 u32 rt_separate_frag_data;
539
540 INSERT_PADDING_WORDS(0xC);
537 541
538 struct { 542 struct {
539 u32 address_high; 543 u32 address_high;
@@ -557,7 +561,22 @@ public:
557 struct { 561 struct {
558 union { 562 union {
559 BitField<0, 4, u32> count; 563 BitField<0, 4, u32> count;
564 BitField<4, 3, u32> map_0;
565 BitField<7, 3, u32> map_1;
566 BitField<10, 3, u32> map_2;
567 BitField<13, 3, u32> map_3;
568 BitField<16, 3, u32> map_4;
569 BitField<19, 3, u32> map_5;
570 BitField<22, 3, u32> map_6;
571 BitField<25, 3, u32> map_7;
560 }; 572 };
573
574 u32 GetMap(size_t index) const {
575 const std::array<u32, NumRenderTargets> maps{map_0, map_1, map_2, map_3,
576 map_4, map_5, map_6, map_7};
577 ASSERT(index < maps.size());
578 return maps[index];
579 }
561 } rt_control; 580 } rt_control;
562 581
563 INSERT_PADDING_WORDS(0x2); 582 INSERT_PADDING_WORDS(0x2);
@@ -968,6 +987,7 @@ ASSERT_REG_POSITION(clear_stencil, 0x368);
968ASSERT_REG_POSITION(stencil_back_func_ref, 0x3D5); 987ASSERT_REG_POSITION(stencil_back_func_ref, 0x3D5);
969ASSERT_REG_POSITION(stencil_back_mask, 0x3D6); 988ASSERT_REG_POSITION(stencil_back_mask, 0x3D6);
970ASSERT_REG_POSITION(stencil_back_func_mask, 0x3D7); 989ASSERT_REG_POSITION(stencil_back_func_mask, 0x3D7);
990ASSERT_REG_POSITION(rt_separate_frag_data, 0x3EB);
971ASSERT_REG_POSITION(zeta, 0x3F8); 991ASSERT_REG_POSITION(zeta, 0x3F8);
972ASSERT_REG_POSITION(vertex_attrib_format, 0x458); 992ASSERT_REG_POSITION(vertex_attrib_format, 0x458);
973ASSERT_REG_POSITION(rt_control, 0x487); 993ASSERT_REG_POSITION(rt_control, 0x487);
diff --git a/src/video_core/engines/maxwell_dma.cpp b/src/video_core/engines/maxwell_dma.cpp
index 6e740713f..c24d33d5c 100644
--- a/src/video_core/engines/maxwell_dma.cpp
+++ b/src/video_core/engines/maxwell_dma.cpp
@@ -41,7 +41,6 @@ void MaxwellDMA::HandleCopy() {
41 41
42 // TODO(Subv): Perform more research and implement all features of this engine. 42 // TODO(Subv): Perform more research and implement all features of this engine.
43 ASSERT(regs.exec.enable_swizzle == 0); 43 ASSERT(regs.exec.enable_swizzle == 0);
44 ASSERT(regs.exec.enable_2d == 1);
45 ASSERT(regs.exec.query_mode == Regs::QueryMode::None); 44 ASSERT(regs.exec.query_mode == Regs::QueryMode::None);
46 ASSERT(regs.exec.query_intr == Regs::QueryIntr::None); 45 ASSERT(regs.exec.query_intr == Regs::QueryIntr::None);
47 ASSERT(regs.exec.copy_mode == Regs::CopyMode::Unk2); 46 ASSERT(regs.exec.copy_mode == Regs::CopyMode::Unk2);
@@ -51,10 +50,19 @@ void MaxwellDMA::HandleCopy() {
51 ASSERT(regs.dst_params.pos_y == 0); 50 ASSERT(regs.dst_params.pos_y == 0);
52 51
53 if (regs.exec.is_dst_linear == regs.exec.is_src_linear) { 52 if (regs.exec.is_dst_linear == regs.exec.is_src_linear) {
54 Memory::CopyBlock(dest_cpu, source_cpu, regs.x_count * regs.y_count); 53 size_t copy_size = regs.x_count;
54
55 // When the enable_2d bit is disabled, the copy is performed as if we were copying a 1D
56 // buffer of length `x_count`, otherwise we copy a 2D buffer of size (x_count, y_count).
57 if (regs.exec.enable_2d) {
58 copy_size = copy_size * regs.y_count;
59 }
60
61 Memory::CopyBlock(dest_cpu, source_cpu, copy_size);
55 return; 62 return;
56 } 63 }
57 64
65 ASSERT(regs.exec.enable_2d == 1);
58 u8* src_buffer = Memory::GetPointer(source_cpu); 66 u8* src_buffer = Memory::GetPointer(source_cpu);
59 u8* dst_buffer = Memory::GetPointer(dest_cpu); 67 u8* dst_buffer = Memory::GetPointer(dest_cpu);
60 68
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index d2388673e..2db906ea5 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -244,6 +244,16 @@ enum class TextureType : u64 {
244 TextureCube = 3, 244 TextureCube = 3,
245}; 245};
246 246
247enum class TextureQueryType : u64 {
248 Dimension = 1,
249 TextureType = 2,
250 SamplePosition = 5,
251 Filter = 16,
252 LevelOfDetail = 18,
253 Wrap = 20,
254 BorderColor = 22,
255};
256
247enum class IpaInterpMode : u64 { Linear = 0, Perspective = 1, Flat = 2, Sc = 3 }; 257enum class IpaInterpMode : u64 { Linear = 0, Perspective = 1, Flat = 2, Sc = 3 };
248enum class IpaSampleMode : u64 { Default = 0, Centroid = 1, Offset = 2 }; 258enum class IpaSampleMode : u64 { Default = 0, Centroid = 1, Offset = 2 };
249 259
@@ -414,6 +424,45 @@ union Instruction {
414 } bfe; 424 } bfe;
415 425
416 union { 426 union {
427 BitField<48, 3, u64> pred48;
428
429 union {
430 BitField<20, 20, u64> entry_a;
431 BitField<39, 5, u64> entry_b;
432 BitField<45, 1, u64> neg;
433 BitField<46, 1, u64> uses_cc;
434 } imm;
435
436 union {
437 BitField<20, 14, u64> cb_index;
438 BitField<34, 5, u64> cb_offset;
439 BitField<56, 1, u64> neg;
440 BitField<57, 1, u64> uses_cc;
441 } hi;
442
443 union {
444 BitField<20, 14, u64> cb_index;
445 BitField<34, 5, u64> cb_offset;
446 BitField<39, 5, u64> entry_a;
447 BitField<45, 1, u64> neg;
448 BitField<46, 1, u64> uses_cc;
449 } rz;
450
451 union {
452 BitField<39, 5, u64> entry_a;
453 BitField<45, 1, u64> neg;
454 BitField<46, 1, u64> uses_cc;
455 } r1;
456
457 union {
458 BitField<28, 8, u64> entry_a;
459 BitField<37, 1, u64> neg;
460 BitField<38, 1, u64> uses_cc;
461 } r2;
462
463 } lea;
464
465 union {
417 BitField<0, 5, FlowCondition> cond; 466 BitField<0, 5, FlowCondition> cond;
418 } flow; 467 } flow;
419 468
@@ -468,6 +517,18 @@ union Instruction {
468 } psetp; 517 } psetp;
469 518
470 union { 519 union {
520 BitField<12, 3, u64> pred12;
521 BitField<15, 1, u64> neg_pred12;
522 BitField<24, 2, PredOperation> cond;
523 BitField<29, 3, u64> pred29;
524 BitField<32, 1, u64> neg_pred29;
525 BitField<39, 3, u64> pred39;
526 BitField<42, 1, u64> neg_pred39;
527 BitField<44, 1, u64> bf;
528 BitField<45, 2, PredOperation> op;
529 } pset;
530
531 union {
471 BitField<39, 3, u64> pred39; 532 BitField<39, 3, u64> pred39;
472 BitField<42, 1, u64> neg_pred; 533 BitField<42, 1, u64> neg_pred;
473 BitField<43, 1, u64> neg_a; 534 BitField<43, 1, u64> neg_a;
@@ -519,6 +580,21 @@ union Instruction {
519 } tex; 580 } tex;
520 581
521 union { 582 union {
583 BitField<22, 6, TextureQueryType> query_type;
584 BitField<31, 4, u64> component_mask;
585 } txq;
586
587 union {
588 BitField<28, 1, u64> array;
589 BitField<29, 2, TextureType> texture_type;
590 BitField<31, 4, u64> component_mask;
591
592 bool IsComponentEnabled(size_t component) const {
593 return ((1ull << component) & component_mask) != 0;
594 }
595 } tmml;
596
597 union {
522 BitField<28, 1, u64> array; 598 BitField<28, 1, u64> array;
523 BitField<29, 2, TextureType> texture_type; 599 BitField<29, 2, TextureType> texture_type;
524 BitField<56, 2, u64> component; 600 BitField<56, 2, u64> component;
@@ -670,11 +746,13 @@ public:
670 LDG, // Load from global memory 746 LDG, // Load from global memory
671 STG, // Store in global memory 747 STG, // Store in global memory
672 TEX, 748 TEX,
673 TEXQ, // Texture Query 749 TXQ, // Texture Query
674 TEXS, // Texture Fetch with scalar/non-vec4 source/destinations 750 TEXS, // Texture Fetch with scalar/non-vec4 source/destinations
675 TLDS, // Texture Load with scalar/non-vec4 source/destinations 751 TLDS, // Texture Load with scalar/non-vec4 source/destinations
676 TLD4, // Texture Load 4 752 TLD4, // Texture Load 4
677 TLD4S, // Texture Load 4 with scalar / non - vec4 source / destinations 753 TLD4S, // Texture Load 4 with scalar / non - vec4 source / destinations
754 TMML_B, // Texture Mip Map Level
755 TMML, // Texture Mip Map Level
678 EXIT, 756 EXIT,
679 IPA, 757 IPA,
680 FFMA_IMM, // Fused Multiply and Add 758 FFMA_IMM, // Fused Multiply and Add
@@ -699,6 +777,11 @@ public:
699 ISCADD_C, // Scale and Add 777 ISCADD_C, // Scale and Add
700 ISCADD_R, 778 ISCADD_R,
701 ISCADD_IMM, 779 ISCADD_IMM,
780 LEA_R1,
781 LEA_R2,
782 LEA_RZ,
783 LEA_IMM,
784 LEA_HI,
702 POPC_C, 785 POPC_C,
703 POPC_R, 786 POPC_R,
704 POPC_IMM, 787 POPC_IMM,
@@ -757,6 +840,7 @@ public:
757 ISET_C, 840 ISET_C,
758 ISET_IMM, 841 ISET_IMM,
759 PSETP, 842 PSETP,
843 PSET,
760 XMAD_IMM, 844 XMAD_IMM,
761 XMAD_CR, 845 XMAD_CR,
762 XMAD_RC, 846 XMAD_RC,
@@ -780,6 +864,7 @@ public:
780 IntegerSet, 864 IntegerSet,
781 IntegerSetPredicate, 865 IntegerSetPredicate,
782 PredicateSetPredicate, 866 PredicateSetPredicate,
867 PredicateSetRegister,
783 Conversion, 868 Conversion,
784 Xmad, 869 Xmad,
785 Unknown, 870 Unknown,
@@ -894,11 +979,13 @@ private:
894 INST("1110111011010---", Id::LDG, Type::Memory, "LDG"), 979 INST("1110111011010---", Id::LDG, Type::Memory, "LDG"),
895 INST("1110111011011---", Id::STG, Type::Memory, "STG"), 980 INST("1110111011011---", Id::STG, Type::Memory, "STG"),
896 INST("110000----111---", Id::TEX, Type::Memory, "TEX"), 981 INST("110000----111---", Id::TEX, Type::Memory, "TEX"),
897 INST("1101111101001---", Id::TEXQ, Type::Memory, "TEXQ"), 982 INST("1101111101001---", Id::TXQ, Type::Memory, "TXQ"),
898 INST("1101100---------", Id::TEXS, Type::Memory, "TEXS"), 983 INST("1101100---------", Id::TEXS, Type::Memory, "TEXS"),
899 INST("1101101---------", Id::TLDS, Type::Memory, "TLDS"), 984 INST("1101101---------", Id::TLDS, Type::Memory, "TLDS"),
900 INST("110010----111---", Id::TLD4, Type::Memory, "TLD4"), 985 INST("110010----111---", Id::TLD4, Type::Memory, "TLD4"),
901 INST("1101111100------", Id::TLD4S, Type::Memory, "TLD4S"), 986 INST("1101111100------", Id::TLD4S, Type::Memory, "TLD4S"),
987 INST("110111110110----", Id::TMML_B, Type::Memory, "TMML_B"),
988 INST("1101111101011---", Id::TMML, Type::Memory, "TMML"),
902 INST("111000110000----", Id::EXIT, Type::Trivial, "EXIT"), 989 INST("111000110000----", Id::EXIT, Type::Trivial, "EXIT"),
903 INST("11100000--------", Id::IPA, Type::Trivial, "IPA"), 990 INST("11100000--------", Id::IPA, Type::Trivial, "IPA"),
904 INST("0011001-1-------", Id::FFMA_IMM, Type::Ffma, "FFMA_IMM"), 991 INST("0011001-1-------", Id::FFMA_IMM, Type::Ffma, "FFMA_IMM"),
@@ -929,6 +1016,11 @@ private:
929 INST("0100110010100---", Id::SEL_C, Type::ArithmeticInteger, "SEL_C"), 1016 INST("0100110010100---", Id::SEL_C, Type::ArithmeticInteger, "SEL_C"),
930 INST("0101110010100---", Id::SEL_R, Type::ArithmeticInteger, "SEL_R"), 1017 INST("0101110010100---", Id::SEL_R, Type::ArithmeticInteger, "SEL_R"),
931 INST("0011100-10100---", Id::SEL_IMM, Type::ArithmeticInteger, "SEL_IMM"), 1018 INST("0011100-10100---", Id::SEL_IMM, Type::ArithmeticInteger, "SEL_IMM"),
1019 INST("0101101111011---", Id::LEA_R2, Type::ArithmeticInteger, "LEA_R2"),
1020 INST("0101101111010---", Id::LEA_R1, Type::ArithmeticInteger, "LEA_R1"),
1021 INST("001101101101----", Id::LEA_IMM, Type::ArithmeticInteger, "LEA_IMM"),
1022 INST("010010111101----", Id::LEA_RZ, Type::ArithmeticInteger, "LEA_RZ"),
1023 INST("00011000--------", Id::LEA_HI, Type::ArithmeticInteger, "LEA_HI"),
932 INST("0101000010000---", Id::MUFU, Type::Arithmetic, "MUFU"), 1024 INST("0101000010000---", Id::MUFU, Type::Arithmetic, "MUFU"),
933 INST("0100110010010---", Id::RRO_C, Type::Arithmetic, "RRO_C"), 1025 INST("0100110010010---", Id::RRO_C, Type::Arithmetic, "RRO_C"),
934 INST("0101110010010---", Id::RRO_R, Type::Arithmetic, "RRO_R"), 1026 INST("0101110010010---", Id::RRO_R, Type::Arithmetic, "RRO_R"),
@@ -983,6 +1075,7 @@ private:
983 INST("010110110101----", Id::ISET_R, Type::IntegerSet, "ISET_R"), 1075 INST("010110110101----", Id::ISET_R, Type::IntegerSet, "ISET_R"),
984 INST("010010110101----", Id::ISET_C, Type::IntegerSet, "ISET_C"), 1076 INST("010010110101----", Id::ISET_C, Type::IntegerSet, "ISET_C"),
985 INST("0011011-0101----", Id::ISET_IMM, Type::IntegerSet, "ISET_IMM"), 1077 INST("0011011-0101----", Id::ISET_IMM, Type::IntegerSet, "ISET_IMM"),
1078 INST("0101000010001---", Id::PSET, Type::PredicateSetRegister, "PSET"),
986 INST("0101000010010---", Id::PSETP, Type::PredicateSetPredicate, "PSETP"), 1079 INST("0101000010010---", Id::PSETP, Type::PredicateSetPredicate, "PSETP"),
987 INST("0011011-00------", Id::XMAD_IMM, Type::Xmad, "XMAD_IMM"), 1080 INST("0011011-00------", Id::XMAD_IMM, Type::Xmad, "XMAD_IMM"),
988 INST("0100111---------", Id::XMAD_CR, Type::Xmad, "XMAD_CR"), 1081 INST("0100111---------", Id::XMAD_CR, Type::Xmad, "XMAD_CR"),
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp
index e6d8e65c6..86a809f86 100644
--- a/src/video_core/gpu.cpp
+++ b/src/video_core/gpu.cpp
@@ -66,6 +66,7 @@ u32 RenderTargetBytesPerPixel(RenderTargetFormat format) {
66 case RenderTargetFormat::RGBA8_UINT: 66 case RenderTargetFormat::RGBA8_UINT:
67 case RenderTargetFormat::RGB10_A2_UNORM: 67 case RenderTargetFormat::RGB10_A2_UNORM:
68 case RenderTargetFormat::BGRA8_UNORM: 68 case RenderTargetFormat::BGRA8_UNORM:
69 case RenderTargetFormat::BGRA8_SRGB:
69 case RenderTargetFormat::RG16_UNORM: 70 case RenderTargetFormat::RG16_UNORM:
70 case RenderTargetFormat::RG16_SNORM: 71 case RenderTargetFormat::RG16_SNORM:
71 case RenderTargetFormat::RG16_UINT: 72 case RenderTargetFormat::RG16_UINT:
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h
index d29f31f52..589a59b4f 100644
--- a/src/video_core/gpu.h
+++ b/src/video_core/gpu.h
@@ -6,6 +6,7 @@
6 6
7#include <array> 7#include <array>
8#include <memory> 8#include <memory>
9#include <vector>
9#include "common/common_types.h" 10#include "common/common_types.h"
10#include "core/hle/service/nvflinger/buffer_queue.h" 11#include "core/hle/service/nvflinger/buffer_queue.h"
11#include "video_core/memory_manager.h" 12#include "video_core/memory_manager.h"
@@ -26,6 +27,7 @@ enum class RenderTargetFormat : u32 {
26 RG32_FLOAT = 0xCB, 27 RG32_FLOAT = 0xCB,
27 RG32_UINT = 0xCD, 28 RG32_UINT = 0xCD,
28 BGRA8_UNORM = 0xCF, 29 BGRA8_UNORM = 0xCF,
30 BGRA8_SRGB = 0xD0,
29 RGB10_A2_UNORM = 0xD1, 31 RGB10_A2_UNORM = 0xD1,
30 RGBA8_UNORM = 0xD5, 32 RGBA8_UNORM = 0xD5,
31 RGBA8_SRGB = 0xD6, 33 RGBA8_SRGB = 0xD6,
@@ -67,6 +69,7 @@ u32 RenderTargetBytesPerPixel(RenderTargetFormat format);
67/// Returns the number of bytes per pixel of each depth format. 69/// Returns the number of bytes per pixel of each depth format.
68u32 DepthFormatBytesPerPixel(DepthFormat format); 70u32 DepthFormatBytesPerPixel(DepthFormat format);
69 71
72struct CommandListHeader;
70class DebugContext; 73class DebugContext;
71 74
72/** 75/**
@@ -115,7 +118,7 @@ public:
115 ~GPU(); 118 ~GPU();
116 119
117 /// Processes a command list stored at the specified address in GPU memory. 120 /// Processes a command list stored at the specified address in GPU memory.
118 void ProcessCommandList(GPUVAddr address, u32 size); 121 void ProcessCommandLists(const std::vector<CommandListHeader>& commands);
119 122
120 /// Returns a reference to the Maxwell3D GPU engine. 123 /// Returns a reference to the Maxwell3D GPU engine.
121 Engines::Maxwell3D& Maxwell3D(); 124 Engines::Maxwell3D& Maxwell3D();
@@ -130,9 +133,6 @@ public:
130 const Tegra::MemoryManager& MemoryManager() const; 133 const Tegra::MemoryManager& MemoryManager() const;
131 134
132private: 135private:
133 /// Writes a single register in the engine bound to the specified subchannel
134 void WriteReg(u32 method, u32 subchannel, u32 value, u32 remaining_params);
135
136 std::unique_ptr<Tegra::MemoryManager> memory_manager; 136 std::unique_ptr<Tegra::MemoryManager> memory_manager;
137 137
138 /// Mapping of command subchannels to their bound engine ids. 138 /// Mapping of command subchannels to their bound engine ids.
diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h
index 9d78e8b6b..cd819d69f 100644
--- a/src/video_core/rasterizer_interface.h
+++ b/src/video_core/rasterizer_interface.h
@@ -20,9 +20,6 @@ public:
20 /// Clear the current framebuffer 20 /// Clear the current framebuffer
21 virtual void Clear() = 0; 21 virtual void Clear() = 0;
22 22
23 /// Notify rasterizer that the specified Maxwell register has been changed
24 virtual void NotifyMaxwellRegisterChanged(u32 method) = 0;
25
26 /// Notify rasterizer that all caches should be flushed to Switch memory 23 /// Notify rasterizer that all caches should be flushed to Switch memory
27 virtual void FlushAll() = 0; 24 virtual void FlushAll() = 0;
28 25
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index e6d6917fa..c59f3af1b 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -294,61 +294,80 @@ void RasterizerOpenGL::UpdatePagesCachedCount(VAddr addr, u64 size, int delta) {
294 cached_pages.add({pages_interval, delta}); 294 cached_pages.add({pages_interval, delta});
295} 295}
296 296
297std::pair<Surface, Surface> RasterizerOpenGL::ConfigureFramebuffers(bool using_color_fb, 297void RasterizerOpenGL::ConfigureFramebuffers(bool using_color_fb, bool using_depth_fb,
298 bool using_depth_fb, 298 bool preserve_contents,
299 bool preserve_contents) { 299 boost::optional<size_t> single_color_target) {
300 MICROPROFILE_SCOPE(OpenGL_Framebuffer); 300 MICROPROFILE_SCOPE(OpenGL_Framebuffer);
301 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; 301 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
302 302
303 if (regs.rt[0].format == Tegra::RenderTargetFormat::NONE) { 303 Surface depth_surface;
304 LOG_ERROR(HW_GPU, "RenderTargetFormat is not configured"); 304 if (using_depth_fb) {
305 using_color_fb = false; 305 depth_surface = res_cache.GetDepthBufferSurface(preserve_contents);
306 } 306 }
307 307
308 const bool has_stencil = regs.stencil_enable; 308 // TODO(bunnei): Figure out how the below register works. According to envytools, this should be
309 const bool write_color_fb = 309 // used to enable multiple render targets. However, it is left unset on all games that I have
310 state.color_mask.red_enabled == GL_TRUE || state.color_mask.green_enabled == GL_TRUE || 310 // tested.
311 state.color_mask.blue_enabled == GL_TRUE || state.color_mask.alpha_enabled == GL_TRUE; 311 ASSERT_MSG(regs.rt_separate_frag_data == 0, "Unimplemented");
312
313 const bool write_depth_fb =
314 (state.depth.test_enabled && state.depth.write_mask == GL_TRUE) ||
315 (has_stencil && (state.stencil.front.write_mask || state.stencil.back.write_mask));
316 312
317 Surface color_surface; 313 // Bind the framebuffer surfaces
318 Surface depth_surface; 314 state.draw.draw_framebuffer = framebuffer.handle;
319 MathUtil::Rectangle<u32> surfaces_rect; 315 state.Apply();
320 std::tie(color_surface, depth_surface, surfaces_rect) =
321 res_cache.GetFramebufferSurfaces(using_color_fb, using_depth_fb, preserve_contents);
322 316
323 const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[0].GetRect()}; 317 if (using_color_fb) {
324 const MathUtil::Rectangle<u32> draw_rect{ 318 if (single_color_target) {
325 static_cast<u32>(std::clamp<s32>(static_cast<s32>(surfaces_rect.left) + viewport_rect.left, 319 // Used when just a single color attachment is enabled, e.g. for clearing a color buffer
326 surfaces_rect.left, surfaces_rect.right)), // Left 320 Surface color_surface =
327 static_cast<u32>(std::clamp<s32>(static_cast<s32>(surfaces_rect.bottom) + viewport_rect.top, 321 res_cache.GetColorBufferSurface(*single_color_target, preserve_contents);
328 surfaces_rect.bottom, surfaces_rect.top)), // Top 322 glFramebufferTexture2D(
329 static_cast<u32>(std::clamp<s32>(static_cast<s32>(surfaces_rect.left) + viewport_rect.right, 323 GL_DRAW_FRAMEBUFFER,
330 surfaces_rect.left, surfaces_rect.right)), // Right 324 GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(*single_color_target), GL_TEXTURE_2D,
331 static_cast<u32>( 325 color_surface != nullptr ? color_surface->Texture().handle : 0, 0);
332 std::clamp<s32>(static_cast<s32>(surfaces_rect.bottom) + viewport_rect.bottom, 326 glDrawBuffer(GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(*single_color_target));
333 surfaces_rect.bottom, surfaces_rect.top))}; // Bottom 327 } else {
328 // Multiple color attachments are enabled
329 std::array<GLenum, Maxwell::NumRenderTargets> buffers;
330 for (size_t index = 0; index < Maxwell::NumRenderTargets; ++index) {
331 Surface color_surface = res_cache.GetColorBufferSurface(index, preserve_contents);
332 buffers[index] = GL_COLOR_ATTACHMENT0 + regs.rt_control.GetMap(index);
333 glFramebufferTexture2D(
334 GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(index),
335 GL_TEXTURE_2D, color_surface != nullptr ? color_surface->Texture().handle : 0,
336 0);
337 }
338 glDrawBuffers(regs.rt_control.count, buffers.data());
339 }
340 } else {
341 // No color attachments are enabled - zero out all of them
342 for (size_t index = 0; index < Maxwell::NumRenderTargets; ++index) {
343 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
344 GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(index), GL_TEXTURE_2D,
345 0, 0);
346 }
347 glDrawBuffer(GL_NONE);
348 }
334 349
335 // Bind the framebuffer surfaces 350 if (depth_surface) {
336 BindFramebufferSurfaces(color_surface, depth_surface, has_stencil); 351 if (regs.stencil_enable) {
352 // Attach both depth and stencil
353 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
354 depth_surface->Texture().handle, 0);
355 } else {
356 // Attach depth
357 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D,
358 depth_surface->Texture().handle, 0);
359 // Clear stencil attachment
360 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
361 }
362 } else {
363 // Clear both depth and stencil attachment
364 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0,
365 0);
366 }
337 367
338 SyncViewport(surfaces_rect); 368 SyncViewport();
339 369
340 // Viewport can have negative offsets or larger dimensions than our framebuffer sub-rect. Enable
341 // scissor test to prevent drawing outside of the framebuffer region
342 state.scissor.enabled = true;
343 state.scissor.x = draw_rect.left;
344 state.scissor.y = draw_rect.bottom;
345 state.scissor.width = draw_rect.GetWidth();
346 state.scissor.height = draw_rect.GetHeight();
347 state.Apply(); 370 state.Apply();
348
349 // Only return the surface to be marked as dirty if writing to it is enabled.
350 return std::make_pair(write_color_fb ? color_surface : nullptr,
351 write_depth_fb ? depth_surface : nullptr);
352} 371}
353 372
354void RasterizerOpenGL::Clear() { 373void RasterizerOpenGL::Clear() {
@@ -356,8 +375,9 @@ void RasterizerOpenGL::Clear() {
356 SCOPE_EXIT({ prev_state.Apply(); }); 375 SCOPE_EXIT({ prev_state.Apply(); });
357 376
358 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; 377 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
359 bool use_color_fb = false; 378 bool use_color{};
360 bool use_depth_fb = false; 379 bool use_depth{};
380 bool use_stencil{};
361 381
362 OpenGLState clear_state; 382 OpenGLState clear_state;
363 clear_state.draw.draw_framebuffer = state.draw.draw_framebuffer; 383 clear_state.draw.draw_framebuffer = state.draw.draw_framebuffer;
@@ -366,22 +386,13 @@ void RasterizerOpenGL::Clear() {
366 clear_state.color_mask.blue_enabled = regs.clear_buffers.B ? GL_TRUE : GL_FALSE; 386 clear_state.color_mask.blue_enabled = regs.clear_buffers.B ? GL_TRUE : GL_FALSE;
367 clear_state.color_mask.alpha_enabled = regs.clear_buffers.A ? GL_TRUE : GL_FALSE; 387 clear_state.color_mask.alpha_enabled = regs.clear_buffers.A ? GL_TRUE : GL_FALSE;
368 388
369 GLbitfield clear_mask{};
370 if (regs.clear_buffers.R || regs.clear_buffers.G || regs.clear_buffers.B || 389 if (regs.clear_buffers.R || regs.clear_buffers.G || regs.clear_buffers.B ||
371 regs.clear_buffers.A) { 390 regs.clear_buffers.A) {
372 if (regs.clear_buffers.RT == 0) { 391 use_color = true;
373 // We only support clearing the first color attachment for now
374 clear_mask |= GL_COLOR_BUFFER_BIT;
375 use_color_fb = true;
376 } else {
377 // TODO(subv): Add support for the other color attachments
378 LOG_CRITICAL(HW_GPU, "Clear unimplemented for RT {}", regs.clear_buffers.RT);
379 }
380 } 392 }
381 if (regs.clear_buffers.Z) { 393 if (regs.clear_buffers.Z) {
382 ASSERT_MSG(regs.zeta_enable != 0, "Tried to clear Z but buffer is not enabled!"); 394 ASSERT_MSG(regs.zeta_enable != 0, "Tried to clear Z but buffer is not enabled!");
383 use_depth_fb = true; 395 use_depth = true;
384 clear_mask |= GL_DEPTH_BUFFER_BIT;
385 396
386 // Always enable the depth write when clearing the depth buffer. The depth write mask is 397 // Always enable the depth write when clearing the depth buffer. The depth write mask is
387 // ignored when clearing the buffer in the Switch, but OpenGL obeys it so we set it to true. 398 // ignored when clearing the buffer in the Switch, but OpenGL obeys it so we set it to true.
@@ -390,34 +401,33 @@ void RasterizerOpenGL::Clear() {
390 } 401 }
391 if (regs.clear_buffers.S) { 402 if (regs.clear_buffers.S) {
392 ASSERT_MSG(regs.zeta_enable != 0, "Tried to clear stencil but buffer is not enabled!"); 403 ASSERT_MSG(regs.zeta_enable != 0, "Tried to clear stencil but buffer is not enabled!");
393 use_depth_fb = true; 404 use_stencil = true;
394 clear_mask |= GL_STENCIL_BUFFER_BIT;
395 clear_state.stencil.test_enabled = true; 405 clear_state.stencil.test_enabled = true;
396 } 406 }
397 407
398 if (!use_color_fb && !use_depth_fb) { 408 if (!use_color && !use_depth && !use_stencil) {
399 // No color surface nor depth/stencil surface are enabled 409 // No color surface nor depth/stencil surface are enabled
400 return; 410 return;
401 } 411 }
402 412
403 if (clear_mask == 0) {
404 // No clear mask is enabled
405 return;
406 }
407
408 ScopeAcquireGLContext acquire_context{emu_window}; 413 ScopeAcquireGLContext acquire_context{emu_window};
409 414
410 auto [dirty_color_surface, dirty_depth_surface] = 415 ConfigureFramebuffers(use_color, use_depth || use_stencil, false,
411 ConfigureFramebuffers(use_color_fb, use_depth_fb, false); 416 regs.clear_buffers.RT.Value());
412 417
413 clear_state.Apply(); 418 clear_state.Apply();
414 419
415 glClearColor(regs.clear_color[0], regs.clear_color[1], regs.clear_color[2], 420 if (use_color) {
416 regs.clear_color[3]); 421 glClearBufferfv(GL_COLOR, regs.clear_buffers.RT, regs.clear_color);
417 glClearDepth(regs.clear_depth); 422 }
418 glClearStencil(regs.clear_stencil);
419 423
420 glClear(clear_mask); 424 if (use_depth && use_stencil) {
425 glClearBufferfi(GL_DEPTH_STENCIL, 0, regs.clear_depth, regs.clear_stencil);
426 } else if (use_depth) {
427 glClearBufferfv(GL_DEPTH, 0, &regs.clear_depth);
428 } else if (use_stencil) {
429 glClearBufferiv(GL_STENCIL, 0, &regs.clear_stencil);
430 }
421} 431}
422 432
423void RasterizerOpenGL::DrawArrays() { 433void RasterizerOpenGL::DrawArrays() {
@@ -430,8 +440,7 @@ void RasterizerOpenGL::DrawArrays() {
430 440
431 ScopeAcquireGLContext acquire_context{emu_window}; 441 ScopeAcquireGLContext acquire_context{emu_window};
432 442
433 const auto [dirty_color_surface, dirty_depth_surface] = 443 ConfigureFramebuffers();
434 ConfigureFramebuffers(true, regs.zeta.Address() != 0 && regs.zeta_enable != 0, true);
435 444
436 SyncDepthTestState(); 445 SyncDepthTestState();
437 SyncStencilTestState(); 446 SyncStencilTestState();
@@ -525,8 +534,6 @@ void RasterizerOpenGL::DrawArrays() {
525 state.Apply(); 534 state.Apply();
526} 535}
527 536
528void RasterizerOpenGL::NotifyMaxwellRegisterChanged(u32 method) {}
529
530void RasterizerOpenGL::FlushAll() {} 537void RasterizerOpenGL::FlushAll() {}
531 538
532void RasterizerOpenGL::FlushRegion(VAddr addr, u64 size) {} 539void RasterizerOpenGL::FlushRegion(VAddr addr, u64 size) {}
@@ -729,38 +736,12 @@ u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, Shader& shader,
729 return current_unit + static_cast<u32>(entries.size()); 736 return current_unit + static_cast<u32>(entries.size());
730} 737}
731 738
732void RasterizerOpenGL::BindFramebufferSurfaces(const Surface& color_surface, 739void RasterizerOpenGL::SyncViewport() {
733 const Surface& depth_surface, bool has_stencil) {
734 state.draw.draw_framebuffer = framebuffer.handle;
735 state.Apply();
736
737 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
738 color_surface != nullptr ? color_surface->Texture().handle : 0, 0);
739 if (depth_surface != nullptr) {
740 if (has_stencil) {
741 // attach both depth and stencil
742 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
743 depth_surface->Texture().handle, 0);
744 } else {
745 // attach depth
746 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D,
747 depth_surface->Texture().handle, 0);
748 // clear stencil attachment
749 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
750 }
751 } else {
752 // clear both depth and stencil attachment
753 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0,
754 0);
755 }
756}
757
758void RasterizerOpenGL::SyncViewport(const MathUtil::Rectangle<u32>& surfaces_rect) {
759 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; 740 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
760 const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[0].GetRect()}; 741 const MathUtil::Rectangle<s32> viewport_rect{regs.viewport_transform[0].GetRect()};
761 742
762 state.viewport.x = static_cast<GLint>(surfaces_rect.left) + viewport_rect.left; 743 state.viewport.x = viewport_rect.left;
763 state.viewport.y = static_cast<GLint>(surfaces_rect.bottom) + viewport_rect.bottom; 744 state.viewport.y = viewport_rect.bottom;
764 state.viewport.width = static_cast<GLsizei>(viewport_rect.GetWidth()); 745 state.viewport.width = static_cast<GLsizei>(viewport_rect.GetWidth());
765 state.viewport.height = static_cast<GLsizei>(viewport_rect.GetHeight()); 746 state.viewport.height = static_cast<GLsizei>(viewport_rect.GetHeight());
766} 747}
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index c6bb1516b..745c3dc0c 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -13,6 +13,7 @@
13#include <vector> 13#include <vector>
14 14
15#include <boost/icl/interval_map.hpp> 15#include <boost/icl/interval_map.hpp>
16#include <boost/optional.hpp>
16#include <boost/range/iterator_range.hpp> 17#include <boost/range/iterator_range.hpp>
17#include <glad/glad.h> 18#include <glad/glad.h>
18 19
@@ -45,7 +46,6 @@ public:
45 46
46 void DrawArrays() override; 47 void DrawArrays() override;
47 void Clear() override; 48 void Clear() override;
48 void NotifyMaxwellRegisterChanged(u32 method) override;
49 void FlushAll() override; 49 void FlushAll() override;
50 void FlushRegion(VAddr addr, u64 size) override; 50 void FlushRegion(VAddr addr, u64 size) override;
51 void InvalidateRegion(VAddr addr, u64 size) override; 51 void InvalidateRegion(VAddr addr, u64 size) override;
@@ -97,14 +97,16 @@ private:
97 GLvec4 border_color; 97 GLvec4 border_color;
98 }; 98 };
99 99
100 /// Configures the color and depth framebuffer states and returns the dirty <Color, Depth> 100 /**
101 /// surfaces if writing was enabled. 101 * Configures the color and depth framebuffer states.
102 std::pair<Surface, Surface> ConfigureFramebuffers(bool using_color_fb, bool using_depth_fb, 102 * @param use_color_fb If true, configure color framebuffers.
103 bool preserve_contents); 103 * @param using_depth_fb If true, configure the depth/stencil framebuffer.
104 104 * @param preserve_contents If true, tries to preserve data from a previously used framebuffer.
105 /// Binds the framebuffer color and depth surface 105 * @param single_color_target Specifies if a single color buffer target should be used.
106 void BindFramebufferSurfaces(const Surface& color_surface, const Surface& depth_surface, 106 */
107 bool has_stencil); 107 void ConfigureFramebuffers(bool use_color_fb = true, bool using_depth_fb = true,
108 bool preserve_contents = true,
109 boost::optional<size_t> single_color_target = {});
108 110
109 /* 111 /*
110 * Configures the current constbuffers to use for the draw command. 112 * Configures the current constbuffers to use for the draw command.
@@ -127,7 +129,7 @@ private:
127 u32 current_unit); 129 u32 current_unit);
128 130
129 /// Syncs the viewport to match the guest state 131 /// Syncs the viewport to match the guest state
130 void SyncViewport(const MathUtil::Rectangle<u32>& surfaces_rect); 132 void SyncViewport();
131 133
132 /// Syncs the clip enabled status to match the guest state 134 /// Syncs the clip enabled status to match the guest state
133 void SyncClipEnabled(); 135 void SyncClipEnabled();
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index 360fb0cd5..fb56decc0 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -52,17 +52,31 @@ static VAddr TryGetCpuAddr(Tegra::GPUVAddr gpu_addr) {
52 params.type = GetFormatType(params.pixel_format); 52 params.type = GetFormatType(params.pixel_format);
53 params.width = Common::AlignUp(config.tic.Width(), GetCompressionFactor(params.pixel_format)); 53 params.width = Common::AlignUp(config.tic.Width(), GetCompressionFactor(params.pixel_format));
54 params.height = Common::AlignUp(config.tic.Height(), GetCompressionFactor(params.pixel_format)); 54 params.height = Common::AlignUp(config.tic.Height(), GetCompressionFactor(params.pixel_format));
55 params.depth = config.tic.Depth();
56 params.unaligned_height = config.tic.Height(); 55 params.unaligned_height = config.tic.Height();
57 params.size_in_bytes = params.SizeInBytes();
58 params.cache_width = Common::AlignUp(params.width, 8);
59 params.cache_height = Common::AlignUp(params.height, 8);
60 params.target = SurfaceTargetFromTextureType(config.tic.texture_type); 56 params.target = SurfaceTargetFromTextureType(config.tic.texture_type);
57
58 switch (params.target) {
59 case SurfaceTarget::Texture1D:
60 case SurfaceTarget::Texture2D:
61 params.depth = 1;
62 break;
63 case SurfaceTarget::Texture3D:
64 case SurfaceTarget::Texture2DArray:
65 params.depth = config.tic.Depth();
66 break;
67 default:
68 LOG_CRITICAL(HW_GPU, "Unknown depth for target={}", static_cast<u32>(params.target));
69 UNREACHABLE();
70 params.depth = 1;
71 break;
72 }
73
74 params.size_in_bytes = params.SizeInBytes();
61 return params; 75 return params;
62} 76}
63 77
64/*static*/ SurfaceParams SurfaceParams::CreateForFramebuffer( 78/*static*/ SurfaceParams SurfaceParams::CreateForFramebuffer(size_t index) {
65 const Tegra::Engines::Maxwell3D::Regs::RenderTargetConfig& config) { 79 const auto& config{Core::System::GetInstance().GPU().Maxwell3D().regs.rt[index]};
66 SurfaceParams params{}; 80 SurfaceParams params{};
67 params.addr = TryGetCpuAddr(config.Address()); 81 params.addr = TryGetCpuAddr(config.Address());
68 params.is_tiled = true; 82 params.is_tiled = true;
@@ -72,12 +86,10 @@ static VAddr TryGetCpuAddr(Tegra::GPUVAddr gpu_addr) {
72 params.type = GetFormatType(params.pixel_format); 86 params.type = GetFormatType(params.pixel_format);
73 params.width = config.width; 87 params.width = config.width;
74 params.height = config.height; 88 params.height = config.height;
75 params.depth = 1;
76 params.unaligned_height = config.height; 89 params.unaligned_height = config.height;
77 params.size_in_bytes = params.SizeInBytes();
78 params.cache_width = Common::AlignUp(params.width, 8);
79 params.cache_height = Common::AlignUp(params.height, 8);
80 params.target = SurfaceTarget::Texture2D; 90 params.target = SurfaceTarget::Texture2D;
91 params.depth = 1;
92 params.size_in_bytes = params.SizeInBytes();
81 return params; 93 return params;
82} 94}
83 95
@@ -93,12 +105,10 @@ static VAddr TryGetCpuAddr(Tegra::GPUVAddr gpu_addr) {
93 params.type = GetFormatType(params.pixel_format); 105 params.type = GetFormatType(params.pixel_format);
94 params.width = zeta_width; 106 params.width = zeta_width;
95 params.height = zeta_height; 107 params.height = zeta_height;
96 params.depth = 1;
97 params.unaligned_height = zeta_height; 108 params.unaligned_height = zeta_height;
98 params.size_in_bytes = params.SizeInBytes();
99 params.cache_width = Common::AlignUp(params.width, 8);
100 params.cache_height = Common::AlignUp(params.height, 8);
101 params.target = SurfaceTarget::Texture2D; 109 params.target = SurfaceTarget::Texture2D;
110 params.depth = 1;
111 params.size_in_bytes = params.SizeInBytes();
102 return params; 112 return params;
103} 113}
104 114
@@ -461,30 +471,27 @@ CachedSurface::CachedSurface(const SurfaceParams& params)
461 // Only pre-create the texture for non-compressed textures. 471 // Only pre-create the texture for non-compressed textures.
462 switch (params.target) { 472 switch (params.target) {
463 case SurfaceParams::SurfaceTarget::Texture1D: 473 case SurfaceParams::SurfaceTarget::Texture1D:
464 glTexImage1D(SurfaceTargetToGL(params.target), 0, format_tuple.internal_format, 474 glTexStorage1D(SurfaceTargetToGL(params.target), 1, format_tuple.internal_format,
465 rect.GetWidth(), 0, format_tuple.format, format_tuple.type, nullptr); 475 rect.GetWidth());
466 break; 476 break;
467 case SurfaceParams::SurfaceTarget::Texture2D: 477 case SurfaceParams::SurfaceTarget::Texture2D:
468 glTexImage2D(SurfaceTargetToGL(params.target), 0, format_tuple.internal_format, 478 glTexStorage2D(SurfaceTargetToGL(params.target), 1, format_tuple.internal_format,
469 rect.GetWidth(), rect.GetHeight(), 0, format_tuple.format, 479 rect.GetWidth(), rect.GetHeight());
470 format_tuple.type, nullptr);
471 break; 480 break;
472 case SurfaceParams::SurfaceTarget::Texture3D: 481 case SurfaceParams::SurfaceTarget::Texture3D:
473 case SurfaceParams::SurfaceTarget::Texture2DArray: 482 case SurfaceParams::SurfaceTarget::Texture2DArray:
474 glTexImage3D(SurfaceTargetToGL(params.target), 0, format_tuple.internal_format, 483 glTexStorage3D(SurfaceTargetToGL(params.target), 1, format_tuple.internal_format,
475 rect.GetWidth(), rect.GetHeight(), params.depth, 0, format_tuple.format, 484 rect.GetWidth(), rect.GetHeight(), params.depth);
476 format_tuple.type, nullptr);
477 break; 485 break;
478 default: 486 default:
479 LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}", 487 LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}",
480 static_cast<u32>(params.target)); 488 static_cast<u32>(params.target));
481 UNREACHABLE(); 489 UNREACHABLE();
482 glTexImage2D(GL_TEXTURE_2D, 0, format_tuple.internal_format, rect.GetWidth(), 490 glTexStorage2D(GL_TEXTURE_2D, 1, format_tuple.internal_format, rect.GetWidth(),
483 rect.GetHeight(), 0, format_tuple.format, format_tuple.type, nullptr); 491 rect.GetHeight());
484 } 492 }
485 } 493 }
486 494
487 glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MAX_LEVEL, 0);
488 glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MIN_FILTER, GL_LINEAR); 495 glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MIN_FILTER, GL_LINEAR);
489 glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 496 glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
490 glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 497 glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
@@ -505,7 +512,7 @@ static void ConvertS8Z24ToZ24S8(std::vector<u8>& data, u32 width, u32 height) {
505 512
506 S8Z24 input_pixel{}; 513 S8Z24 input_pixel{};
507 Z24S8 output_pixel{}; 514 Z24S8 output_pixel{};
508 const auto bpp{CachedSurface::GetGLBytesPerPixel(PixelFormat::S8Z24)}; 515 constexpr auto bpp{CachedSurface::GetGLBytesPerPixel(PixelFormat::S8Z24)};
509 for (size_t y = 0; y < height; ++y) { 516 for (size_t y = 0; y < height; ++y) {
510 for (size_t x = 0; x < width; ++x) { 517 for (size_t x = 0; x < width; ++x) {
511 const size_t offset{bpp * (y * width + x)}; 518 const size_t offset{bpp * (y * width + x)};
@@ -518,7 +525,7 @@ static void ConvertS8Z24ToZ24S8(std::vector<u8>& data, u32 width, u32 height) {
518} 525}
519 526
520static void ConvertG8R8ToR8G8(std::vector<u8>& data, u32 width, u32 height) { 527static void ConvertG8R8ToR8G8(std::vector<u8>& data, u32 width, u32 height) {
521 const auto bpp{CachedSurface::GetGLBytesPerPixel(PixelFormat::G8R8U)}; 528 constexpr auto bpp{CachedSurface::GetGLBytesPerPixel(PixelFormat::G8R8U)};
522 for (size_t y = 0; y < height; ++y) { 529 for (size_t y = 0; y < height; ++y) {
523 for (size_t x = 0; x < width; ++x) { 530 for (size_t x = 0; x < width; ++x) {
524 const size_t offset{bpp * (y * width + x)}; 531 const size_t offset{bpp * (y * width + x)};
@@ -584,12 +591,13 @@ void CachedSurface::LoadGLBuffer() {
584 UNREACHABLE(); 591 UNREACHABLE();
585 } 592 }
586 593
587 gl_buffer.resize(params.depth * copy_size); 594 gl_buffer.resize(static_cast<size_t>(params.depth) * copy_size);
588 morton_to_gl_fns[static_cast<size_t>(params.pixel_format)]( 595 morton_to_gl_fns[static_cast<size_t>(params.pixel_format)](
589 params.width, params.block_height, params.height, gl_buffer.data(), copy_size, 596 params.width, params.block_height, params.height, gl_buffer.data(), copy_size,
590 params.addr); 597 params.addr);
591 } else { 598 } else {
592 const u8* const texture_src_data_end{texture_src_data + (params.depth * copy_size)}; 599 const u8* const texture_src_data_end{texture_src_data +
600 (static_cast<size_t>(params.depth) * copy_size)};
593 gl_buffer.assign(texture_src_data, texture_src_data_end); 601 gl_buffer.assign(texture_src_data, texture_src_data_end);
594 } 602 }
595 603
@@ -608,18 +616,20 @@ void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle
608 616
609 MICROPROFILE_SCOPE(OpenGL_TextureUL); 617 MICROPROFILE_SCOPE(OpenGL_TextureUL);
610 618
611 ASSERT(gl_buffer.size() == 619 ASSERT(gl_buffer.size() == static_cast<size_t>(params.width) * params.height *
612 params.width * params.height * GetGLBytesPerPixel(params.pixel_format) * params.depth); 620 GetGLBytesPerPixel(params.pixel_format) * params.depth);
613 621
614 const auto& rect{params.GetRect()}; 622 const auto& rect{params.GetRect()};
615 623
616 // Load data from memory to the surface 624 // Load data from memory to the surface
617 GLint x0 = static_cast<GLint>(rect.left); 625 const GLint x0 = static_cast<GLint>(rect.left);
618 GLint y0 = static_cast<GLint>(rect.bottom); 626 const GLint y0 = static_cast<GLint>(rect.bottom);
619 size_t buffer_offset = (y0 * params.width + x0) * GetGLBytesPerPixel(params.pixel_format); 627 const size_t buffer_offset =
628 static_cast<size_t>(static_cast<size_t>(y0) * params.width + static_cast<size_t>(x0)) *
629 GetGLBytesPerPixel(params.pixel_format);
620 630
621 const FormatTuple& tuple = GetFormatTuple(params.pixel_format, params.component_type); 631 const FormatTuple& tuple = GetFormatTuple(params.pixel_format, params.component_type);
622 GLuint target_tex = texture.handle; 632 const GLuint target_tex = texture.handle;
623 OpenGLState cur_state = OpenGLState::GetCurState(); 633 OpenGLState cur_state = OpenGLState::GetCurState();
624 634
625 const auto& old_tex = cur_state.texture_units[0]; 635 const auto& old_tex = cur_state.texture_units[0];
@@ -705,62 +715,34 @@ Surface RasterizerCacheOpenGL::GetTextureSurface(const Tegra::Texture::FullTextu
705 return GetSurface(SurfaceParams::CreateForTexture(config)); 715 return GetSurface(SurfaceParams::CreateForTexture(config));
706} 716}
707 717
708SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces(bool using_color_fb, 718Surface RasterizerCacheOpenGL::GetDepthBufferSurface(bool preserve_contents) {
709 bool using_depth_fb, 719 const auto& regs{Core::System::GetInstance().GPU().Maxwell3D().regs};
710 bool preserve_contents) { 720 if (!regs.zeta.Address() || !regs.zeta_enable) {
711 const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; 721 return {};
722 }
712 723
713 // TODO(bunnei): This is hard corded to use just the first render buffer 724 SurfaceParams depth_params{SurfaceParams::CreateForDepthBuffer(
714 LOG_TRACE(Render_OpenGL, "hard-coded for render target 0!"); 725 regs.zeta_width, regs.zeta_height, regs.zeta.Address(), regs.zeta.format)};
715 726
716 // get color and depth surfaces 727 return GetSurface(depth_params, preserve_contents);
717 SurfaceParams color_params{}; 728}
718 SurfaceParams depth_params{};
719 729
720 if (using_color_fb) { 730Surface RasterizerCacheOpenGL::GetColorBufferSurface(size_t index, bool preserve_contents) {
721 color_params = SurfaceParams::CreateForFramebuffer(regs.rt[0]); 731 const auto& regs{Core::System::GetInstance().GPU().Maxwell3D().regs};
722 }
723 732
724 if (using_depth_fb) { 733 ASSERT(index < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets);
725 depth_params = SurfaceParams::CreateForDepthBuffer(regs.zeta_width, regs.zeta_height,
726 regs.zeta.Address(), regs.zeta.format);
727 }
728 734
729 MathUtil::Rectangle<u32> color_rect{}; 735 if (index >= regs.rt_control.count) {
730 Surface color_surface; 736 return {};
731 if (using_color_fb) {
732 color_surface = GetSurface(color_params, preserve_contents);
733 if (color_surface) {
734 color_rect = color_surface->GetSurfaceParams().GetRect();
735 }
736 } 737 }
737 738
738 MathUtil::Rectangle<u32> depth_rect{}; 739 if (regs.rt[index].Address() == 0 || regs.rt[index].format == Tegra::RenderTargetFormat::NONE) {
739 Surface depth_surface; 740 return {};
740 if (using_depth_fb) {
741 depth_surface = GetSurface(depth_params, preserve_contents);
742 if (depth_surface) {
743 depth_rect = depth_surface->GetSurfaceParams().GetRect();
744 }
745 } 741 }
746 742
747 MathUtil::Rectangle<u32> fb_rect{}; 743 const SurfaceParams color_params{SurfaceParams::CreateForFramebuffer(index)};
748 if (color_surface && depth_surface) {
749 fb_rect = color_rect;
750 // Color and Depth surfaces must have the same dimensions and offsets
751 if (color_rect.bottom != depth_rect.bottom || color_rect.top != depth_rect.top ||
752 color_rect.left != depth_rect.left || color_rect.right != depth_rect.right) {
753 color_surface = GetSurface(color_params);
754 depth_surface = GetSurface(depth_params);
755 fb_rect = color_surface->GetSurfaceParams().GetRect();
756 }
757 } else if (color_surface) {
758 fb_rect = color_rect;
759 } else if (depth_surface) {
760 fb_rect = depth_rect;
761 }
762 744
763 return std::make_tuple(color_surface, depth_surface, fb_rect); 745 return GetSurface(color_params, preserve_contents);
764} 746}
765 747
766void RasterizerCacheOpenGL::LoadSurface(const Surface& surface) { 748void RasterizerCacheOpenGL::LoadSurface(const Surface& surface) {
@@ -826,16 +808,20 @@ Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& surface,
826 // Get a new surface with the new parameters, and blit the previous surface to it 808 // Get a new surface with the new parameters, and blit the previous surface to it
827 Surface new_surface{GetUncachedSurface(new_params)}; 809 Surface new_surface{GetUncachedSurface(new_params)};
828 810
829 // If format is unchanged, we can do a faster blit without reinterpreting pixel data 811 if (params.pixel_format == new_params.pixel_format ||
830 if (params.pixel_format == new_params.pixel_format) { 812 !Settings::values.use_accurate_framebuffers) {
813 // If the format is the same, just do a framebuffer blit. This is significantly faster than
814 // using PBOs. The is also likely less accurate, as textures will be converted rather than
815 // reinterpreted.
816
831 BlitTextures(surface->Texture().handle, params.GetRect(), new_surface->Texture().handle, 817 BlitTextures(surface->Texture().handle, params.GetRect(), new_surface->Texture().handle,
832 params.GetRect(), params.type, read_framebuffer.handle, 818 params.GetRect(), params.type, read_framebuffer.handle,
833 draw_framebuffer.handle); 819 draw_framebuffer.handle);
834 return new_surface; 820 } else {
835 } 821 // When use_accurate_framebuffers setting is enabled, perform a more accurate surface copy,
822 // where pixels are reinterpreted as a new format (without conversion). This code path uses
823 // OpenGL PBOs and is quite slow.
836 824
837 // When using accurate framebuffers, always copy old data to new surface, regardless of format
838 if (Settings::values.use_accurate_framebuffers) {
839 auto source_format = GetFormatTuple(params.pixel_format, params.component_type); 825 auto source_format = GetFormatTuple(params.pixel_format, params.component_type);
840 auto dest_format = GetFormatTuple(new_params.pixel_format, new_params.component_type); 826 auto dest_format = GetFormatTuple(new_params.pixel_format, new_params.component_type);
841 827
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index 8312b2c7a..57ea8593b 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -297,6 +297,7 @@ struct SurfaceParams {
297 return PixelFormat::ABGR8S; 297 return PixelFormat::ABGR8S;
298 case Tegra::RenderTargetFormat::RGBA8_UINT: 298 case Tegra::RenderTargetFormat::RGBA8_UINT:
299 return PixelFormat::ABGR8UI; 299 return PixelFormat::ABGR8UI;
300 case Tegra::RenderTargetFormat::BGRA8_SRGB:
300 case Tegra::RenderTargetFormat::BGRA8_UNORM: 301 case Tegra::RenderTargetFormat::BGRA8_UNORM:
301 return PixelFormat::BGRA8; 302 return PixelFormat::BGRA8;
302 case Tegra::RenderTargetFormat::RGB10_A2_UNORM: 303 case Tegra::RenderTargetFormat::RGB10_A2_UNORM:
@@ -569,6 +570,7 @@ struct SurfaceParams {
569 case Tegra::RenderTargetFormat::RGBA8_UNORM: 570 case Tegra::RenderTargetFormat::RGBA8_UNORM:
570 case Tegra::RenderTargetFormat::RGBA8_SRGB: 571 case Tegra::RenderTargetFormat::RGBA8_SRGB:
571 case Tegra::RenderTargetFormat::BGRA8_UNORM: 572 case Tegra::RenderTargetFormat::BGRA8_UNORM:
573 case Tegra::RenderTargetFormat::BGRA8_SRGB:
572 case Tegra::RenderTargetFormat::RGB10_A2_UNORM: 574 case Tegra::RenderTargetFormat::RGB10_A2_UNORM:
573 case Tegra::RenderTargetFormat::R8_UNORM: 575 case Tegra::RenderTargetFormat::R8_UNORM:
574 case Tegra::RenderTargetFormat::RG16_UNORM: 576 case Tegra::RenderTargetFormat::RG16_UNORM:
@@ -669,8 +671,7 @@ struct SurfaceParams {
669 static SurfaceParams CreateForTexture(const Tegra::Texture::FullTextureInfo& config); 671 static SurfaceParams CreateForTexture(const Tegra::Texture::FullTextureInfo& config);
670 672
671 /// Creates SurfaceParams from a framebuffer configuration 673 /// Creates SurfaceParams from a framebuffer configuration
672 static SurfaceParams CreateForFramebuffer( 674 static SurfaceParams CreateForFramebuffer(size_t index);
673 const Tegra::Engines::Maxwell3D::Regs::RenderTargetConfig& config);
674 675
675 /// Creates SurfaceParams for a depth buffer configuration 676 /// Creates SurfaceParams for a depth buffer configuration
676 static SurfaceParams CreateForDepthBuffer(u32 zeta_width, u32 zeta_height, 677 static SurfaceParams CreateForDepthBuffer(u32 zeta_width, u32 zeta_height,
@@ -679,8 +680,8 @@ struct SurfaceParams {
679 680
680 /// Checks if surfaces are compatible for caching 681 /// Checks if surfaces are compatible for caching
681 bool IsCompatibleSurface(const SurfaceParams& other) const { 682 bool IsCompatibleSurface(const SurfaceParams& other) const {
682 return std::tie(pixel_format, type, cache_width, cache_height) == 683 return std::tie(pixel_format, type, width, height) ==
683 std::tie(other.pixel_format, other.type, other.cache_width, other.cache_height); 684 std::tie(other.pixel_format, other.type, other.width, other.height);
684 } 685 }
685 686
686 VAddr addr; 687 VAddr addr;
@@ -695,10 +696,6 @@ struct SurfaceParams {
695 u32 unaligned_height; 696 u32 unaligned_height;
696 size_t size_in_bytes; 697 size_t size_in_bytes;
697 SurfaceTarget target; 698 SurfaceTarget target;
698
699 // Parameters used for caching only
700 u32 cache_width;
701 u32 cache_height;
702}; 699};
703 700
704}; // namespace OpenGL 701}; // namespace OpenGL
@@ -774,9 +771,11 @@ public:
774 /// Get a surface based on the texture configuration 771 /// Get a surface based on the texture configuration
775 Surface GetTextureSurface(const Tegra::Texture::FullTextureInfo& config); 772 Surface GetTextureSurface(const Tegra::Texture::FullTextureInfo& config);
776 773
777 /// Get the color and depth surfaces based on the framebuffer configuration 774 /// Get the depth surface based on the framebuffer configuration
778 SurfaceSurfaceRect_Tuple GetFramebufferSurfaces(bool using_color_fb, bool using_depth_fb, 775 Surface GetDepthBufferSurface(bool preserve_contents);
779 bool preserve_contents); 776
777 /// Get the color surface based on the framebuffer configuration and the specified render target
778 Surface GetColorBufferSurface(size_t index, bool preserve_contents);
780 779
781 /// Flushes the surface to Switch memory 780 /// Flushes the surface to Switch memory
782 void FlushSurface(const Surface& surface); 781 void FlushSurface(const Surface& surface);
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index 7e4b85ac3..61080f5cc 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -13,8 +13,8 @@ namespace OpenGL {
13 13
14/// Gets the address for the specified shader stage program 14/// Gets the address for the specified shader stage program
15static VAddr GetShaderAddress(Maxwell::ShaderProgram program) { 15static VAddr GetShaderAddress(Maxwell::ShaderProgram program) {
16 auto& gpu = Core::System::GetInstance().GPU().Maxwell3D(); 16 const auto& gpu = Core::System::GetInstance().GPU().Maxwell3D();
17 auto& shader_config = gpu.regs.shader_config[static_cast<size_t>(program)]; 17 const auto& shader_config = gpu.regs.shader_config[static_cast<size_t>(program)];
18 return *gpu.memory_manager.GpuToCpuAddress(gpu.regs.code_address.CodeAddress() + 18 return *gpu.memory_manager.GpuToCpuAddress(gpu.regs.code_address.CodeAddress() +
19 shader_config.offset); 19 shader_config.offset);
20} 20}
@@ -86,7 +86,7 @@ CachedShader::CachedShader(VAddr addr, Maxwell::ShaderProgram program_type)
86} 86}
87 87
88GLuint CachedShader::GetProgramResourceIndex(const GLShader::ConstBufferEntry& buffer) { 88GLuint CachedShader::GetProgramResourceIndex(const GLShader::ConstBufferEntry& buffer) {
89 auto search{resource_cache.find(buffer.GetHash())}; 89 const auto search{resource_cache.find(buffer.GetHash())};
90 if (search == resource_cache.end()) { 90 if (search == resource_cache.end()) {
91 const GLuint index{ 91 const GLuint index{
92 glGetProgramResourceIndex(program.handle, GL_UNIFORM_BLOCK, buffer.GetName().c_str())}; 92 glGetProgramResourceIndex(program.handle, GL_UNIFORM_BLOCK, buffer.GetName().c_str())};
@@ -98,7 +98,7 @@ GLuint CachedShader::GetProgramResourceIndex(const GLShader::ConstBufferEntry& b
98} 98}
99 99
100GLint CachedShader::GetUniformLocation(const GLShader::SamplerEntry& sampler) { 100GLint CachedShader::GetUniformLocation(const GLShader::SamplerEntry& sampler) {
101 auto search{uniform_cache.find(sampler.GetHash())}; 101 const auto search{uniform_cache.find(sampler.GetHash())};
102 if (search == uniform_cache.end()) { 102 if (search == uniform_cache.end()) {
103 const GLint index{glGetUniformLocation(program.handle, sampler.GetName().c_str())}; 103 const GLint index{glGetUniformLocation(program.handle, sampler.GetName().c_str())};
104 uniform_cache[sampler.GetHash()] = index; 104 uniform_cache[sampler.GetHash()] = index;
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 172ba8335..582c811e0 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -113,7 +113,7 @@ private:
113 113
114 /// Scans a range of code for labels and determines the exit method. 114 /// Scans a range of code for labels and determines the exit method.
115 ExitMethod Scan(u32 begin, u32 end, std::set<u32>& labels) { 115 ExitMethod Scan(u32 begin, u32 end, std::set<u32>& labels) {
116 auto [iter, inserted] = 116 const auto [iter, inserted] =
117 exit_method_map.emplace(std::make_pair(begin, end), ExitMethod::Undetermined); 117 exit_method_map.emplace(std::make_pair(begin, end), ExitMethod::Undetermined);
118 ExitMethod& exit_method = iter->second; 118 ExitMethod& exit_method = iter->second;
119 if (!inserted) 119 if (!inserted)
@@ -131,22 +131,22 @@ private:
131 if (instr.pred.pred_index == static_cast<u64>(Pred::UnusedIndex)) { 131 if (instr.pred.pred_index == static_cast<u64>(Pred::UnusedIndex)) {
132 return exit_method = ExitMethod::AlwaysEnd; 132 return exit_method = ExitMethod::AlwaysEnd;
133 } else { 133 } else {
134 ExitMethod not_met = Scan(offset + 1, end, labels); 134 const ExitMethod not_met = Scan(offset + 1, end, labels);
135 return exit_method = ParallelExit(ExitMethod::AlwaysEnd, not_met); 135 return exit_method = ParallelExit(ExitMethod::AlwaysEnd, not_met);
136 } 136 }
137 } 137 }
138 case OpCode::Id::BRA: { 138 case OpCode::Id::BRA: {
139 u32 target = offset + instr.bra.GetBranchTarget(); 139 const u32 target = offset + instr.bra.GetBranchTarget();
140 labels.insert(target); 140 labels.insert(target);
141 ExitMethod no_jmp = Scan(offset + 1, end, labels); 141 const ExitMethod no_jmp = Scan(offset + 1, end, labels);
142 ExitMethod jmp = Scan(target, end, labels); 142 const ExitMethod jmp = Scan(target, end, labels);
143 return exit_method = ParallelExit(no_jmp, jmp); 143 return exit_method = ParallelExit(no_jmp, jmp);
144 } 144 }
145 case OpCode::Id::SSY: { 145 case OpCode::Id::SSY: {
146 // The SSY instruction uses a similar encoding as the BRA instruction. 146 // The SSY instruction uses a similar encoding as the BRA instruction.
147 ASSERT_MSG(instr.bra.constant_buffer == 0, 147 ASSERT_MSG(instr.bra.constant_buffer == 0,
148 "Constant buffer SSY is not supported"); 148 "Constant buffer SSY is not supported");
149 u32 target = offset + instr.bra.GetBranchTarget(); 149 const u32 target = offset + instr.bra.GetBranchTarget();
150 labels.insert(target); 150 labels.insert(target);
151 // Continue scanning for an exit method. 151 // Continue scanning for an exit method.
152 break; 152 break;
@@ -346,8 +346,8 @@ public:
346 */ 346 */
347 void SetRegisterToInputAttibute(const Register& reg, u64 elem, Attribute::Index attribute, 347 void SetRegisterToInputAttibute(const Register& reg, u64 elem, Attribute::Index attribute,
348 const Tegra::Shader::IpaMode& input_mode) { 348 const Tegra::Shader::IpaMode& input_mode) {
349 std::string dest = GetRegisterAsFloat(reg); 349 const std::string dest = GetRegisterAsFloat(reg);
350 std::string src = GetInputAttribute(attribute, input_mode) + GetSwizzle(elem); 350 const std::string src = GetInputAttribute(attribute, input_mode) + GetSwizzle(elem);
351 shader.AddLine(dest + " = " + src + ';'); 351 shader.AddLine(dest + " = " + src + ';');
352 } 352 }
353 353
@@ -359,8 +359,8 @@ public:
359 * @param reg The register to use as the source value. 359 * @param reg The register to use as the source value.
360 */ 360 */
361 void SetOutputAttributeToRegister(Attribute::Index attribute, u64 elem, const Register& reg) { 361 void SetOutputAttributeToRegister(Attribute::Index attribute, u64 elem, const Register& reg) {
362 std::string dest = GetOutputAttribute(attribute); 362 const std::string dest = GetOutputAttribute(attribute);
363 std::string src = GetRegisterAsFloat(reg); 363 const std::string src = GetRegisterAsFloat(reg);
364 364
365 if (!dest.empty()) { 365 if (!dest.empty()) {
366 // Can happen with unknown/unimplemented output attributes, in which case we ignore the 366 // Can happen with unknown/unimplemented output attributes, in which case we ignore the
@@ -393,9 +393,9 @@ public:
393 GLSLRegister::Type type) { 393 GLSLRegister::Type type) {
394 declr_const_buffers[cbuf_index].MarkAsUsedIndirect(cbuf_index, stage); 394 declr_const_buffers[cbuf_index].MarkAsUsedIndirect(cbuf_index, stage);
395 395
396 std::string final_offset = fmt::format("({} + {})", index_str, offset / 4); 396 const std::string final_offset = fmt::format("({} + {})", index_str, offset / 4);
397 std::string value = 'c' + std::to_string(cbuf_index) + '[' + final_offset + " / 4][" + 397 const std::string value = 'c' + std::to_string(cbuf_index) + '[' + final_offset + " / 4][" +
398 final_offset + " % 4]"; 398 final_offset + " % 4]";
399 399
400 if (type == GLSLRegister::Type::Float) { 400 if (type == GLSLRegister::Type::Float) {
401 return value; 401 return value;
@@ -468,10 +468,10 @@ public:
468 /// necessary. 468 /// necessary.
469 std::string AccessSampler(const Sampler& sampler, Tegra::Shader::TextureType type, 469 std::string AccessSampler(const Sampler& sampler, Tegra::Shader::TextureType type,
470 bool is_array) { 470 bool is_array) {
471 size_t offset = static_cast<size_t>(sampler.index.Value()); 471 const size_t offset = static_cast<size_t>(sampler.index.Value());
472 472
473 // If this sampler has already been used, return the existing mapping. 473 // If this sampler has already been used, return the existing mapping.
474 auto itr = 474 const auto itr =
475 std::find_if(used_samplers.begin(), used_samplers.end(), 475 std::find_if(used_samplers.begin(), used_samplers.end(),
476 [&](const SamplerEntry& entry) { return entry.GetOffset() == offset; }); 476 [&](const SamplerEntry& entry) { return entry.GetOffset() == offset; });
477 477
@@ -481,8 +481,8 @@ public:
481 } 481 }
482 482
483 // Otherwise create a new mapping for this sampler 483 // Otherwise create a new mapping for this sampler
484 size_t next_index = used_samplers.size(); 484 const size_t next_index = used_samplers.size();
485 SamplerEntry entry{stage, offset, next_index, type, is_array}; 485 const SamplerEntry entry{stage, offset, next_index, type, is_array};
486 used_samplers.emplace_back(entry); 486 used_samplers.emplace_back(entry);
487 return entry.GetName(); 487 return entry.GetName();
488 } 488 }
@@ -699,7 +699,7 @@ private:
699 }; 699 };
700 700
701 bool IsColorComponentOutputEnabled(u32 render_target, u32 component) const { 701 bool IsColorComponentOutputEnabled(u32 render_target, u32 component) const {
702 u32 bit = render_target * 4 + component; 702 const u32 bit = render_target * 4 + component;
703 return enabled_color_outputs & (1 << bit); 703 return enabled_color_outputs & (1 << bit);
704 } 704 }
705 }; 705 };
@@ -707,7 +707,7 @@ private:
707 707
708 /// Gets the Subroutine object corresponding to the specified address. 708 /// Gets the Subroutine object corresponding to the specified address.
709 const Subroutine& GetSubroutine(u32 begin, u32 end) const { 709 const Subroutine& GetSubroutine(u32 begin, u32 end) const {
710 auto iter = subroutines.find(Subroutine{begin, end, suffix}); 710 const auto iter = subroutines.find(Subroutine{begin, end, suffix});
711 ASSERT(iter != subroutines.end()); 711 ASSERT(iter != subroutines.end());
712 return *iter; 712 return *iter;
713 } 713 }
@@ -752,7 +752,7 @@ private:
752 // Can't assign to the constant predicate. 752 // Can't assign to the constant predicate.
753 ASSERT(pred != static_cast<u64>(Pred::UnusedIndex)); 753 ASSERT(pred != static_cast<u64>(Pred::UnusedIndex));
754 754
755 std::string variable = 'p' + std::to_string(pred) + '_' + suffix; 755 const std::string variable = 'p' + std::to_string(pred) + '_' + suffix;
756 shader.AddLine(variable + " = " + value + ';'); 756 shader.AddLine(variable + " = " + value + ';');
757 declr_predicates.insert(std::move(variable)); 757 declr_predicates.insert(std::move(variable));
758 } 758 }
@@ -1023,7 +1023,7 @@ private:
1023 // TODO(Subv): Figure out how dual-source blending is configured in the Switch. 1023 // TODO(Subv): Figure out how dual-source blending is configured in the Switch.
1024 for (u32 component = 0; component < 4; ++component) { 1024 for (u32 component = 0; component < 4; ++component) {
1025 if (header.IsColorComponentOutputEnabled(render_target, component)) { 1025 if (header.IsColorComponentOutputEnabled(render_target, component)) {
1026 shader.AddLine(fmt::format("color[{}][{}] = {};", render_target, component, 1026 shader.AddLine(fmt::format("FragColor{}[{}] = {};", render_target, component,
1027 regs.GetRegisterAsFloat(current_reg))); 1027 regs.GetRegisterAsFloat(current_reg)));
1028 ++current_reg; 1028 ++current_reg;
1029 } 1029 }
@@ -1033,7 +1033,11 @@ private:
1033 if (header.writes_depth) { 1033 if (header.writes_depth) {
1034 // The depth output is always 2 registers after the last color output, and current_reg 1034 // The depth output is always 2 registers after the last color output, and current_reg
1035 // already contains one past the last color register. 1035 // already contains one past the last color register.
1036 shader.AddLine("gl_FragDepth = " + regs.GetRegisterAsFloat(current_reg + 1) + ';'); 1036
1037 shader.AddLine(
1038 "gl_FragDepth = " +
1039 regs.GetRegisterAsFloat(static_cast<Tegra::Shader::Register>(current_reg) + 1) +
1040 ';');
1037 } 1041 }
1038 } 1042 }
1039 1043
@@ -1435,7 +1439,7 @@ private:
1435 if (instr.alu_integer.negate_b) 1439 if (instr.alu_integer.negate_b)
1436 op_b = "-(" + op_b + ')'; 1440 op_b = "-(" + op_b + ')';
1437 1441
1438 std::string shift = std::to_string(instr.alu_integer.shift_amount.Value()); 1442 const std::string shift = std::to_string(instr.alu_integer.shift_amount.Value());
1439 1443
1440 regs.SetRegisterToInteger(instr.gpr0, true, 0, 1444 regs.SetRegisterToInteger(instr.gpr0, true, 0,
1441 "((" + op_a + " << " + shift + ") + " + op_b + ')', 1, 1); 1445 "((" + op_a + " << " + shift + ") + " + op_b + ')', 1, 1);
@@ -1453,7 +1457,7 @@ private:
1453 case OpCode::Id::SEL_C: 1457 case OpCode::Id::SEL_C:
1454 case OpCode::Id::SEL_R: 1458 case OpCode::Id::SEL_R:
1455 case OpCode::Id::SEL_IMM: { 1459 case OpCode::Id::SEL_IMM: {
1456 std::string condition = 1460 const std::string condition =
1457 GetPredicateCondition(instr.sel.pred, instr.sel.neg_pred != 0); 1461 GetPredicateCondition(instr.sel.pred, instr.sel.neg_pred != 0);
1458 regs.SetRegisterToInteger(instr.gpr0, true, 0, 1462 regs.SetRegisterToInteger(instr.gpr0, true, 0,
1459 '(' + condition + ") ? " + op_a + " : " + op_b, 1, 1); 1463 '(' + condition + ") ? " + op_a + " : " + op_b, 1, 1);
@@ -1475,8 +1479,9 @@ private:
1475 case OpCode::Id::LOP3_C: 1479 case OpCode::Id::LOP3_C:
1476 case OpCode::Id::LOP3_R: 1480 case OpCode::Id::LOP3_R:
1477 case OpCode::Id::LOP3_IMM: { 1481 case OpCode::Id::LOP3_IMM: {
1478 std::string op_c = regs.GetRegisterAsInteger(instr.gpr39); 1482 const std::string op_c = regs.GetRegisterAsInteger(instr.gpr39);
1479 std::string lut; 1483 std::string lut;
1484
1480 if (opcode->GetId() == OpCode::Id::LOP3_R) { 1485 if (opcode->GetId() == OpCode::Id::LOP3_R) {
1481 lut = '(' + std::to_string(instr.alu.lop3.GetImmLut28()) + ')'; 1486 lut = '(' + std::to_string(instr.alu.lop3.GetImmLut28()) + ')';
1482 } else { 1487 } else {
@@ -1491,15 +1496,82 @@ private:
1491 case OpCode::Id::IMNMX_IMM: { 1496 case OpCode::Id::IMNMX_IMM: {
1492 ASSERT_MSG(instr.imnmx.exchange == Tegra::Shader::IMinMaxExchange::None, 1497 ASSERT_MSG(instr.imnmx.exchange == Tegra::Shader::IMinMaxExchange::None,
1493 "Unimplemented"); 1498 "Unimplemented");
1494 std::string condition = 1499 const std::string condition =
1495 GetPredicateCondition(instr.imnmx.pred, instr.imnmx.negate_pred != 0); 1500 GetPredicateCondition(instr.imnmx.pred, instr.imnmx.negate_pred != 0);
1496 std::string parameters = op_a + ',' + op_b; 1501 const std::string parameters = op_a + ',' + op_b;
1497 regs.SetRegisterToInteger(instr.gpr0, instr.imnmx.is_signed, 0, 1502 regs.SetRegisterToInteger(instr.gpr0, instr.imnmx.is_signed, 0,
1498 '(' + condition + ") ? min(" + parameters + ") : max(" + 1503 '(' + condition + ") ? min(" + parameters + ") : max(" +
1499 parameters + ')', 1504 parameters + ')',
1500 1, 1); 1505 1, 1);
1501 break; 1506 break;
1502 } 1507 }
1508 case OpCode::Id::LEA_R2:
1509 case OpCode::Id::LEA_R1:
1510 case OpCode::Id::LEA_IMM:
1511 case OpCode::Id::LEA_RZ:
1512 case OpCode::Id::LEA_HI: {
1513 std::string op_a;
1514 std::string op_b;
1515 std::string op_c;
1516
1517 switch (opcode->GetId()) {
1518 case OpCode::Id::LEA_R2: {
1519 op_a = regs.GetRegisterAsInteger(instr.gpr20);
1520 op_b = regs.GetRegisterAsInteger(instr.gpr39);
1521 op_c = std::to_string(instr.lea.r2.entry_a);
1522 break;
1523 }
1524
1525 case OpCode::Id::LEA_R1: {
1526 const bool neg = instr.lea.r1.neg != 0;
1527 op_a = regs.GetRegisterAsInteger(instr.gpr8);
1528 if (neg)
1529 op_a = "-(" + op_a + ')';
1530 op_b = regs.GetRegisterAsInteger(instr.gpr20);
1531 op_c = std::to_string(instr.lea.r1.entry_a);
1532 break;
1533 }
1534
1535 case OpCode::Id::LEA_IMM: {
1536 const bool neg = instr.lea.imm.neg != 0;
1537 op_b = regs.GetRegisterAsInteger(instr.gpr8);
1538 if (neg)
1539 op_b = "-(" + op_b + ')';
1540 op_a = std::to_string(instr.lea.imm.entry_a);
1541 op_c = std::to_string(instr.lea.imm.entry_b);
1542 break;
1543 }
1544
1545 case OpCode::Id::LEA_RZ: {
1546 const bool neg = instr.lea.rz.neg != 0;
1547 op_b = regs.GetRegisterAsInteger(instr.gpr8);
1548 if (neg)
1549 op_b = "-(" + op_b + ')';
1550 op_a = regs.GetUniform(instr.lea.rz.cb_index, instr.lea.rz.cb_offset,
1551 GLSLRegister::Type::Integer);
1552 op_c = std::to_string(instr.lea.rz.entry_a);
1553
1554 break;
1555 }
1556
1557 case OpCode::Id::LEA_HI:
1558 default: {
1559 op_b = regs.GetRegisterAsInteger(instr.gpr8);
1560 op_a = std::to_string(instr.lea.imm.entry_a);
1561 op_c = std::to_string(instr.lea.imm.entry_b);
1562 LOG_CRITICAL(HW_GPU, "Unhandled LEA subinstruction: {}", opcode->GetName());
1563 UNREACHABLE();
1564 }
1565 }
1566 if (instr.lea.pred48 != static_cast<u64>(Pred::UnusedIndex)) {
1567 LOG_ERROR(HW_GPU, "Unhandled LEA Predicate");
1568 UNREACHABLE();
1569 }
1570 const std::string value = '(' + op_a + " + (" + op_b + "*(1 << " + op_c + ")))";
1571 regs.SetRegisterToInteger(instr.gpr0, true, 0, value, 1, 1);
1572
1573 break;
1574 }
1503 default: { 1575 default: {
1504 LOG_CRITICAL(HW_GPU, "Unhandled ArithmeticInteger instruction: {}", 1576 LOG_CRITICAL(HW_GPU, "Unhandled ArithmeticInteger instruction: {}",
1505 opcode->GetName()); 1577 opcode->GetName());
@@ -1510,7 +1582,7 @@ private:
1510 break; 1582 break;
1511 } 1583 }
1512 case OpCode::Type::Ffma: { 1584 case OpCode::Type::Ffma: {
1513 std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); 1585 const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8);
1514 std::string op_b = instr.ffma.negate_b ? "-" : ""; 1586 std::string op_b = instr.ffma.negate_b ? "-" : "";
1515 std::string op_c = instr.ffma.negate_c ? "-" : ""; 1587 std::string op_c = instr.ffma.negate_c ? "-" : "";
1516 1588
@@ -1720,7 +1792,7 @@ private:
1720 shader.AddLine("uint index = (" + regs.GetRegisterAsInteger(instr.gpr8, 0, false) + 1792 shader.AddLine("uint index = (" + regs.GetRegisterAsInteger(instr.gpr8, 0, false) +
1721 " / 4) & (MAX_CONSTBUFFER_ELEMENTS - 1);"); 1793 " / 4) & (MAX_CONSTBUFFER_ELEMENTS - 1);");
1722 1794
1723 std::string op_a = 1795 const std::string op_a =
1724 regs.GetUniformIndirect(instr.cbuf36.index, instr.cbuf36.offset + 0, "index", 1796 regs.GetUniformIndirect(instr.cbuf36.index, instr.cbuf36.offset + 0, "index",
1725 GLSLRegister::Type::Float); 1797 GLSLRegister::Type::Float);
1726 1798
@@ -1730,7 +1802,7 @@ private:
1730 break; 1802 break;
1731 1803
1732 case Tegra::Shader::UniformType::Double: { 1804 case Tegra::Shader::UniformType::Double: {
1733 std::string op_b = 1805 const std::string op_b =
1734 regs.GetUniformIndirect(instr.cbuf36.index, instr.cbuf36.offset + 4, 1806 regs.GetUniformIndirect(instr.cbuf36.index, instr.cbuf36.offset + 4,
1735 "index", GLSLRegister::Type::Float); 1807 "index", GLSLRegister::Type::Float);
1736 regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1); 1808 regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1);
@@ -1760,13 +1832,13 @@ private:
1760 1832
1761 switch (texture_type) { 1833 switch (texture_type) {
1762 case Tegra::Shader::TextureType::Texture1D: { 1834 case Tegra::Shader::TextureType::Texture1D: {
1763 std::string x = regs.GetRegisterAsFloat(instr.gpr8); 1835 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
1764 coord = "float coords = " + x + ';'; 1836 coord = "float coords = " + x + ';';
1765 break; 1837 break;
1766 } 1838 }
1767 case Tegra::Shader::TextureType::Texture2D: { 1839 case Tegra::Shader::TextureType::Texture2D: {
1768 std::string x = regs.GetRegisterAsFloat(instr.gpr8); 1840 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
1769 std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); 1841 const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
1770 coord = "vec2 coords = vec2(" + x + ", " + y + ");"; 1842 coord = "vec2 coords = vec2(" + x + ", " + y + ");";
1771 break; 1843 break;
1772 } 1844 }
@@ -1776,8 +1848,8 @@ private:
1776 UNREACHABLE(); 1848 UNREACHABLE();
1777 1849
1778 // Fallback to interpreting as a 2D texture for now 1850 // Fallback to interpreting as a 2D texture for now
1779 std::string x = regs.GetRegisterAsFloat(instr.gpr8); 1851 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
1780 std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); 1852 const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
1781 coord = "vec2 coords = vec2(" + x + ", " + y + ");"; 1853 coord = "vec2 coords = vec2(" + x + ", " + y + ");";
1782 texture_type = Tegra::Shader::TextureType::Texture2D; 1854 texture_type = Tegra::Shader::TextureType::Texture2D;
1783 } 1855 }
@@ -1811,13 +1883,13 @@ private:
1811 switch (texture_type) { 1883 switch (texture_type) {
1812 case Tegra::Shader::TextureType::Texture2D: { 1884 case Tegra::Shader::TextureType::Texture2D: {
1813 if (is_array) { 1885 if (is_array) {
1814 std::string index = regs.GetRegisterAsInteger(instr.gpr8); 1886 const std::string index = regs.GetRegisterAsInteger(instr.gpr8);
1815 std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); 1887 const std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
1816 std::string y = regs.GetRegisterAsFloat(instr.gpr20); 1888 const std::string y = regs.GetRegisterAsFloat(instr.gpr20);
1817 coord = "vec3 coords = vec3(" + x + ", " + y + ", " + index + ");"; 1889 coord = "vec3 coords = vec3(" + x + ", " + y + ", " + index + ");";
1818 } else { 1890 } else {
1819 std::string x = regs.GetRegisterAsFloat(instr.gpr8); 1891 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
1820 std::string y = regs.GetRegisterAsFloat(instr.gpr20); 1892 const std::string y = regs.GetRegisterAsFloat(instr.gpr20);
1821 coord = "vec2 coords = vec2(" + x + ", " + y + ");"; 1893 coord = "vec2 coords = vec2(" + x + ", " + y + ");";
1822 } 1894 }
1823 break; 1895 break;
@@ -1828,8 +1900,8 @@ private:
1828 UNREACHABLE(); 1900 UNREACHABLE();
1829 1901
1830 // Fallback to interpreting as a 2D texture for now 1902 // Fallback to interpreting as a 2D texture for now
1831 std::string x = regs.GetRegisterAsFloat(instr.gpr8); 1903 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
1832 std::string y = regs.GetRegisterAsFloat(instr.gpr20); 1904 const std::string y = regs.GetRegisterAsFloat(instr.gpr20);
1833 coord = "vec2 coords = vec2(" + x + ", " + y + ");"; 1905 coord = "vec2 coords = vec2(" + x + ", " + y + ");";
1834 texture_type = Tegra::Shader::TextureType::Texture2D; 1906 texture_type = Tegra::Shader::TextureType::Texture2D;
1835 is_array = false; 1907 is_array = false;
@@ -1850,8 +1922,8 @@ private:
1850 LOG_CRITICAL(HW_GPU, "Unhandled 2d array texture"); 1922 LOG_CRITICAL(HW_GPU, "Unhandled 2d array texture");
1851 UNREACHABLE(); 1923 UNREACHABLE();
1852 } else { 1924 } else {
1853 std::string x = regs.GetRegisterAsInteger(instr.gpr8); 1925 const std::string x = regs.GetRegisterAsInteger(instr.gpr8);
1854 std::string y = regs.GetRegisterAsInteger(instr.gpr20); 1926 const std::string y = regs.GetRegisterAsInteger(instr.gpr20);
1855 coord = "ivec2 coords = ivec2(" + x + ", " + y + ");"; 1927 coord = "ivec2 coords = ivec2(" + x + ", " + y + ");";
1856 } 1928 }
1857 break; 1929 break;
@@ -1874,8 +1946,8 @@ private:
1874 1946
1875 switch (instr.tld4.texture_type) { 1947 switch (instr.tld4.texture_type) {
1876 case Tegra::Shader::TextureType::Texture2D: { 1948 case Tegra::Shader::TextureType::Texture2D: {
1877 std::string x = regs.GetRegisterAsFloat(instr.gpr8); 1949 const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
1878 std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); 1950 const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
1879 coord = "vec2 coords = vec2(" + x + ", " + y + ");"; 1951 coord = "vec2 coords = vec2(" + x + ", " + y + ");";
1880 break; 1952 break;
1881 } 1953 }
@@ -1920,6 +1992,74 @@ private:
1920 WriteTexsInstruction(instr, coord, texture); 1992 WriteTexsInstruction(instr, coord, texture);
1921 break; 1993 break;
1922 } 1994 }
1995 case OpCode::Id::TXQ: {
1996 // TODO: the new commits on the texture refactor, change the way samplers work.
1997 // Sadly, not all texture instructions specify the type of texture their sampler
1998 // uses. This must be fixed at a later instance.
1999 const std::string sampler =
2000 GetSampler(instr.sampler, Tegra::Shader::TextureType::Texture2D, false);
2001 switch (instr.txq.query_type) {
2002 case Tegra::Shader::TextureQueryType::Dimension: {
2003 const std::string texture = "textureQueryLevels(" + sampler + ')';
2004 regs.SetRegisterToInteger(instr.gpr0, true, 0, texture, 1, 1);
2005 break;
2006 }
2007 default: {
2008 LOG_CRITICAL(HW_GPU, "Unhandled texture query type: {}",
2009 static_cast<u32>(instr.txq.query_type.Value()));
2010 UNREACHABLE();
2011 }
2012 }
2013 break;
2014 }
2015 case OpCode::Id::TMML: {
2016 const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8);
2017 const std::string op_b = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
2018 const bool is_array = instr.tmml.array != 0;
2019 auto texture_type = instr.tmml.texture_type.Value();
2020 const std::string sampler = GetSampler(instr.sampler, texture_type, is_array);
2021
2022 // TODO: add coordinates for different samplers once other texture types are
2023 // implemented.
2024 std::string coord;
2025 switch (texture_type) {
2026 case Tegra::Shader::TextureType::Texture1D: {
2027 std::string x = regs.GetRegisterAsFloat(instr.gpr8);
2028 coord = "float coords = " + x + ';';
2029 break;
2030 }
2031 case Tegra::Shader::TextureType::Texture2D: {
2032 std::string x = regs.GetRegisterAsFloat(instr.gpr8);
2033 std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
2034 coord = "vec2 coords = vec2(" + x + ", " + y + ");";
2035 break;
2036 }
2037 default:
2038 LOG_CRITICAL(HW_GPU, "Unhandled texture type {}",
2039 static_cast<u32>(texture_type));
2040 UNREACHABLE();
2041
2042 // Fallback to interpreting as a 2D texture for now
2043 std::string x = regs.GetRegisterAsFloat(instr.gpr8);
2044 std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
2045 coord = "vec2 coords = vec2(" + x + ", " + y + ");";
2046 texture_type = Tegra::Shader::TextureType::Texture2D;
2047 }
2048 // Add an extra scope and declare the texture coords inside to prevent
2049 // overwriting them in case they are used as outputs of the texs instruction.
2050 shader.AddLine('{');
2051 ++shader.scope;
2052 shader.AddLine(coord);
2053 const std::string texture = "textureQueryLod(" + sampler + ", coords)";
2054 const std::string tmp = "vec2 tmp = " + texture + "*vec2(256.0, 256.0);";
2055 shader.AddLine(tmp);
2056
2057 regs.SetRegisterToInteger(instr.gpr0, true, 0, "int(tmp.y)", 1, 1);
2058 regs.SetRegisterToInteger(instr.gpr0.Value() + 1, false, 0, "uint(tmp.x)", 1, 1);
2059 --shader.scope;
2060 shader.AddLine('}');
2061 break;
2062 }
1923 default: { 2063 default: {
1924 LOG_CRITICAL(HW_GPU, "Unhandled memory instruction: {}", opcode->GetName()); 2064 LOG_CRITICAL(HW_GPU, "Unhandled memory instruction: {}", opcode->GetName());
1925 UNREACHABLE(); 2065 UNREACHABLE();
@@ -1959,12 +2099,12 @@ private:
1959 // We can't use the constant predicate as destination. 2099 // We can't use the constant predicate as destination.
1960 ASSERT(instr.fsetp.pred3 != static_cast<u64>(Pred::UnusedIndex)); 2100 ASSERT(instr.fsetp.pred3 != static_cast<u64>(Pred::UnusedIndex));
1961 2101
1962 std::string second_pred = 2102 const std::string second_pred =
1963 GetPredicateCondition(instr.fsetp.pred39, instr.fsetp.neg_pred != 0); 2103 GetPredicateCondition(instr.fsetp.pred39, instr.fsetp.neg_pred != 0);
1964 2104
1965 std::string combiner = GetPredicateCombiner(instr.fsetp.op); 2105 const std::string combiner = GetPredicateCombiner(instr.fsetp.op);
1966 2106
1967 std::string predicate = GetPredicateComparison(instr.fsetp.cond, op_a, op_b); 2107 const std::string predicate = GetPredicateComparison(instr.fsetp.cond, op_a, op_b);
1968 // Set the primary predicate to the result of Predicate OP SecondPredicate 2108 // Set the primary predicate to the result of Predicate OP SecondPredicate
1969 SetPredicate(instr.fsetp.pred3, 2109 SetPredicate(instr.fsetp.pred3,
1970 '(' + predicate + ") " + combiner + " (" + second_pred + ')'); 2110 '(' + predicate + ") " + combiner + " (" + second_pred + ')');
@@ -1978,7 +2118,8 @@ private:
1978 break; 2118 break;
1979 } 2119 }
1980 case OpCode::Type::IntegerSetPredicate: { 2120 case OpCode::Type::IntegerSetPredicate: {
1981 std::string op_a = regs.GetRegisterAsInteger(instr.gpr8, 0, instr.isetp.is_signed); 2121 const std::string op_a =
2122 regs.GetRegisterAsInteger(instr.gpr8, 0, instr.isetp.is_signed);
1982 std::string op_b; 2123 std::string op_b;
1983 2124
1984 if (instr.is_b_imm) { 2125 if (instr.is_b_imm) {
@@ -1995,12 +2136,12 @@ private:
1995 // We can't use the constant predicate as destination. 2136 // We can't use the constant predicate as destination.
1996 ASSERT(instr.isetp.pred3 != static_cast<u64>(Pred::UnusedIndex)); 2137 ASSERT(instr.isetp.pred3 != static_cast<u64>(Pred::UnusedIndex));
1997 2138
1998 std::string second_pred = 2139 const std::string second_pred =
1999 GetPredicateCondition(instr.isetp.pred39, instr.isetp.neg_pred != 0); 2140 GetPredicateCondition(instr.isetp.pred39, instr.isetp.neg_pred != 0);
2000 2141
2001 std::string combiner = GetPredicateCombiner(instr.isetp.op); 2142 const std::string combiner = GetPredicateCombiner(instr.isetp.op);
2002 2143
2003 std::string predicate = GetPredicateComparison(instr.isetp.cond, op_a, op_b); 2144 const std::string predicate = GetPredicateComparison(instr.isetp.cond, op_a, op_b);
2004 // Set the primary predicate to the result of Predicate OP SecondPredicate 2145 // Set the primary predicate to the result of Predicate OP SecondPredicate
2005 SetPredicate(instr.isetp.pred3, 2146 SetPredicate(instr.isetp.pred3,
2006 '(' + predicate + ") " + combiner + " (" + second_pred + ')'); 2147 '(' + predicate + ") " + combiner + " (" + second_pred + ')');
@@ -2013,21 +2154,45 @@ private:
2013 } 2154 }
2014 break; 2155 break;
2015 } 2156 }
2157 case OpCode::Type::PredicateSetRegister: {
2158 const std::string op_a =
2159 GetPredicateCondition(instr.pset.pred12, instr.pset.neg_pred12 != 0);
2160 const std::string op_b =
2161 GetPredicateCondition(instr.pset.pred29, instr.pset.neg_pred29 != 0);
2162
2163 const std::string second_pred =
2164 GetPredicateCondition(instr.pset.pred39, instr.pset.neg_pred39 != 0);
2165
2166 const std::string combiner = GetPredicateCombiner(instr.pset.op);
2167
2168 const std::string predicate =
2169 '(' + op_a + ") " + GetPredicateCombiner(instr.pset.cond) + " (" + op_b + ')';
2170 const std::string result = '(' + predicate + ") " + combiner + " (" + second_pred + ')';
2171 if (instr.pset.bf == 0) {
2172 const std::string value = '(' + result + ") ? 0xFFFFFFFF : 0";
2173 regs.SetRegisterToInteger(instr.gpr0, false, 0, value, 1, 1);
2174 } else {
2175 const std::string value = '(' + result + ") ? 1.0 : 0.0";
2176 regs.SetRegisterToFloat(instr.gpr0, 0, value, 1, 1);
2177 }
2178
2179 break;
2180 }
2016 case OpCode::Type::PredicateSetPredicate: { 2181 case OpCode::Type::PredicateSetPredicate: {
2017 std::string op_a = 2182 const std::string op_a =
2018 GetPredicateCondition(instr.psetp.pred12, instr.psetp.neg_pred12 != 0); 2183 GetPredicateCondition(instr.psetp.pred12, instr.psetp.neg_pred12 != 0);
2019 std::string op_b = 2184 const std::string op_b =
2020 GetPredicateCondition(instr.psetp.pred29, instr.psetp.neg_pred29 != 0); 2185 GetPredicateCondition(instr.psetp.pred29, instr.psetp.neg_pred29 != 0);
2021 2186
2022 // We can't use the constant predicate as destination. 2187 // We can't use the constant predicate as destination.
2023 ASSERT(instr.psetp.pred3 != static_cast<u64>(Pred::UnusedIndex)); 2188 ASSERT(instr.psetp.pred3 != static_cast<u64>(Pred::UnusedIndex));
2024 2189
2025 std::string second_pred = 2190 const std::string second_pred =
2026 GetPredicateCondition(instr.psetp.pred39, instr.psetp.neg_pred39 != 0); 2191 GetPredicateCondition(instr.psetp.pred39, instr.psetp.neg_pred39 != 0);
2027 2192
2028 std::string combiner = GetPredicateCombiner(instr.psetp.op); 2193 const std::string combiner = GetPredicateCombiner(instr.psetp.op);
2029 2194
2030 std::string predicate = 2195 const std::string predicate =
2031 '(' + op_a + ") " + GetPredicateCombiner(instr.psetp.cond) + " (" + op_b + ')'; 2196 '(' + op_a + ") " + GetPredicateCombiner(instr.psetp.cond) + " (" + op_b + ')';
2032 2197
2033 // Set the primary predicate to the result of Predicate OP SecondPredicate 2198 // Set the primary predicate to the result of Predicate OP SecondPredicate
@@ -2053,7 +2218,7 @@ private:
2053 std::string op_b = instr.fset.neg_b ? "-" : ""; 2218 std::string op_b = instr.fset.neg_b ? "-" : "";
2054 2219
2055 if (instr.is_b_imm) { 2220 if (instr.is_b_imm) {
2056 std::string imm = GetImmediate19(instr); 2221 const std::string imm = GetImmediate19(instr);
2057 if (instr.fset.neg_imm) 2222 if (instr.fset.neg_imm)
2058 op_b += "(-" + imm + ')'; 2223 op_b += "(-" + imm + ')';
2059 else 2224 else
@@ -2073,13 +2238,14 @@ private:
2073 2238
2074 // The fset instruction sets a register to 1.0 or -1 (depending on the bf bit) if the 2239 // The fset instruction sets a register to 1.0 or -1 (depending on the bf bit) if the
2075 // condition is true, and to 0 otherwise. 2240 // condition is true, and to 0 otherwise.
2076 std::string second_pred = 2241 const std::string second_pred =
2077 GetPredicateCondition(instr.fset.pred39, instr.fset.neg_pred != 0); 2242 GetPredicateCondition(instr.fset.pred39, instr.fset.neg_pred != 0);
2078 2243
2079 std::string combiner = GetPredicateCombiner(instr.fset.op); 2244 const std::string combiner = GetPredicateCombiner(instr.fset.op);
2080 2245
2081 std::string predicate = "((" + GetPredicateComparison(instr.fset.cond, op_a, op_b) + 2246 const std::string predicate = "((" +
2082 ") " + combiner + " (" + second_pred + "))"; 2247 GetPredicateComparison(instr.fset.cond, op_a, op_b) +
2248 ") " + combiner + " (" + second_pred + "))";
2083 2249
2084 if (instr.fset.bf) { 2250 if (instr.fset.bf) {
2085 regs.SetRegisterToFloat(instr.gpr0, 0, predicate + " ? 1.0 : 0.0", 1, 1); 2251 regs.SetRegisterToFloat(instr.gpr0, 0, predicate + " ? 1.0 : 0.0", 1, 1);
@@ -2090,7 +2256,7 @@ private:
2090 break; 2256 break;
2091 } 2257 }
2092 case OpCode::Type::IntegerSet: { 2258 case OpCode::Type::IntegerSet: {
2093 std::string op_a = regs.GetRegisterAsInteger(instr.gpr8, 0, instr.iset.is_signed); 2259 const std::string op_a = regs.GetRegisterAsInteger(instr.gpr8, 0, instr.iset.is_signed);
2094 2260
2095 std::string op_b; 2261 std::string op_b;
2096 2262
@@ -2107,13 +2273,14 @@ private:
2107 2273
2108 // The iset instruction sets a register to 1.0 or -1 (depending on the bf bit) if the 2274 // The iset instruction sets a register to 1.0 or -1 (depending on the bf bit) if the
2109 // condition is true, and to 0 otherwise. 2275 // condition is true, and to 0 otherwise.
2110 std::string second_pred = 2276 const std::string second_pred =
2111 GetPredicateCondition(instr.iset.pred39, instr.iset.neg_pred != 0); 2277 GetPredicateCondition(instr.iset.pred39, instr.iset.neg_pred != 0);
2112 2278
2113 std::string combiner = GetPredicateCombiner(instr.iset.op); 2279 const std::string combiner = GetPredicateCombiner(instr.iset.op);
2114 2280
2115 std::string predicate = "((" + GetPredicateComparison(instr.iset.cond, op_a, op_b) + 2281 const std::string predicate = "((" +
2116 ") " + combiner + " (" + second_pred + "))"; 2282 GetPredicateComparison(instr.iset.cond, op_a, op_b) +
2283 ") " + combiner + " (" + second_pred + "))";
2117 2284
2118 if (instr.iset.bf) { 2285 if (instr.iset.bf) {
2119 regs.SetRegisterToFloat(instr.gpr0, 0, predicate + " ? 1.0 : 0.0", 1, 1); 2286 regs.SetRegisterToFloat(instr.gpr0, 0, predicate + " ? 1.0 : 0.0", 1, 1);
@@ -2263,7 +2430,7 @@ private:
2263 case OpCode::Id::BRA: { 2430 case OpCode::Id::BRA: {
2264 ASSERT_MSG(instr.bra.constant_buffer == 0, 2431 ASSERT_MSG(instr.bra.constant_buffer == 0,
2265 "BRA with constant buffers are not implemented"); 2432 "BRA with constant buffers are not implemented");
2266 u32 target = offset + instr.bra.GetBranchTarget(); 2433 const u32 target = offset + instr.bra.GetBranchTarget();
2267 shader.AddLine("{ jmp_to = " + std::to_string(target) + "u; break; }"); 2434 shader.AddLine("{ jmp_to = " + std::to_string(target) + "u; break; }");
2268 break; 2435 break;
2269 } 2436 }
@@ -2287,7 +2454,7 @@ private:
2287 // has a similar structure to the BRA opcode. 2454 // has a similar structure to the BRA opcode.
2288 ASSERT_MSG(instr.bra.constant_buffer == 0, "Constant buffer SSY is not supported"); 2455 ASSERT_MSG(instr.bra.constant_buffer == 0, "Constant buffer SSY is not supported");
2289 2456
2290 u32 target = offset + instr.bra.GetBranchTarget(); 2457 const u32 target = offset + instr.bra.GetBranchTarget();
2291 EmitPushToSSYStack(target); 2458 EmitPushToSSYStack(target);
2292 break; 2459 break;
2293 } 2460 }
@@ -2381,10 +2548,10 @@ private:
2381 shader.AddLine("case " + std::to_string(label) + "u: {"); 2548 shader.AddLine("case " + std::to_string(label) + "u: {");
2382 ++shader.scope; 2549 ++shader.scope;
2383 2550
2384 auto next_it = labels.lower_bound(label + 1); 2551 const auto next_it = labels.lower_bound(label + 1);
2385 u32 next_label = next_it == labels.end() ? subroutine.end : *next_it; 2552 const u32 next_label = next_it == labels.end() ? subroutine.end : *next_it;
2386 2553
2387 u32 compile_end = CompileRange(label, next_label); 2554 const u32 compile_end = CompileRange(label, next_label);
2388 if (compile_end > next_label && compile_end != PROGRAM_END) { 2555 if (compile_end > next_label && compile_end != PROGRAM_END) {
2389 // This happens only when there is a label inside a IF/LOOP block 2556 // This happens only when there is a label inside a IF/LOOP block
2390 shader.AddLine(" jmp_to = " + std::to_string(compile_end) + "u; break; }"); 2557 shader.AddLine(" jmp_to = " + std::to_string(compile_end) + "u; break; }");
@@ -2447,7 +2614,8 @@ boost::optional<ProgramResult> DecompileProgram(const ProgramCode& program_code,
2447 Maxwell3D::Regs::ShaderStage stage, 2614 Maxwell3D::Regs::ShaderStage stage,
2448 const std::string& suffix) { 2615 const std::string& suffix) {
2449 try { 2616 try {
2450 auto subroutines = ControlFlowAnalyzer(program_code, main_offset, suffix).GetSubroutines(); 2617 const auto subroutines =
2618 ControlFlowAnalyzer(program_code, main_offset, suffix).GetSubroutines();
2451 GLSLGenerator generator(subroutines, program_code, main_offset, stage, suffix); 2619 GLSLGenerator generator(subroutines, program_code, main_offset, stage, suffix);
2452 return ProgramResult{generator.GetShaderCode(), generator.GetEntries()}; 2620 return ProgramResult{generator.GetShaderCode(), generator.GetEntries()};
2453 } catch (const DecompileFail& exception) { 2621 } catch (const DecompileFail& exception) {
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp
index e1b1a9d73..b0466c18f 100644
--- a/src/video_core/renderer_opengl/gl_shader_gen.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp
@@ -88,7 +88,14 @@ ProgramResult GenerateFragmentShader(const ShaderSetup& setup) {
88 .get_value_or({}); 88 .get_value_or({});
89 out += R"( 89 out += R"(
90in vec4 position; 90in vec4 position;
91layout(location = 0) out vec4 color[8]; 91layout(location = 0) out vec4 FragColor0;
92layout(location = 1) out vec4 FragColor1;
93layout(location = 2) out vec4 FragColor2;
94layout(location = 3) out vec4 FragColor3;
95layout(location = 4) out vec4 FragColor4;
96layout(location = 5) out vec4 FragColor5;
97layout(location = 6) out vec4 FragColor6;
98layout(location = 7) out vec4 FragColor7;
92 99
93layout (std140) uniform fs_config { 100layout (std140) uniform fs_config {
94 vec4 viewport_flip; 101 vec4 viewport_flip;
diff --git a/src/video_core/renderer_opengl/gl_shader_util.cpp b/src/video_core/renderer_opengl/gl_shader_util.cpp
index 5781d9d16..5f3fe067e 100644
--- a/src/video_core/renderer_opengl/gl_shader_util.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_util.cpp
@@ -25,7 +25,7 @@ GLuint LoadShader(const char* source, GLenum type) {
25 default: 25 default:
26 UNREACHABLE(); 26 UNREACHABLE();
27 } 27 }
28 GLuint shader_id = glCreateShader(type); 28 const GLuint shader_id = glCreateShader(type);
29 glShaderSource(shader_id, 1, &source, nullptr); 29 glShaderSource(shader_id, 1, &source, nullptr);
30 LOG_DEBUG(Render_OpenGL, "Compiling {} shader...", debug_type); 30 LOG_DEBUG(Render_OpenGL, "Compiling {} shader...", debug_type);
31 glCompileShader(shader_id); 31 glCompileShader(shader_id);
diff --git a/src/video_core/renderer_opengl/gl_stream_buffer.cpp b/src/video_core/renderer_opengl/gl_stream_buffer.cpp
index e565afcee..aadf68f16 100644
--- a/src/video_core/renderer_opengl/gl_stream_buffer.cpp
+++ b/src/video_core/renderer_opengl/gl_stream_buffer.cpp
@@ -29,7 +29,7 @@ OGLStreamBuffer::OGLStreamBuffer(GLenum target, GLsizeiptr size, bool prefer_coh
29 if (GLAD_GL_ARB_buffer_storage) { 29 if (GLAD_GL_ARB_buffer_storage) {
30 persistent = true; 30 persistent = true;
31 coherent = prefer_coherent; 31 coherent = prefer_coherent;
32 GLbitfield flags = 32 const GLbitfield flags =
33 GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | (coherent ? GL_MAP_COHERENT_BIT : 0); 33 GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | (coherent ? GL_MAP_COHERENT_BIT : 0);
34 glBufferStorage(gl_target, allocate_size, nullptr, flags); 34 glBufferStorage(gl_target, allocate_size, nullptr, flags);
35 mapped_ptr = static_cast<u8*>(glMapBufferRange( 35 mapped_ptr = static_cast<u8*>(glMapBufferRange(
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index a2b6e984e..f48b69809 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -9,6 +9,8 @@ add_executable(yuzu
9 about_dialog.h 9 about_dialog.h
10 bootmanager.cpp 10 bootmanager.cpp
11 bootmanager.h 11 bootmanager.h
12 compatibility_list.cpp
13 compatibility_list.h
12 configuration/config.cpp 14 configuration/config.cpp
13 configuration/config.h 15 configuration/config.h
14 configuration/configure_audio.cpp 16 configuration/configure_audio.cpp
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 4a60f450a..4e4c108ab 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -112,6 +112,7 @@ GRenderWindow::GRenderWindow(QWidget* parent, EmuThread* emu_thread)
112 setWindowTitle(QString::fromStdString(window_title)); 112 setWindowTitle(QString::fromStdString(window_title));
113 113
114 InputCommon::Init(); 114 InputCommon::Init();
115 InputCommon::StartJoystickEventHandler();
115} 116}
116 117
117GRenderWindow::~GRenderWindow() { 118GRenderWindow::~GRenderWindow() {
diff --git a/src/yuzu/compatibility_list.cpp b/src/yuzu/compatibility_list.cpp
new file mode 100644
index 000000000..2d2cfd03c
--- /dev/null
+++ b/src/yuzu/compatibility_list.cpp
@@ -0,0 +1,18 @@
1// Copyright 2018 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <algorithm>
6
7#include <fmt/format.h>
8
9#include "yuzu/compatibility_list.h"
10
11CompatibilityList::const_iterator FindMatchingCompatibilityEntry(
12 const CompatibilityList& compatibility_list, u64 program_id) {
13 return std::find_if(compatibility_list.begin(), compatibility_list.end(),
14 [program_id](const auto& element) {
15 std::string pid = fmt::format("{:016X}", program_id);
16 return element.first == pid;
17 });
18}
diff --git a/src/yuzu/compatibility_list.h b/src/yuzu/compatibility_list.h
new file mode 100644
index 000000000..bc0175bd3
--- /dev/null
+++ b/src/yuzu/compatibility_list.h
@@ -0,0 +1,17 @@
1// Copyright 2018 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <string>
8#include <unordered_map>
9
10#include <QString>
11
12#include "common/common_types.h"
13
14using CompatibilityList = std::unordered_map<std::string, std::pair<QString, QString>>;
15
16CompatibilityList::const_iterator FindMatchingCompatibilityEntry(
17 const CompatibilityList& compatibility_list, u64 program_id);
diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp
index d8caee1e8..9292d9a42 100644
--- a/src/yuzu/configuration/configure_general.cpp
+++ b/src/yuzu/configuration/configure_general.cpp
@@ -20,7 +20,6 @@ ConfigureGeneral::ConfigureGeneral(QWidget* parent)
20 this->setConfiguration(); 20 this->setConfiguration();
21 21
22 ui->use_cpu_jit->setEnabled(!Core::System::GetInstance().IsPoweredOn()); 22 ui->use_cpu_jit->setEnabled(!Core::System::GetInstance().IsPoweredOn());
23 ui->use_multi_core->setEnabled(!Core::System::GetInstance().IsPoweredOn());
24 ui->use_docked_mode->setEnabled(!Core::System::GetInstance().IsPoweredOn()); 23 ui->use_docked_mode->setEnabled(!Core::System::GetInstance().IsPoweredOn());
25} 24}
26 25
@@ -31,7 +30,6 @@ void ConfigureGeneral::setConfiguration() {
31 ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing); 30 ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing);
32 ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme)); 31 ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme));
33 ui->use_cpu_jit->setChecked(Settings::values.use_cpu_jit); 32 ui->use_cpu_jit->setChecked(Settings::values.use_cpu_jit);
34 ui->use_multi_core->setChecked(Settings::values.use_multi_core);
35 ui->use_docked_mode->setChecked(Settings::values.use_docked_mode); 33 ui->use_docked_mode->setChecked(Settings::values.use_docked_mode);
36} 34}
37 35
@@ -46,6 +44,5 @@ void ConfigureGeneral::applyConfiguration() {
46 ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString(); 44 ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString();
47 45
48 Settings::values.use_cpu_jit = ui->use_cpu_jit->isChecked(); 46 Settings::values.use_cpu_jit = ui->use_cpu_jit->isChecked();
49 Settings::values.use_multi_core = ui->use_multi_core->isChecked();
50 Settings::values.use_docked_mode = ui->use_docked_mode->isChecked(); 47 Settings::values.use_docked_mode = ui->use_docked_mode->isChecked();
51} 48}
diff --git a/src/yuzu/configuration/configure_general.ui b/src/yuzu/configuration/configure_general.ui
index 233adbe27..1775c4d40 100644
--- a/src/yuzu/configuration/configure_general.ui
+++ b/src/yuzu/configuration/configure_general.ui
@@ -58,13 +58,6 @@
58 </property> 58 </property>
59 </widget> 59 </widget>
60 </item> 60 </item>
61 <item>
62 <widget class="QCheckBox" name="use_multi_core">
63 <property name="text">
64 <string>Enable multi-core</string>
65 </property>
66 </widget>
67 </item>
68 </layout> 61 </layout>
69 </item> 62 </item>
70 </layout> 63 </layout>
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp
index 5e7badedf..d29abb74b 100644
--- a/src/yuzu/configuration/configure_input.cpp
+++ b/src/yuzu/configuration/configure_input.cpp
@@ -1,4 +1,4 @@
1// Copyright 2016 Citra Emulator Project 1// Copyright 2016 Citra Emulator Project
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
@@ -53,19 +53,18 @@ static QString ButtonToText(const Common::ParamPackage& param) {
53 } else if (param.Get("engine", "") == "keyboard") { 53 } else if (param.Get("engine", "") == "keyboard") {
54 return getKeyName(param.Get("code", 0)); 54 return getKeyName(param.Get("code", 0));
55 } else if (param.Get("engine", "") == "sdl") { 55 } else if (param.Get("engine", "") == "sdl") {
56 QString text = QString(QObject::tr("Joystick %1")).arg(param.Get("joystick", "").c_str());
57 if (param.Has("hat")) { 56 if (param.Has("hat")) {
58 text += QString(QObject::tr(" Hat %1 %2")) 57 return QString(QObject::tr("Hat %1 %2"))
59 .arg(param.Get("hat", "").c_str(), param.Get("direction", "").c_str()); 58 .arg(param.Get("hat", "").c_str(), param.Get("direction", "").c_str());
60 } 59 }
61 if (param.Has("axis")) { 60 if (param.Has("axis")) {
62 text += QString(QObject::tr(" Axis %1%2")) 61 return QString(QObject::tr("Axis %1%2"))
63 .arg(param.Get("axis", "").c_str(), param.Get("direction", "").c_str()); 62 .arg(param.Get("axis", "").c_str(), param.Get("direction", "").c_str());
64 } 63 }
65 if (param.Has("button")) { 64 if (param.Has("button")) {
66 text += QString(QObject::tr(" Button %1")).arg(param.Get("button", "").c_str()); 65 return QString(QObject::tr("Button %1")).arg(param.Get("button", "").c_str());
67 } 66 }
68 return text; 67 return QString();
69 } else { 68 } else {
70 return QObject::tr("[unknown]"); 69 return QObject::tr("[unknown]");
71 } 70 }
@@ -81,13 +80,12 @@ static QString AnalogToText(const Common::ParamPackage& param, const std::string
81 return QString(QObject::tr("[unused]")); 80 return QString(QObject::tr("[unused]"));
82 } 81 }
83 82
84 QString text = QString(QObject::tr("Joystick %1")).arg(param.Get("joystick", "").c_str());
85 if (dir == "left" || dir == "right") { 83 if (dir == "left" || dir == "right") {
86 text += QString(QObject::tr(" Axis %1")).arg(param.Get("axis_x", "").c_str()); 84 return QString(QObject::tr("Axis %1")).arg(param.Get("axis_x", "").c_str());
87 } else if (dir == "up" || dir == "down") { 85 } else if (dir == "up" || dir == "down") {
88 text += QString(QObject::tr(" Axis %1")).arg(param.Get("axis_y", "").c_str()); 86 return QString(QObject::tr("Axis %1")).arg(param.Get("axis_y", "").c_str());
89 } 87 }
90 return text; 88 return QString();
91 } else { 89 } else {
92 return QObject::tr("[unknown]"); 90 return QObject::tr("[unknown]");
93 } 91 }
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp
index 86532e4a9..8c6e16d47 100644
--- a/src/yuzu/game_list.cpp
+++ b/src/yuzu/game_list.cpp
@@ -19,6 +19,7 @@
19#include "common/file_util.h" 19#include "common/file_util.h"
20#include "common/logging/log.h" 20#include "common/logging/log.h"
21#include "core/file_sys/patch_manager.h" 21#include "core/file_sys/patch_manager.h"
22#include "yuzu/compatibility_list.h"
22#include "yuzu/game_list.h" 23#include "yuzu/game_list.h"
23#include "yuzu/game_list_p.h" 24#include "yuzu/game_list_p.h"
24#include "yuzu/game_list_worker.h" 25#include "yuzu/game_list_worker.h"
diff --git a/src/yuzu/game_list.h b/src/yuzu/game_list.h
index 3fcb298ed..2713e7b54 100644
--- a/src/yuzu/game_list.h
+++ b/src/yuzu/game_list.h
@@ -4,8 +4,6 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <unordered_map>
8
9#include <QFileSystemWatcher> 7#include <QFileSystemWatcher>
10#include <QHBoxLayout> 8#include <QHBoxLayout>
11#include <QLabel> 9#include <QLabel>
@@ -21,6 +19,7 @@
21#include <QWidget> 19#include <QWidget>
22 20
23#include "common/common_types.h" 21#include "common/common_types.h"
22#include "yuzu/compatibility_list.h"
24 23
25class GameListWorker; 24class GameListWorker;
26class GMainWindow; 25class GMainWindow;
@@ -90,9 +89,8 @@ signals:
90 void GameChosen(QString game_path); 89 void GameChosen(QString game_path);
91 void ShouldCancelWorker(); 90 void ShouldCancelWorker();
92 void OpenFolderRequested(u64 program_id, GameListOpenTarget target); 91 void OpenFolderRequested(u64 program_id, GameListOpenTarget target);
93 void NavigateToGamedbEntryRequested( 92 void NavigateToGamedbEntryRequested(u64 program_id,
94 u64 program_id, 93 const CompatibilityList& compatibility_list);
95 std::unordered_map<std::string, std::pair<QString, QString>>& compatibility_list);
96 94
97private slots: 95private slots:
98 void onTextChanged(const QString& newText); 96 void onTextChanged(const QString& newText);
@@ -114,7 +112,7 @@ private:
114 QStandardItemModel* item_model = nullptr; 112 QStandardItemModel* item_model = nullptr;
115 GameListWorker* current_worker = nullptr; 113 GameListWorker* current_worker = nullptr;
116 QFileSystemWatcher* watcher = nullptr; 114 QFileSystemWatcher* watcher = nullptr;
117 std::unordered_map<std::string, std::pair<QString, QString>> compatibility_list; 115 CompatibilityList compatibility_list;
118}; 116};
119 117
120Q_DECLARE_METATYPE(GameListOpenTarget); 118Q_DECLARE_METATYPE(GameListOpenTarget);
diff --git a/src/yuzu/game_list_p.h b/src/yuzu/game_list_p.h
index 2720bf143..f22e422e5 100644
--- a/src/yuzu/game_list_p.h
+++ b/src/yuzu/game_list_p.h
@@ -176,14 +176,3 @@ public:
176 return data(SizeRole).toULongLong() < other.data(SizeRole).toULongLong(); 176 return data(SizeRole).toULongLong() < other.data(SizeRole).toULongLong();
177 } 177 }
178}; 178};
179
180inline auto FindMatchingCompatibilityEntry(
181 const std::unordered_map<std::string, std::pair<QString, QString>>& compatibility_list,
182 u64 program_id) {
183 return std::find_if(
184 compatibility_list.begin(), compatibility_list.end(),
185 [program_id](const std::pair<std::string, std::pair<QString, QString>>& element) {
186 std::string pid = fmt::format("{:016X}", program_id);
187 return element.first == pid;
188 });
189}
diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp
index 9f26935d6..e228d61bd 100644
--- a/src/yuzu/game_list_worker.cpp
+++ b/src/yuzu/game_list_worker.cpp
@@ -20,6 +20,7 @@
20#include "core/file_sys/registered_cache.h" 20#include "core/file_sys/registered_cache.h"
21#include "core/hle/service/filesystem/filesystem.h" 21#include "core/hle/service/filesystem/filesystem.h"
22#include "core/loader/loader.h" 22#include "core/loader/loader.h"
23#include "yuzu/compatibility_list.h"
23#include "yuzu/game_list.h" 24#include "yuzu/game_list.h"
24#include "yuzu/game_list_p.h" 25#include "yuzu/game_list_p.h"
25#include "yuzu/game_list_worker.h" 26#include "yuzu/game_list_worker.h"
@@ -75,9 +76,8 @@ QString FormatPatchNameVersions(const FileSys::PatchManager& patch_manager, bool
75} 76}
76} // Anonymous namespace 77} // Anonymous namespace
77 78
78GameListWorker::GameListWorker( 79GameListWorker::GameListWorker(FileSys::VirtualFilesystem vfs, QString dir_path, bool deep_scan,
79 FileSys::VirtualFilesystem vfs, QString dir_path, bool deep_scan, 80 const CompatibilityList& compatibility_list)
80 const std::unordered_map<std::string, std::pair<QString, QString>>& compatibility_list)
81 : vfs(std::move(vfs)), dir_path(std::move(dir_path)), deep_scan(deep_scan), 81 : vfs(std::move(vfs)), dir_path(std::move(dir_path)), deep_scan(deep_scan),
82 compatibility_list(compatibility_list) {} 82 compatibility_list(compatibility_list) {}
83 83
diff --git a/src/yuzu/game_list_worker.h b/src/yuzu/game_list_worker.h
index 42c93fc31..09d20c42f 100644
--- a/src/yuzu/game_list_worker.h
+++ b/src/yuzu/game_list_worker.h
@@ -16,6 +16,7 @@
16#include <QString> 16#include <QString>
17 17
18#include "common/common_types.h" 18#include "common/common_types.h"
19#include "yuzu/compatibility_list.h"
19 20
20class QStandardItem; 21class QStandardItem;
21 22
@@ -32,9 +33,8 @@ class GameListWorker : public QObject, public QRunnable {
32 Q_OBJECT 33 Q_OBJECT
33 34
34public: 35public:
35 GameListWorker( 36 GameListWorker(std::shared_ptr<FileSys::VfsFilesystem> vfs, QString dir_path, bool deep_scan,
36 std::shared_ptr<FileSys::VfsFilesystem> vfs, QString dir_path, bool deep_scan, 37 const CompatibilityList& compatibility_list);
37 const std::unordered_map<std::string, std::pair<QString, QString>>& compatibility_list);
38 ~GameListWorker() override; 38 ~GameListWorker() override;
39 39
40 /// Starts the processing of directory tree information. 40 /// Starts the processing of directory tree information.
@@ -67,6 +67,6 @@ private:
67 QStringList watch_list; 67 QStringList watch_list;
68 QString dir_path; 68 QString dir_path;
69 bool deep_scan; 69 bool deep_scan;
70 const std::unordered_map<std::string, std::pair<QString, QString>>& compatibility_list; 70 const CompatibilityList& compatibility_list;
71 std::atomic_bool stop_processing; 71 std::atomic_bool stop_processing;
72}; 72};
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 811e7cd3f..05a4a55e8 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -47,6 +47,7 @@
47#include "video_core/debug_utils/debug_utils.h" 47#include "video_core/debug_utils/debug_utils.h"
48#include "yuzu/about_dialog.h" 48#include "yuzu/about_dialog.h"
49#include "yuzu/bootmanager.h" 49#include "yuzu/bootmanager.h"
50#include "yuzu/compatibility_list.h"
50#include "yuzu/configuration/config.h" 51#include "yuzu/configuration/config.h"
51#include "yuzu/configuration/configure_dialog.h" 52#include "yuzu/configuration/configure_dialog.h"
52#include "yuzu/debugger/console.h" 53#include "yuzu/debugger/console.h"
@@ -446,6 +447,8 @@ QStringList GMainWindow::GetUnsupportedGLExtensions() {
446 unsupported_ext.append("ARB_texture_mirror_clamp_to_edge"); 447 unsupported_ext.append("ARB_texture_mirror_clamp_to_edge");
447 if (!GLAD_GL_ARB_base_instance) 448 if (!GLAD_GL_ARB_base_instance)
448 unsupported_ext.append("ARB_base_instance"); 449 unsupported_ext.append("ARB_base_instance");
450 if (!GLAD_GL_ARB_texture_storage)
451 unsupported_ext.append("ARB_texture_storage");
449 452
450 // Extensions required to support some texture formats. 453 // Extensions required to support some texture formats.
451 if (!GLAD_GL_EXT_texture_compression_s3tc) 454 if (!GLAD_GL_EXT_texture_compression_s3tc)
@@ -725,14 +728,11 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target
725 QDesktopServices::openUrl(QUrl::fromLocalFile(qpath)); 728 QDesktopServices::openUrl(QUrl::fromLocalFile(qpath));
726} 729}
727 730
728void GMainWindow::OnGameListNavigateToGamedbEntry( 731void GMainWindow::OnGameListNavigateToGamedbEntry(u64 program_id,
729 u64 program_id, 732 const CompatibilityList& compatibility_list) {
730 std::unordered_map<std::string, std::pair<QString, QString>>& compatibility_list) { 733 const auto it = FindMatchingCompatibilityEntry(compatibility_list, program_id);
731
732 auto it = FindMatchingCompatibilityEntry(compatibility_list, program_id);
733 734
734 QString directory; 735 QString directory;
735
736 if (it != compatibility_list.end()) 736 if (it != compatibility_list.end())
737 directory = it->second.second; 737 directory = it->second.second;
738 738
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 089ea2445..552e3e61c 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -13,6 +13,7 @@
13#include "common/common_types.h" 13#include "common/common_types.h"
14#include "core/core.h" 14#include "core/core.h"
15#include "ui_main.h" 15#include "ui_main.h"
16#include "yuzu/compatibility_list.h"
16#include "yuzu/hotkeys.h" 17#include "yuzu/hotkeys.h"
17 18
18class Config; 19class Config;
@@ -137,9 +138,8 @@ private slots:
137 /// Called whenever a user selects a game in the game list widget. 138 /// Called whenever a user selects a game in the game list widget.
138 void OnGameListLoadFile(QString game_path); 139 void OnGameListLoadFile(QString game_path);
139 void OnGameListOpenFolder(u64 program_id, GameListOpenTarget target); 140 void OnGameListOpenFolder(u64 program_id, GameListOpenTarget target);
140 void OnGameListNavigateToGamedbEntry( 141 void OnGameListNavigateToGamedbEntry(u64 program_id,
141 u64 program_id, 142 const CompatibilityList& compatibility_list);
142 std::unordered_map<std::string, std::pair<QString, QString>>& compatibility_list);
143 void OnMenuLoadFile(); 143 void OnMenuLoadFile();
144 void OnMenuLoadFolder(); 144 void OnMenuLoadFolder();
145 void OnMenuInstallToNAND(); 145 void OnMenuInstallToNAND();
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
index 2f7916256..d213929bd 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
@@ -16,6 +16,7 @@
16#include "input_common/keyboard.h" 16#include "input_common/keyboard.h"
17#include "input_common/main.h" 17#include "input_common/main.h"
18#include "input_common/motion_emu.h" 18#include "input_common/motion_emu.h"
19#include "input_common/sdl/sdl.h"
19#include "yuzu_cmd/emu_window/emu_window_sdl2.h" 20#include "yuzu_cmd/emu_window/emu_window_sdl2.h"
20 21
21void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) { 22void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) {
@@ -93,6 +94,8 @@ bool EmuWindow_SDL2::SupportsRequiredGLExtensions() {
93 unsupported_ext.push_back("ARB_texture_mirror_clamp_to_edge"); 94 unsupported_ext.push_back("ARB_texture_mirror_clamp_to_edge");
94 if (!GLAD_GL_ARB_base_instance) 95 if (!GLAD_GL_ARB_base_instance)
95 unsupported_ext.push_back("ARB_base_instance"); 96 unsupported_ext.push_back("ARB_base_instance");
97 if (!GLAD_GL_ARB_texture_storage)
98 unsupported_ext.push_back("ARB_texture_storage");
96 99
97 // Extensions required to support some texture formats. 100 // Extensions required to support some texture formats.
98 if (!GLAD_GL_EXT_texture_compression_s3tc) 101 if (!GLAD_GL_EXT_texture_compression_s3tc)
@@ -116,7 +119,7 @@ EmuWindow_SDL2::EmuWindow_SDL2(bool fullscreen) {
116 SDL_SetMainReady(); 119 SDL_SetMainReady();
117 120
118 // Initialize the window 121 // Initialize the window
119 if (SDL_Init(SDL_INIT_VIDEO) < 0) { 122 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) {
120 LOG_CRITICAL(Frontend, "Failed to initialize SDL2! Exiting..."); 123 LOG_CRITICAL(Frontend, "Failed to initialize SDL2! Exiting...");
121 exit(1); 124 exit(1);
122 } 125 }
@@ -176,6 +179,7 @@ EmuWindow_SDL2::EmuWindow_SDL2(bool fullscreen) {
176} 179}
177 180
178EmuWindow_SDL2::~EmuWindow_SDL2() { 181EmuWindow_SDL2::~EmuWindow_SDL2() {
182 InputCommon::SDL::CloseSDLJoysticks();
179 SDL_GL_DeleteContext(gl_context); 183 SDL_GL_DeleteContext(gl_context);
180 SDL_Quit(); 184 SDL_Quit();
181 185
@@ -220,6 +224,9 @@ void EmuWindow_SDL2::PollEvents() {
220 case SDL_QUIT: 224 case SDL_QUIT:
221 is_open = false; 225 is_open = false;
222 break; 226 break;
227 default:
228 InputCommon::SDL::HandleGameControllerEvent(event);
229 break;
223 } 230 }
224 } 231 }
225} 232}
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp
index 173ac0e0f..b1c364fbb 100644
--- a/src/yuzu_cmd/yuzu.cpp
+++ b/src/yuzu_cmd/yuzu.cpp
@@ -82,6 +82,9 @@ int main(int argc, char** argv) {
82 int option_index = 0; 82 int option_index = 0;
83 bool use_gdbstub = Settings::values.use_gdbstub; 83 bool use_gdbstub = Settings::values.use_gdbstub;
84 u32 gdb_port = static_cast<u32>(Settings::values.gdbstub_port); 84 u32 gdb_port = static_cast<u32>(Settings::values.gdbstub_port);
85
86 InitializeLogging();
87
85 char* endarg; 88 char* endarg;
86#ifdef _WIN32 89#ifdef _WIN32
87 int argc_w; 90 int argc_w;
@@ -144,8 +147,6 @@ int main(int argc, char** argv) {
144 LocalFree(argv_w); 147 LocalFree(argv_w);
145#endif 148#endif
146 149
147 InitializeLogging();
148
149 MicroProfileOnThreadCreate("EmuThread"); 150 MicroProfileOnThreadCreate("EmuThread");
150 SCOPE_EXIT({ MicroProfileShutdown(); }); 151 SCOPE_EXIT({ MicroProfileShutdown(); });
151 152