summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/CMakeLists.txt1
-rw-r--r--src/common/common_paths.h6
-rw-r--r--src/common/file_util.cpp68
-rw-r--r--src/common/file_util.h27
-rw-r--r--src/common/synchronized_wrapper.h85
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp4
-rw-r--r--src/core/hle/service/ns/pl_u.cpp2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp30
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.h8
-rw-r--r--src/core/hle/service/nvdrv/interface.cpp2
-rw-r--r--src/core/telemetry_session.cpp6
-rw-r--r--src/video_core/engines/fermi_2d.cpp6
-rw-r--r--src/video_core/engines/fermi_2d.h6
-rw-r--r--src/video_core/engines/maxwell_3d.h6
-rw-r--r--src/video_core/engines/maxwell_compute.h6
-rw-r--r--src/video_core/engines/maxwell_dma.h6
-rw-r--r--src/video_core/engines/shader_bytecode.h12
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp6
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.h6
-rw-r--r--src/video_core/textures/decoders.cpp6
-rw-r--r--src/video_core/textures/decoders.h6
-rw-r--r--src/video_core/textures/texture.h6
-rw-r--r--src/yuzu/configuration/config.cpp2
-rw-r--r--src/yuzu/configuration/configure_debug.cpp2
-rw-r--r--src/yuzu/main.cpp18
-rw-r--r--src/yuzu_cmd/config.cpp2
-rw-r--r--src/yuzu_cmd/yuzu.cpp21
27 files changed, 143 insertions, 213 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index f49a31612..d5d4f6f82 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -63,7 +63,6 @@ add_library(common STATIC
63 string_util.cpp 63 string_util.cpp
64 string_util.h 64 string_util.h
65 swap.h 65 swap.h
66 synchronized_wrapper.h
67 telemetry.cpp 66 telemetry.cpp
68 telemetry.h 67 telemetry.h
69 thread.cpp 68 thread.cpp
diff --git a/src/common/common_paths.h b/src/common/common_paths.h
index 9bf3efaf2..6799a357a 100644
--- a/src/common/common_paths.h
+++ b/src/common/common_paths.h
@@ -26,7 +26,7 @@
26#define USA_DIR "USA" 26#define USA_DIR "USA"
27#define JAP_DIR "JAP" 27#define JAP_DIR "JAP"
28 28
29// Subdirs in the User dir returned by GetUserPath(D_USER_IDX) 29// Subdirs in the User dir returned by GetUserPath(UserPath::UserDir)
30#define CONFIG_DIR "config" 30#define CONFIG_DIR "config"
31#define CACHE_DIR "cache" 31#define CACHE_DIR "cache"
32#define SDMC_DIR "sdmc" 32#define SDMC_DIR "sdmc"
@@ -35,11 +35,11 @@
35#define LOG_DIR "log" 35#define LOG_DIR "log"
36 36
37// Filenames 37// Filenames
38// Files in the directory returned by GetUserPath(D_CONFIG_IDX) 38// Files in the directory returned by GetUserPath(UserPath::ConfigDir)
39#define EMU_CONFIG "emu.ini" 39#define EMU_CONFIG "emu.ini"
40#define DEBUGGER_CONFIG "debugger.ini" 40#define DEBUGGER_CONFIG "debugger.ini"
41#define LOGGER_CONFIG "logger.ini" 41#define LOGGER_CONFIG "logger.ini"
42// Files in the directory returned by GetUserPath(D_LOGS_IDX) 42// Files in the directory returned by GetUserPath(UserPath::LogDir)
43#define LOG_FILE "yuzu_log.txt" 43#define LOG_FILE "yuzu_log.txt"
44 44
45// Sys files 45// Sys files
diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp
index efcf58ca6..d8163a4a8 100644
--- a/src/common/file_util.cpp
+++ b/src/common/file_util.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 <sstream> 5#include <sstream>
6#include <unordered_map>
6#include "common/assert.h" 7#include "common/assert.h"
7#include "common/common_funcs.h" 8#include "common/common_funcs.h"
8#include "common/common_paths.h" 9#include "common/common_paths.h"
@@ -681,67 +682,68 @@ std::string GetSysDirectory() {
681 682
682// Returns a string with a yuzu data dir or file in the user's home 683// Returns a string with a yuzu data dir or file in the user's home
683// directory. To be used in "multi-user" mode (that is, installed). 684// directory. To be used in "multi-user" mode (that is, installed).
684const std::string& GetUserPath(const unsigned int DirIDX, const std::string& newPath) { 685const std::string& GetUserPath(UserPath path, const std::string& new_path) {
685 static std::string paths[NUM_PATH_INDICES]; 686 static std::unordered_map<UserPath, std::string> paths;
687 auto& user_path = paths[UserPath::UserDir];
686 688
687 // Set up all paths and files on the first run 689 // Set up all paths and files on the first run
688 if (paths[D_USER_IDX].empty()) { 690 if (user_path.empty()) {
689#ifdef _WIN32 691#ifdef _WIN32
690 paths[D_USER_IDX] = GetExeDirectory() + DIR_SEP USERDATA_DIR DIR_SEP; 692 user_path = GetExeDirectory() + DIR_SEP USERDATA_DIR DIR_SEP;
691 if (!FileUtil::IsDirectory(paths[D_USER_IDX])) { 693 if (!FileUtil::IsDirectory(user_path)) {
692 paths[D_USER_IDX] = AppDataRoamingDirectory() + DIR_SEP EMU_DATA_DIR DIR_SEP; 694 user_path = AppDataRoamingDirectory() + DIR_SEP EMU_DATA_DIR DIR_SEP;
693 } else { 695 } else {
694 LOG_INFO(Common_Filesystem, "Using the local user directory"); 696 LOG_INFO(Common_Filesystem, "Using the local user directory");
695 } 697 }
696 698
697 paths[D_CONFIG_IDX] = paths[D_USER_IDX] + CONFIG_DIR DIR_SEP; 699 paths.emplace(UserPath::ConfigDir, user_path + CONFIG_DIR DIR_SEP);
698 paths[D_CACHE_IDX] = paths[D_USER_IDX] + CACHE_DIR DIR_SEP; 700 paths.emplace(UserPath::CacheDir, user_path + CACHE_DIR DIR_SEP);
699#else 701#else
700 if (FileUtil::Exists(ROOT_DIR DIR_SEP USERDATA_DIR)) { 702 if (FileUtil::Exists(ROOT_DIR DIR_SEP USERDATA_DIR)) {
701 paths[D_USER_IDX] = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP; 703 user_path = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP;
702 paths[D_CONFIG_IDX] = paths[D_USER_IDX] + CONFIG_DIR DIR_SEP; 704 paths.emplace(UserPath::ConfigDir, user_path + CONFIG_DIR DIR_SEP);
703 paths[D_CACHE_IDX] = paths[D_USER_IDX] + CACHE_DIR DIR_SEP; 705 paths.emplace(UserPath::CacheDir, user_path + CACHE_DIR DIR_SEP);
704 } else { 706 } else {
705 std::string data_dir = GetUserDirectory("XDG_DATA_HOME"); 707 std::string data_dir = GetUserDirectory("XDG_DATA_HOME");
706 std::string config_dir = GetUserDirectory("XDG_CONFIG_HOME"); 708 std::string config_dir = GetUserDirectory("XDG_CONFIG_HOME");
707 std::string cache_dir = GetUserDirectory("XDG_CACHE_HOME"); 709 std::string cache_dir = GetUserDirectory("XDG_CACHE_HOME");
708 710
709 paths[D_USER_IDX] = data_dir + DIR_SEP EMU_DATA_DIR DIR_SEP; 711 user_path = data_dir + DIR_SEP EMU_DATA_DIR DIR_SEP;
710 paths[D_CONFIG_IDX] = config_dir + DIR_SEP EMU_DATA_DIR DIR_SEP; 712 paths.emplace(UserPath::ConfigDir, config_dir + DIR_SEP EMU_DATA_DIR DIR_SEP);
711 paths[D_CACHE_IDX] = cache_dir + DIR_SEP EMU_DATA_DIR DIR_SEP; 713 paths.emplace(UserPath::CacheDir, cache_dir + DIR_SEP EMU_DATA_DIR DIR_SEP);
712 } 714 }
713#endif 715#endif
714 paths[D_SDMC_IDX] = paths[D_USER_IDX] + SDMC_DIR DIR_SEP; 716 paths.emplace(UserPath::SDMCDir, user_path + SDMC_DIR DIR_SEP);
715 paths[D_NAND_IDX] = paths[D_USER_IDX] + NAND_DIR DIR_SEP; 717 paths.emplace(UserPath::NANDDir, user_path + NAND_DIR DIR_SEP);
716 paths[D_SYSDATA_IDX] = paths[D_USER_IDX] + SYSDATA_DIR DIR_SEP; 718 paths.emplace(UserPath::SysDataDir, user_path + SYSDATA_DIR DIR_SEP);
717 // TODO: Put the logs in a better location for each OS 719 // TODO: Put the logs in a better location for each OS
718 paths[D_LOGS_IDX] = paths[D_USER_IDX] + LOG_DIR DIR_SEP; 720 paths.emplace(UserPath::LogDir, user_path + LOG_DIR DIR_SEP);
719 } 721 }
720 722
721 if (!newPath.empty()) { 723 if (!new_path.empty()) {
722 if (!FileUtil::IsDirectory(newPath)) { 724 if (!FileUtil::IsDirectory(new_path)) {
723 LOG_ERROR(Common_Filesystem, "Invalid path specified {}", newPath); 725 LOG_ERROR(Common_Filesystem, "Invalid path specified {}", new_path);
724 return paths[DirIDX]; 726 return paths[path];
725 } else { 727 } else {
726 paths[DirIDX] = newPath; 728 paths[path] = new_path;
727 } 729 }
728 730
729 switch (DirIDX) { 731 switch (path) {
730 case D_ROOT_IDX: 732 case UserPath::RootDir:
731 paths[D_USER_IDX] = paths[D_ROOT_IDX] + DIR_SEP; 733 user_path = paths[UserPath::RootDir] + DIR_SEP;
732 break; 734 break;
733 735
734 case D_USER_IDX: 736 case UserPath::UserDir:
735 paths[D_USER_IDX] = paths[D_ROOT_IDX] + DIR_SEP; 737 user_path = paths[UserPath::RootDir] + DIR_SEP;
736 paths[D_CONFIG_IDX] = paths[D_USER_IDX] + CONFIG_DIR DIR_SEP; 738 paths[UserPath::ConfigDir] = user_path + CONFIG_DIR DIR_SEP;
737 paths[D_CACHE_IDX] = paths[D_USER_IDX] + CACHE_DIR DIR_SEP; 739 paths[UserPath::CacheDir] = user_path + CACHE_DIR DIR_SEP;
738 paths[D_SDMC_IDX] = paths[D_USER_IDX] + SDMC_DIR DIR_SEP; 740 paths[UserPath::SDMCDir] = user_path + SDMC_DIR DIR_SEP;
739 paths[D_NAND_IDX] = paths[D_USER_IDX] + NAND_DIR DIR_SEP; 741 paths[UserPath::NANDDir] = user_path + NAND_DIR DIR_SEP;
740 break; 742 break;
741 } 743 }
742 } 744 }
743 745
744 return paths[DirIDX]; 746 return paths[path];
745} 747}
746 748
747size_t WriteStringToFile(bool text_file, const std::string& str, const char* filename) { 749size_t WriteStringToFile(bool text_file, const std::string& str, const char* filename) {
diff --git a/src/common/file_util.h b/src/common/file_util.h
index 1f38b1560..ff01bf0ff 100644
--- a/src/common/file_util.h
+++ b/src/common/file_util.h
@@ -16,21 +16,20 @@
16#include "common/string_util.h" 16#include "common/string_util.h"
17#endif 17#endif
18 18
19// User directory indices for GetUserPath
20enum {
21 D_USER_IDX,
22 D_ROOT_IDX,
23 D_CONFIG_IDX,
24 D_CACHE_IDX,
25 D_SDMC_IDX,
26 D_NAND_IDX,
27 D_SYSDATA_IDX,
28 D_LOGS_IDX,
29 NUM_PATH_INDICES
30};
31
32namespace FileUtil { 19namespace FileUtil {
33 20
21// User paths for GetUserPath
22enum class UserPath {
23 CacheDir,
24 ConfigDir,
25 LogDir,
26 NANDDir,
27 RootDir,
28 SDMCDir,
29 SysDataDir,
30 UserDir,
31};
32
34// FileSystem tree node/ 33// FileSystem tree node/
35struct FSTEntry { 34struct FSTEntry {
36 bool isDirectory; 35 bool isDirectory;
@@ -123,7 +122,7 @@ bool SetCurrentDir(const std::string& directory);
123 122
124// Returns a pointer to a string with a yuzu data dir in the user's home 123// Returns a pointer to a string with a yuzu data dir in the user's home
125// directory. To be used in "multi-user" mode (that is, installed). 124// directory. To be used in "multi-user" mode (that is, installed).
126const std::string& GetUserPath(const unsigned int DirIDX, const std::string& newPath = ""); 125const std::string& GetUserPath(UserPath path, const std::string& new_path = "");
127 126
128// Returns the path to where the sys file are 127// Returns the path to where the sys file are
129std::string GetSysDirectory(); 128std::string GetSysDirectory();
diff --git a/src/common/synchronized_wrapper.h b/src/common/synchronized_wrapper.h
deleted file mode 100644
index 4a1984c46..000000000
--- a/src/common/synchronized_wrapper.h
+++ /dev/null
@@ -1,85 +0,0 @@
1// Copyright 2015 Citra 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 <algorithm>
8#include <mutex>
9
10namespace Common {
11
12template <typename T>
13class SynchronizedWrapper;
14
15/**
16 * Synchronized reference, that keeps a SynchronizedWrapper's mutex locked during its lifetime. This
17 * greatly reduces the chance that someone will access the wrapped resource without locking the
18 * mutex.
19 */
20template <typename T>
21class SynchronizedRef {
22public:
23 SynchronizedRef(SynchronizedWrapper<T>& wrapper) : wrapper(&wrapper) {
24 wrapper.mutex.lock();
25 }
26
27 SynchronizedRef(SynchronizedRef&) = delete;
28 SynchronizedRef(SynchronizedRef&& o) : wrapper(o.wrapper) {
29 o.wrapper = nullptr;
30 }
31
32 ~SynchronizedRef() {
33 if (wrapper)
34 wrapper->mutex.unlock();
35 }
36
37 SynchronizedRef& operator=(SynchronizedRef&) = delete;
38 SynchronizedRef& operator=(SynchronizedRef&& o) {
39 std::swap(wrapper, o.wrapper);
40 return *this;
41 }
42
43 T& operator*() {
44 return wrapper->data;
45 }
46 const T& operator*() const {
47 return wrapper->data;
48 }
49
50 T* operator->() {
51 return &wrapper->data;
52 }
53 const T* operator->() const {
54 return &wrapper->data;
55 }
56
57private:
58 SynchronizedWrapper<T>* wrapper;
59};
60
61/**
62 * Wraps an object, only allowing access to it via a locking reference wrapper. Good to ensure no
63 * one forgets to lock a mutex before acessing an object. To access the wrapped object construct a
64 * SyncronizedRef on this wrapper. Inspired by Rust's Mutex type
65 * (http://doc.rust-lang.org/std/sync/struct.Mutex.html).
66 */
67template <typename T>
68class SynchronizedWrapper {
69public:
70 template <typename... Args>
71 SynchronizedWrapper(Args&&... args) : data(std::forward<Args>(args)...) {}
72
73 SynchronizedRef<T> Lock() {
74 return {*this};
75 }
76
77private:
78 template <typename U>
79 friend class SynchronizedRef;
80
81 std::mutex mutex;
82 T data;
83};
84
85} // namespace Common
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index dffcdfbaf..671e0b8d0 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -272,9 +272,9 @@ void RegisterFileSystems() {
272 sdmc_factory = nullptr; 272 sdmc_factory = nullptr;
273 273
274 auto nand_directory = std::make_shared<FileSys::RealVfsDirectory>( 274 auto nand_directory = std::make_shared<FileSys::RealVfsDirectory>(
275 FileUtil::GetUserPath(D_NAND_IDX), FileSys::Mode::Write); 275 FileUtil::GetUserPath(FileUtil::UserPath::NANDDir), FileSys::Mode::Write);
276 auto sd_directory = std::make_shared<FileSys::RealVfsDirectory>( 276 auto sd_directory = std::make_shared<FileSys::RealVfsDirectory>(
277 FileUtil::GetUserPath(D_SDMC_IDX), FileSys::Mode::Write); 277 FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir), FileSys::Mode::Write);
278 278
279 auto savedata = std::make_unique<FileSys::SaveDataFactory>(std::move(nand_directory)); 279 auto savedata = std::make_unique<FileSys::SaveDataFactory>(std::move(nand_directory));
280 save_data_factory = std::move(savedata); 280 save_data_factory = std::move(savedata);
diff --git a/src/core/hle/service/ns/pl_u.cpp b/src/core/hle/service/ns/pl_u.cpp
index 691b1d106..bad27894a 100644
--- a/src/core/hle/service/ns/pl_u.cpp
+++ b/src/core/hle/service/ns/pl_u.cpp
@@ -42,7 +42,7 @@ PL_U::PL_U() : ServiceFramework("pl:u") {
42 RegisterHandlers(functions); 42 RegisterHandlers(functions);
43 43
44 // Attempt to load shared font data from disk 44 // Attempt to load shared font data from disk
45 const std::string filepath{FileUtil::GetUserPath(D_SYSDATA_IDX) + SHARED_FONT}; 45 const std::string filepath{FileUtil::GetUserPath(FileUtil::UserPath::SysDataDir) + SHARED_FONT};
46 FileUtil::CreateFullPath(filepath); // Create path if not already created 46 FileUtil::CreateFullPath(filepath); // Create path if not already created
47 FileUtil::IOFile file(filepath, "rb"); 47 FileUtil::IOFile file(filepath, "rb");
48 48
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
index 8de870596..126782573 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
@@ -42,6 +42,9 @@ u32 nvhost_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u
42 if (command.cmd == NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO) { 42 if (command.cmd == NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO) {
43 return SubmitGPFIFO(input, output); 43 return SubmitGPFIFO(input, output);
44 } 44 }
45 if (command.cmd == NVGPU_IOCTL_CHANNEL_KICKOFF_PB) {
46 return KickoffPB(input, output);
47 }
45 } 48 }
46 49
47 UNIMPLEMENTED_MSG("Unimplemented ioctl"); 50 UNIMPLEMENTED_MSG("Unimplemented ioctl");
@@ -127,14 +130,37 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& outp
127 IoctlSubmitGpfifo params{}; 130 IoctlSubmitGpfifo params{};
128 std::memcpy(&params, input.data(), sizeof(IoctlSubmitGpfifo)); 131 std::memcpy(&params, input.data(), sizeof(IoctlSubmitGpfifo));
129 LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}", 132 LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}",
130 params.gpfifo, params.num_entries, params.flags); 133 params.address, params.num_entries, params.flags);
131 134
132 auto entries = std::vector<IoctlGpfifoEntry>(); 135 auto entries = std::vector<IoctlGpfifoEntry>();
133 entries.resize(params.num_entries); 136 entries.resize(params.num_entries);
134 std::memcpy(&entries[0], &input.data()[sizeof(IoctlSubmitGpfifo)], 137 std::memcpy(&entries[0], &input.data()[sizeof(IoctlSubmitGpfifo)],
135 params.num_entries * sizeof(IoctlGpfifoEntry)); 138 params.num_entries * sizeof(IoctlGpfifoEntry));
136 for (auto entry : entries) { 139 for (auto entry : entries) {
137 VAddr va_addr = entry.Address(); 140 Tegra::GPUVAddr va_addr = entry.Address();
141 Core::System::GetInstance().GPU().ProcessCommandList(va_addr, entry.sz);
142 }
143 params.fence_out.id = 0;
144 params.fence_out.value = 0;
145 std::memcpy(output.data(), &params, output.size());
146 return 0;
147}
148
149u32 nvhost_gpu::KickoffPB(const std::vector<u8>& input, std::vector<u8>& output) {
150 if (input.size() < sizeof(IoctlSubmitGpfifo)) {
151 UNIMPLEMENTED();
152 }
153 IoctlSubmitGpfifo params{};
154 std::memcpy(&params, input.data(), sizeof(IoctlSubmitGpfifo));
155 LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}",
156 params.address, params.num_entries, params.flags);
157
158 std::vector<IoctlGpfifoEntry> entries(params.num_entries);
159 Memory::ReadBlock(params.address, entries.data(),
160 params.num_entries * sizeof(IoctlGpfifoEntry));
161
162 for (auto entry : entries) {
163 Tegra::GPUVAddr va_addr = entry.Address();
138 Core::System::GetInstance().GPU().ProcessCommandList(va_addr, entry.sz); 164 Core::System::GetInstance().GPU().ProcessCommandList(va_addr, entry.sz);
139 } 165 }
140 params.fence_out.id = 0; 166 params.fence_out.id = 0;
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
index c9f6b9b6a..aa8df2e6e 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
@@ -15,6 +15,7 @@ namespace Service::Nvidia::Devices {
15class nvmap; 15class nvmap;
16constexpr u32 NVGPU_IOCTL_MAGIC('H'); 16constexpr u32 NVGPU_IOCTL_MAGIC('H');
17constexpr u32 NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO(0x8); 17constexpr u32 NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO(0x8);
18constexpr u32 NVGPU_IOCTL_CHANNEL_KICKOFF_PB(0x1b);
18 19
19class nvhost_gpu final : public nvdevice { 20class nvhost_gpu final : public nvdevice {
20public: 21public:
@@ -158,14 +159,14 @@ private:
158 BitField<31, 1, u32_le> unk2; 159 BitField<31, 1, u32_le> unk2;
159 }; 160 };
160 161
161 VAddr Address() const { 162 Tegra::GPUVAddr Address() const {
162 return (static_cast<VAddr>(gpu_va_hi) << 32) | entry0; 163 return (static_cast<Tegra::GPUVAddr>(gpu_va_hi) << 32) | entry0;
163 } 164 }
164 }; 165 };
165 static_assert(sizeof(IoctlGpfifoEntry) == 8, "IoctlGpfifoEntry is incorrect size"); 166 static_assert(sizeof(IoctlGpfifoEntry) == 8, "IoctlGpfifoEntry is incorrect size");
166 167
167 struct IoctlSubmitGpfifo { 168 struct IoctlSubmitGpfifo {
168 u64_le gpfifo; // (ignored) pointer to gpfifo fence structs 169 u64_le address; // pointer to gpfifo entry structs
169 u32_le num_entries; // number of fence objects being submitted 170 u32_le num_entries; // number of fence objects being submitted
170 u32_le flags; 171 u32_le flags;
171 IoctlFence fence_out; // returned new fence object for others to wait on 172 IoctlFence fence_out; // returned new fence object for others to wait on
@@ -193,6 +194,7 @@ private:
193 u32 AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& output); 194 u32 AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& output);
194 u32 AllocateObjectContext(const std::vector<u8>& input, std::vector<u8>& output); 195 u32 AllocateObjectContext(const std::vector<u8>& input, std::vector<u8>& output);
195 u32 SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& output); 196 u32 SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& output);
197 u32 KickoffPB(const std::vector<u8>& input, std::vector<u8>& output);
196 u32 GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output); 198 u32 GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output);
197 u32 ChannelSetTimeout(const std::vector<u8>& input, std::vector<u8>& output); 199 u32 ChannelSetTimeout(const std::vector<u8>& input, std::vector<u8>& output);
198 200
diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp
index b10efd5c9..1b497b814 100644
--- a/src/core/hle/service/nvdrv/interface.cpp
+++ b/src/core/hle/service/nvdrv/interface.cpp
@@ -101,7 +101,7 @@ NVDRV::NVDRV(std::shared_ptr<Module> nvdrv, const char* name)
101 {8, &NVDRV::SetClientPID, "SetClientPID"}, 101 {8, &NVDRV::SetClientPID, "SetClientPID"},
102 {9, nullptr, "DumpGraphicsMemoryInfo"}, 102 {9, nullptr, "DumpGraphicsMemoryInfo"},
103 {10, nullptr, "InitializeDevtools"}, 103 {10, nullptr, "InitializeDevtools"},
104 {11, nullptr, "Ioctl2"}, 104 {11, &NVDRV::Ioctl, "Ioctl2"},
105 {12, nullptr, "Ioctl3"}, 105 {12, nullptr, "Ioctl3"},
106 {13, &NVDRV::FinishInitialize, "FinishInitialize"}, 106 {13, &NVDRV::FinishInitialize, "FinishInitialize"},
107 }; 107 };
diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp
index b9a603df3..69aa7a7be 100644
--- a/src/core/telemetry_session.cpp
+++ b/src/core/telemetry_session.cpp
@@ -37,7 +37,8 @@ static u64 GenerateTelemetryId() {
37 37
38u64 GetTelemetryId() { 38u64 GetTelemetryId() {
39 u64 telemetry_id{}; 39 u64 telemetry_id{};
40 static const std::string& filename{FileUtil::GetUserPath(D_CONFIG_IDX) + "telemetry_id"}; 40 static const std::string& filename{FileUtil::GetUserPath(FileUtil::UserPath::ConfigDir) +
41 "telemetry_id"};
41 42
42 if (FileUtil::Exists(filename)) { 43 if (FileUtil::Exists(filename)) {
43 FileUtil::IOFile file(filename, "rb"); 44 FileUtil::IOFile file(filename, "rb");
@@ -61,7 +62,8 @@ u64 GetTelemetryId() {
61 62
62u64 RegenerateTelemetryId() { 63u64 RegenerateTelemetryId() {
63 const u64 new_telemetry_id{GenerateTelemetryId()}; 64 const u64 new_telemetry_id{GenerateTelemetryId()};
64 static const std::string& filename{FileUtil::GetUserPath(D_CONFIG_IDX) + "telemetry_id"}; 65 static const std::string& filename{FileUtil::GetUserPath(FileUtil::UserPath::ConfigDir) +
66 "telemetry_id"};
65 67
66 FileUtil::IOFile file(filename, "wb"); 68 FileUtil::IOFile file(filename, "wb");
67 if (!file.IsOpen()) { 69 if (!file.IsOpen()) {
diff --git a/src/video_core/engines/fermi_2d.cpp b/src/video_core/engines/fermi_2d.cpp
index 34053e393..ea1555c5d 100644
--- a/src/video_core/engines/fermi_2d.cpp
+++ b/src/video_core/engines/fermi_2d.cpp
@@ -6,8 +6,7 @@
6#include "video_core/engines/fermi_2d.h" 6#include "video_core/engines/fermi_2d.h"
7#include "video_core/textures/decoders.h" 7#include "video_core/textures/decoders.h"
8 8
9namespace Tegra { 9namespace Tegra::Engines {
10namespace Engines {
11 10
12Fermi2D::Fermi2D(MemoryManager& memory_manager) : memory_manager(memory_manager) {} 11Fermi2D::Fermi2D(MemoryManager& memory_manager) : memory_manager(memory_manager) {}
13 12
@@ -69,5 +68,4 @@ void Fermi2D::HandleSurfaceCopy() {
69 } 68 }
70} 69}
71 70
72} // namespace Engines 71} // namespace Tegra::Engines
73} // namespace Tegra
diff --git a/src/video_core/engines/fermi_2d.h b/src/video_core/engines/fermi_2d.h
index 70667cb94..dcf9ef8b9 100644
--- a/src/video_core/engines/fermi_2d.h
+++ b/src/video_core/engines/fermi_2d.h
@@ -12,8 +12,7 @@
12#include "video_core/gpu.h" 12#include "video_core/gpu.h"
13#include "video_core/memory_manager.h" 13#include "video_core/memory_manager.h"
14 14
15namespace Tegra { 15namespace Tegra::Engines {
16namespace Engines {
17 16
18#define FERMI2D_REG_INDEX(field_name) \ 17#define FERMI2D_REG_INDEX(field_name) \
19 (offsetof(Tegra::Engines::Fermi2D::Regs, field_name) / sizeof(u32)) 18 (offsetof(Tegra::Engines::Fermi2D::Regs, field_name) / sizeof(u32))
@@ -110,5 +109,4 @@ ASSERT_REG_POSITION(operation, 0xAB);
110ASSERT_REG_POSITION(trigger, 0xB5); 109ASSERT_REG_POSITION(trigger, 0xB5);
111#undef ASSERT_REG_POSITION 110#undef ASSERT_REG_POSITION
112 111
113} // namespace Engines 112} // namespace Tegra::Engines
114} // namespace Tegra
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index 91b077005..dbd106c53 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -17,8 +17,7 @@
17#include "video_core/memory_manager.h" 17#include "video_core/memory_manager.h"
18#include "video_core/textures/texture.h" 18#include "video_core/textures/texture.h"
19 19
20namespace Tegra { 20namespace Tegra::Engines {
21namespace Engines {
22 21
23#define MAXWELL3D_REG_INDEX(field_name) \ 22#define MAXWELL3D_REG_INDEX(field_name) \
24 (offsetof(Tegra::Engines::Maxwell3D::Regs, field_name) / sizeof(u32)) 23 (offsetof(Tegra::Engines::Maxwell3D::Regs, field_name) / sizeof(u32))
@@ -898,5 +897,4 @@ ASSERT_REG_POSITION(tex_info_buffers.size[0], 0xD2F);
898 897
899#undef ASSERT_REG_POSITION 898#undef ASSERT_REG_POSITION
900 899
901} // namespace Engines 900} // namespace Tegra::Engines
902} // namespace Tegra
diff --git a/src/video_core/engines/maxwell_compute.h b/src/video_core/engines/maxwell_compute.h
index 7262e1bcb..2b3e4ced6 100644
--- a/src/video_core/engines/maxwell_compute.h
+++ b/src/video_core/engines/maxwell_compute.h
@@ -6,8 +6,7 @@
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8 8
9namespace Tegra { 9namespace Tegra::Engines {
10namespace Engines {
11 10
12class MaxwellCompute final { 11class MaxwellCompute final {
13public: 12public:
@@ -18,5 +17,4 @@ public:
18 void WriteReg(u32 method, u32 value); 17 void WriteReg(u32 method, u32 value);
19}; 18};
20 19
21} // namespace Engines 20} // namespace Tegra::Engines
22} // namespace Tegra
diff --git a/src/video_core/engines/maxwell_dma.h b/src/video_core/engines/maxwell_dma.h
index 905749bde..7882f16e0 100644
--- a/src/video_core/engines/maxwell_dma.h
+++ b/src/video_core/engines/maxwell_dma.h
@@ -12,8 +12,7 @@
12#include "video_core/gpu.h" 12#include "video_core/gpu.h"
13#include "video_core/memory_manager.h" 13#include "video_core/memory_manager.h"
14 14
15namespace Tegra { 15namespace Tegra::Engines {
16namespace Engines {
17 16
18class MaxwellDMA final { 17class MaxwellDMA final {
19public: 18public:
@@ -151,5 +150,4 @@ ASSERT_REG_POSITION(src_params, 0x1CA);
151 150
152#undef ASSERT_REG_POSITION 151#undef ASSERT_REG_POSITION
153 152
154} // namespace Engines 153} // namespace Tegra::Engines
155} // namespace Tegra
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index 65fa1495f..939a71022 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -15,8 +15,7 @@
15#include "common/bit_field.h" 15#include "common/bit_field.h"
16#include "common/common_types.h" 16#include "common/common_types.h"
17 17
18namespace Tegra { 18namespace Tegra::Shader {
19namespace Shader {
20 19
21struct Register { 20struct Register {
22 /// Number of registers 21 /// Number of registers
@@ -109,8 +108,7 @@ union Sampler {
109 u64 value{}; 108 u64 value{};
110}; 109};
111 110
112} // namespace Shader 111} // namespace Tegra::Shader
113} // namespace Tegra
114 112
115namespace std { 113namespace std {
116 114
@@ -127,8 +125,7 @@ struct make_unsigned<Tegra::Shader::Register> {
127 125
128} // namespace std 126} // namespace std
129 127
130namespace Tegra { 128namespace Tegra::Shader {
131namespace Shader {
132 129
133enum class Pred : u64 { 130enum class Pred : u64 {
134 UnusedIndex = 0x7, 131 UnusedIndex = 0x7,
@@ -784,5 +781,4 @@ private:
784 } 781 }
785}; 782};
786 783
787} // namespace Shader 784} // namespace Tegra::Shader
788} // namespace Tegra
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index a1ac18a71..b48d30466 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -12,8 +12,7 @@
12#include "video_core/renderer_opengl/gl_rasterizer.h" 12#include "video_core/renderer_opengl/gl_rasterizer.h"
13#include "video_core/renderer_opengl/gl_shader_decompiler.h" 13#include "video_core/renderer_opengl/gl_shader_decompiler.h"
14 14
15namespace GLShader { 15namespace GLShader::Decompiler {
16namespace Decompiler {
17 16
18using Tegra::Shader::Attribute; 17using Tegra::Shader::Attribute;
19using Tegra::Shader::Instruction; 18using Tegra::Shader::Instruction;
@@ -1845,5 +1844,4 @@ boost::optional<ProgramResult> DecompileProgram(const ProgramCode& program_code,
1845 return boost::none; 1844 return boost::none;
1846} 1845}
1847 1846
1848} // namespace Decompiler 1847} // namespace GLShader::Decompiler
1849} // namespace GLShader
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.h b/src/video_core/renderer_opengl/gl_shader_decompiler.h
index 7610dad3a..df6769462 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.h
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.h
@@ -12,8 +12,7 @@
12#include "video_core/engines/maxwell_3d.h" 12#include "video_core/engines/maxwell_3d.h"
13#include "video_core/renderer_opengl/gl_shader_gen.h" 13#include "video_core/renderer_opengl/gl_shader_gen.h"
14 14
15namespace GLShader { 15namespace GLShader::Decompiler {
16namespace Decompiler {
17 16
18using Tegra::Engines::Maxwell3D; 17using Tegra::Engines::Maxwell3D;
19 18
@@ -23,5 +22,4 @@ boost::optional<ProgramResult> DecompileProgram(const ProgramCode& program_code,
23 Maxwell3D::Regs::ShaderStage stage, 22 Maxwell3D::Regs::ShaderStage stage,
24 const std::string& suffix); 23 const std::string& suffix);
25 24
26} // namespace Decompiler 25} // namespace GLShader::Decompiler
27} // namespace GLShader
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp
index a3684a195..a3e67d105 100644
--- a/src/video_core/textures/decoders.cpp
+++ b/src/video_core/textures/decoders.cpp
@@ -10,8 +10,7 @@
10#include "video_core/textures/decoders.h" 10#include "video_core/textures/decoders.h"
11#include "video_core/textures/texture.h" 11#include "video_core/textures/texture.h"
12 12
13namespace Tegra { 13namespace Tegra::Texture {
14namespace Texture {
15 14
16/** 15/**
17 * Calculates the offset of an (x, y) position within a swizzled texture. 16 * Calculates the offset of an (x, y) position within a swizzled texture.
@@ -186,5 +185,4 @@ std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat
186 return rgba_data; 185 return rgba_data;
187} 186}
188 187
189} // namespace Texture 188} // namespace Tegra::Texture
190} // namespace Tegra
diff --git a/src/video_core/textures/decoders.h b/src/video_core/textures/decoders.h
index 2b088c077..73a4924d1 100644
--- a/src/video_core/textures/decoders.h
+++ b/src/video_core/textures/decoders.h
@@ -8,8 +8,7 @@
8#include "common/common_types.h" 8#include "common/common_types.h"
9#include "video_core/textures/texture.h" 9#include "video_core/textures/texture.h"
10 10
11namespace Tegra { 11namespace Tegra::Texture {
12namespace Texture {
13 12
14/** 13/**
15 * Unswizzles a swizzled texture without changing its format. 14 * Unswizzles a swizzled texture without changing its format.
@@ -33,5 +32,4 @@ void CopySwizzledData(u32 width, u32 height, u32 bytes_per_pixel, u32 out_bytes_
33std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat format, u32 width, 32std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat format, u32 width,
34 u32 height); 33 u32 height);
35 34
36} // namespace Texture 35} // namespace Tegra::Texture
37} // namespace Tegra
diff --git a/src/video_core/textures/texture.h b/src/video_core/textures/texture.h
index a17eaf19d..d1c755033 100644
--- a/src/video_core/textures/texture.h
+++ b/src/video_core/textures/texture.h
@@ -10,8 +10,7 @@
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "video_core/memory_manager.h" 11#include "video_core/memory_manager.h"
12 12
13namespace Tegra { 13namespace Tegra::Texture {
14namespace Texture {
15 14
16enum class TextureFormat : u32 { 15enum class TextureFormat : u32 {
17 R32_G32_B32_A32 = 0x01, 16 R32_G32_B32_A32 = 0x01,
@@ -260,5 +259,4 @@ struct FullTextureInfo {
260/// Returns the number of bytes per pixel of the input texture format. 259/// Returns the number of bytes per pixel of the input texture format.
261u32 BytesPerPixel(TextureFormat format); 260u32 BytesPerPixel(TextureFormat format);
262 261
263} // namespace Texture 262} // namespace Tegra::Texture
264} // namespace Tegra
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 62754a1a9..98969fe10 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -10,7 +10,7 @@
10 10
11Config::Config() { 11Config::Config() {
12 // TODO: Don't hardcode the path; let the frontend decide where to put the config files. 12 // TODO: Don't hardcode the path; let the frontend decide where to put the config files.
13 qt_config_loc = FileUtil::GetUserPath(D_CONFIG_IDX) + "qt-config.ini"; 13 qt_config_loc = FileUtil::GetUserPath(FileUtil::UserPath::ConfigDir) + "qt-config.ini";
14 FileUtil::CreateFullPath(qt_config_loc); 14 FileUtil::CreateFullPath(qt_config_loc);
15 qt_config = new QSettings(QString::fromStdString(qt_config_loc), QSettings::IniFormat); 15 qt_config = new QSettings(QString::fromStdString(qt_config_loc), QSettings::IniFormat);
16 16
diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp
index 241db4ae3..5e66239ff 100644
--- a/src/yuzu/configuration/configure_debug.cpp
+++ b/src/yuzu/configuration/configure_debug.cpp
@@ -19,7 +19,7 @@ ConfigureDebug::ConfigureDebug(QWidget* parent) : QWidget(parent), ui(new Ui::Co
19 ui->setupUi(this); 19 ui->setupUi(this);
20 this->setConfiguration(); 20 this->setConfiguration();
21 connect(ui->open_log_button, &QPushButton::pressed, []() { 21 connect(ui->open_log_button, &QPushButton::pressed, []() {
22 QString path = QString::fromStdString(FileUtil::GetUserPath(D_LOGS_IDX)); 22 QString path = QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::LogDir));
23 QDesktopServices::openUrl(QUrl::fromLocalFile(path)); 23 QDesktopServices::openUrl(QUrl::fromLocalFile(path));
24 }); 24 });
25} 25}
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 16812e077..16a95bb19 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -909,6 +909,16 @@ void GMainWindow::UpdateUITheme() {
909#undef main 909#undef main
910#endif 910#endif
911 911
912static void InitializeLogging() {
913 Log::Filter log_filter;
914 log_filter.ParseFilterString(Settings::values.log_filter);
915 Log::SetGlobalFilter(log_filter);
916
917 const std::string& log_dir = FileUtil::GetUserPath(FileUtil::UserPath::LogDir);
918 FileUtil::CreateFullPath(log_dir);
919 Log::AddBackend(std::make_unique<Log::FileBackend>(log_dir + LOG_FILE));
920}
921
912int main(int argc, char* argv[]) { 922int main(int argc, char* argv[]) {
913 MicroProfileOnThreadCreate("Frontend"); 923 MicroProfileOnThreadCreate("Frontend");
914 SCOPE_EXIT({ MicroProfileShutdown(); }); 924 SCOPE_EXIT({ MicroProfileShutdown(); });
@@ -927,13 +937,7 @@ int main(int argc, char* argv[]) {
927 937
928 GMainWindow main_window; 938 GMainWindow main_window;
929 // After settings have been loaded by GMainWindow, apply the filter 939 // After settings have been loaded by GMainWindow, apply the filter
930 Log::Filter log_filter; 940 InitializeLogging();
931 log_filter.ParseFilterString(Settings::values.log_filter);
932 Log::SetGlobalFilter(log_filter);
933 FileUtil::CreateFullPath(FileUtil::GetUserPath(D_LOGS_IDX));
934 Log::AddBackend(
935 std::make_unique<Log::FileBackend>(FileUtil::GetUserPath(D_LOGS_IDX) + LOG_FILE));
936
937 main_window.show(); 941 main_window.show();
938 return app.exec(); 942 return app.exec();
939} 943}
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
index 723e8b4cc..cea1a5e62 100644
--- a/src/yuzu_cmd/config.cpp
+++ b/src/yuzu_cmd/config.cpp
@@ -15,7 +15,7 @@
15 15
16Config::Config() { 16Config::Config() {
17 // TODO: Don't hardcode the path; let the frontend decide where to put the config files. 17 // TODO: Don't hardcode the path; let the frontend decide where to put the config files.
18 sdl2_config_loc = FileUtil::GetUserPath(D_CONFIG_IDX) + "sdl2-config.ini"; 18 sdl2_config_loc = FileUtil::GetUserPath(FileUtil::UserPath::ConfigDir) + "sdl2-config.ini";
19 sdl2_config = std::make_unique<INIReader>(sdl2_config_loc); 19 sdl2_config = std::make_unique<INIReader>(sdl2_config_loc);
20 20
21 Reload(); 21 Reload();
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp
index 24db1065a..b5392c499 100644
--- a/src/yuzu_cmd/yuzu.cpp
+++ b/src/yuzu_cmd/yuzu.cpp
@@ -56,6 +56,18 @@ static void PrintVersion() {
56 std::cout << "yuzu " << Common::g_scm_branch << " " << Common::g_scm_desc << std::endl; 56 std::cout << "yuzu " << Common::g_scm_branch << " " << Common::g_scm_desc << std::endl;
57} 57}
58 58
59static void InitializeLogging() {
60 Log::Filter log_filter(Log::Level::Debug);
61 log_filter.ParseFilterString(Settings::values.log_filter);
62 Log::SetGlobalFilter(log_filter);
63
64 Log::AddBackend(std::make_unique<Log::ColorConsoleBackend>());
65
66 const std::string& log_dir = FileUtil::GetUserPath(FileUtil::UserPath::LogDir);
67 FileUtil::CreateFullPath(log_dir);
68 Log::AddBackend(std::make_unique<Log::FileBackend>(log_dir + LOG_FILE));
69}
70
59/// Application entry point 71/// Application entry point
60int main(int argc, char** argv) { 72int main(int argc, char** argv) {
61 Config config; 73 Config config;
@@ -124,14 +136,7 @@ int main(int argc, char** argv) {
124 LocalFree(argv_w); 136 LocalFree(argv_w);
125#endif 137#endif
126 138
127 Log::Filter log_filter(Log::Level::Debug); 139 InitializeLogging();
128 log_filter.ParseFilterString(Settings::values.log_filter);
129 Log::SetGlobalFilter(log_filter);
130
131 Log::AddBackend(std::make_unique<Log::ColorConsoleBackend>());
132 FileUtil::CreateFullPath(FileUtil::GetUserPath(D_LOGS_IDX));
133 Log::AddBackend(
134 std::make_unique<Log::FileBackend>(FileUtil::GetUserPath(D_LOGS_IDX) + LOG_FILE));
135 140
136 MicroProfileOnThreadCreate("EmuThread"); 141 MicroProfileOnThreadCreate("EmuThread");
137 SCOPE_EXIT({ MicroProfileShutdown(); }); 142 SCOPE_EXIT({ MicroProfileShutdown(); });