summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/CMakeLists.txt4
-rw-r--r--src/common/bit_field.h17
-rw-r--r--src/common/cityhash.cpp340
-rw-r--r--src/common/cityhash.h110
-rw-r--r--src/common/code_block.h85
-rw-r--r--src/common/common_funcs.h7
-rw-r--r--src/common/common_types.h30
-rw-r--r--src/common/hash.cpp141
-rw-r--r--src/common/hash.h55
-rw-r--r--src/common/math_util.h5
-rw-r--r--src/common/thread.h19
-rw-r--r--src/common/vector_math.h30
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/core.cpp28
-rw-r--r--src/core/core.h12
-rw-r--r--src/core/file_sys/disk_filesystem.cpp14
-rw-r--r--src/core/file_sys/disk_filesystem.h7
-rw-r--r--src/core/file_sys/filesystem.h2
-rw-r--r--src/core/file_sys/partition_filesystem.cpp125
-rw-r--r--src/core/file_sys/partition_filesystem.h87
-rw-r--r--src/core/file_sys/romfs_filesystem.cpp2
-rw-r--r--src/core/file_sys/romfs_filesystem.h2
-rw-r--r--src/core/hle/kernel/resource_limit.cpp46
-rw-r--r--src/core/hle/kernel/resource_limit.h26
-rw-r--r--src/core/hle/kernel/svc.cpp23
-rw-r--r--src/core/hle/kernel/vm_manager.cpp2
-rw-r--r--src/core/hle/service/acc/acc.cpp14
-rw-r--r--src/core/hle/service/acc/acc.h6
-rw-r--r--src/core/hle/service/acc/acc_aa.cpp6
-rw-r--r--src/core/hle/service/acc/acc_aa.h6
-rw-r--r--src/core/hle/service/acc/acc_su.cpp6
-rw-r--r--src/core/hle/service/acc/acc_u0.cpp6
-rw-r--r--src/core/hle/service/acc/acc_u0.h6
-rw-r--r--src/core/hle/service/acc/acc_u1.cpp6
-rw-r--r--src/core/hle/service/acc/acc_u1.h6
-rw-r--r--src/core/hle/service/am/am.cpp6
-rw-r--r--src/core/hle/service/am/applet_ae.cpp6
-rw-r--r--src/core/hle/service/am/applet_oe.cpp6
-rw-r--r--src/core/hle/service/aoc/aoc_u.cpp6
-rw-r--r--src/core/hle/service/aoc/aoc_u.h6
-rw-r--r--src/core/hle/service/apm/apm.cpp6
-rw-r--r--src/core/hle/service/apm/apm.h6
-rw-r--r--src/core/hle/service/apm/interface.cpp6
-rw-r--r--src/core/hle/service/apm/interface.h6
-rw-r--r--src/core/hle/service/audio/audin_u.cpp6
-rw-r--r--src/core/hle/service/audio/audin_u.h6
-rw-r--r--src/core/hle/service/audio/audio.cpp6
-rw-r--r--src/core/hle/service/audio/audio.h6
-rw-r--r--src/core/hle/service/audio/audout_u.cpp6
-rw-r--r--src/core/hle/service/audio/audout_u.h6
-rw-r--r--src/core/hle/service/audio/audrec_u.cpp6
-rw-r--r--src/core/hle/service/audio/audrec_u.h6
-rw-r--r--src/core/hle/service/audio/audren_u.cpp6
-rw-r--r--src/core/hle/service/audio/audren_u.h6
-rw-r--r--src/core/hle/service/audio/codecctl.cpp6
-rw-r--r--src/core/hle/service/audio/codecctl.h6
-rw-r--r--src/core/hle/service/fatal/fatal.cpp6
-rw-r--r--src/core/hle/service/fatal/fatal.h6
-rw-r--r--src/core/hle/service/fatal/fatal_p.cpp6
-rw-r--r--src/core/hle/service/fatal/fatal_p.h6
-rw-r--r--src/core/hle/service/fatal/fatal_u.cpp6
-rw-r--r--src/core/hle/service/fatal/fatal_u.h6
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp6
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.cpp32
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.h6
-rw-r--r--src/core/hle/service/friend/friend.cpp6
-rw-r--r--src/core/hle/service/friend/friend.h6
-rw-r--r--src/core/hle/service/friend/friend_a.cpp6
-rw-r--r--src/core/hle/service/friend/friend_a.h6
-rw-r--r--src/core/hle/service/friend/friend_u.cpp6
-rw-r--r--src/core/hle/service/friend/friend_u.h6
-rw-r--r--src/core/hle/service/hid/hid.cpp6
-rw-r--r--src/core/hle/service/hid/hid.h6
-rw-r--r--src/core/hle/service/lm/lm.cpp6
-rw-r--r--src/core/hle/service/lm/lm.h6
-rw-r--r--src/core/hle/service/nfp/nfp.cpp6
-rw-r--r--src/core/hle/service/nfp/nfp.h6
-rw-r--r--src/core/hle/service/nfp/nfp_user.cpp6
-rw-r--r--src/core/hle/service/nfp/nfp_user.h6
-rw-r--r--src/core/hle/service/nifm/nifm.cpp6
-rw-r--r--src/core/hle/service/nifm/nifm.h6
-rw-r--r--src/core/hle/service/nifm/nifm_a.cpp6
-rw-r--r--src/core/hle/service/nifm/nifm_a.h6
-rw-r--r--src/core/hle/service/nifm/nifm_s.cpp6
-rw-r--r--src/core/hle/service/nifm/nifm_s.h6
-rw-r--r--src/core/hle/service/nifm/nifm_u.cpp6
-rw-r--r--src/core/hle/service/nifm/nifm_u.h6
-rw-r--r--src/core/hle/service/ns/ns.cpp6
-rw-r--r--src/core/hle/service/ns/ns.h6
-rw-r--r--src/core/hle/service/ns/pl_u.cpp37
-rw-r--r--src/core/hle/service/ns/pl_u.h6
-rw-r--r--src/core/hle/service/nvdrv/devices/nvdevice.h8
-rw-r--r--src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp8
-rw-r--r--src/core/hle/service/nvdrv/devices/nvdisp_disp0.h8
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp8
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h8
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp8
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl.h8
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp8
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h9
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp8
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.h8
-rw-r--r--src/core/hle/service/nvdrv/devices/nvmap.cpp8
-rw-r--r--src/core/hle/service/nvdrv/devices/nvmap.h8
-rw-r--r--src/core/hle/service/nvdrv/interface.cpp6
-rw-r--r--src/core/hle/service/nvdrv/interface.h6
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.cpp6
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.h6
-rw-r--r--src/core/hle/service/nvdrv/nvmemp.cpp6
-rw-r--r--src/core/hle/service/nvdrv/nvmemp.h6
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.cpp6
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.h6
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.cpp9
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.h6
-rw-r--r--src/core/hle/service/pctl/pctl.cpp6
-rw-r--r--src/core/hle/service/pctl/pctl.h6
-rw-r--r--src/core/hle/service/pctl/pctl_a.cpp6
-rw-r--r--src/core/hle/service/pctl/pctl_a.h6
-rw-r--r--src/core/hle/service/service.cpp52
-rw-r--r--src/core/hle/service/service.h2
-rw-r--r--src/core/hle/service/set/set.cpp7
-rw-r--r--src/core/hle/service/set/set.h6
-rw-r--r--src/core/hle/service/set/set_cal.cpp15
-rw-r--r--src/core/hle/service/set/set_cal.h6
-rw-r--r--src/core/hle/service/set/set_fd.cpp6
-rw-r--r--src/core/hle/service/set/set_fd.h6
-rw-r--r--src/core/hle/service/set/set_sys.cpp16
-rw-r--r--src/core/hle/service/set/set_sys.h6
-rw-r--r--src/core/hle/service/set/settings.cpp6
-rw-r--r--src/core/hle/service/set/settings.h6
-rw-r--r--src/core/hle/service/sm/controller.cpp6
-rw-r--r--src/core/hle/service/sm/controller.h6
-rw-r--r--src/core/hle/service/sm/sm.cpp10
-rw-r--r--src/core/hle/service/sm/sm.h12
-rw-r--r--src/core/hle/service/sockets/bsd.cpp31
-rw-r--r--src/core/hle/service/sockets/bsd.h6
-rw-r--r--src/core/hle/service/sockets/nsd.cpp6
-rw-r--r--src/core/hle/service/sockets/nsd.h6
-rw-r--r--src/core/hle/service/sockets/sfdnsres.cpp7
-rw-r--r--src/core/hle/service/sockets/sfdnsres.h6
-rw-r--r--src/core/hle/service/sockets/sockets.cpp6
-rw-r--r--src/core/hle/service/sockets/sockets.h6
-rw-r--r--src/core/hle/service/spl/csrng.cpp6
-rw-r--r--src/core/hle/service/spl/csrng.h6
-rw-r--r--src/core/hle/service/spl/module.cpp6
-rw-r--r--src/core/hle/service/spl/module.h6
-rw-r--r--src/core/hle/service/spl/spl.cpp12
-rw-r--r--src/core/hle/service/spl/spl.h6
-rw-r--r--src/core/hle/service/ssl/ssl.cpp6
-rw-r--r--src/core/hle/service/ssl/ssl.h6
-rw-r--r--src/core/hle/service/time/time.cpp12
-rw-r--r--src/core/hle/service/time/time.h6
-rw-r--r--src/core/hle/service/time/time_s.cpp17
-rw-r--r--src/core/hle/service/time/time_s.h6
-rw-r--r--src/core/hle/service/time/time_u.cpp17
-rw-r--r--src/core/hle/service/time/time_u.h6
-rw-r--r--src/core/hle/service/vi/vi.cpp163
-rw-r--r--src/core/hle/service/vi/vi.h6
-rw-r--r--src/core/hle/service/vi/vi_m.cpp6
-rw-r--r--src/core/hle/service/vi/vi_m.h6
-rw-r--r--src/core/hle/service/vi/vi_s.cpp6
-rw-r--r--src/core/hle/service/vi/vi_s.h6
-rw-r--r--src/core/hle/service/vi/vi_u.cpp7
-rw-r--r--src/core/hle/service/vi/vi_u.h6
-rw-r--r--src/core/perf_stats.cpp3
-rw-r--r--src/input_common/motion_emu.cpp5
-rw-r--r--src/video_core/CMakeLists.txt3
-rw-r--r--src/video_core/engines/maxwell_3d.cpp37
-rw-r--r--src/video_core/engines/maxwell_3d.h118
-rw-r--r--src/video_core/engines/shader_bytecode.h439
-rw-r--r--src/video_core/gpu.h3
-rw-r--r--src/video_core/rasterizer_interface.h2
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp406
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h88
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp191
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.h122
-rw-r--r--src/video_core/renderer_opengl/gl_resource_manager.h139
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp791
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.h25
-rw-r--r--src/video_core/renderer_opengl/gl_shader_gen.cpp68
-rw-r--r--src/video_core/renderer_opengl/gl_shader_gen.h119
-rw-r--r--src/video_core/renderer_opengl/gl_shader_manager.cpp64
-rw-r--r--src/video_core/renderer_opengl/gl_shader_manager.h175
-rw-r--r--src/video_core/renderer_opengl/gl_shader_util.cpp169
-rw-r--r--src/video_core/renderer_opengl/gl_shader_util.h56
-rw-r--r--src/video_core/renderer_opengl/gl_state.cpp18
-rw-r--r--src/video_core/renderer_opengl/gl_state.h6
-rw-r--r--src/video_core/renderer_opengl/gl_stream_buffer.h2
-rw-r--r--src/video_core/renderer_opengl/maxwell_to_gl.h108
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp15
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.h2
-rw-r--r--src/video_core/textures/decoders.cpp23
-rw-r--r--src/video_core/textures/decoders.h3
-rw-r--r--src/video_core/textures/texture.h29
-rw-r--r--src/video_core/utils.h2
-rw-r--r--src/yuzu/main.cpp15
-rw-r--r--src/yuzu_cmd/yuzu.cpp9
197 files changed, 3979 insertions, 1710 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 2ba1da195..32cb85de0 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -32,14 +32,14 @@ add_library(common STATIC
32 break_points.cpp 32 break_points.cpp
33 break_points.h 33 break_points.h
34 chunk_file.h 34 chunk_file.h
35 code_block.h 35 cityhash.cpp
36 cityhash.h
36 color.h 37 color.h
37 common_funcs.h 38 common_funcs.h
38 common_paths.h 39 common_paths.h
39 common_types.h 40 common_types.h
40 file_util.cpp 41 file_util.cpp
41 file_util.h 42 file_util.h
42 hash.cpp
43 hash.h 43 hash.h
44 linear_disk_cache.h 44 linear_disk_cache.h
45 logging/backend.cpp 45 logging/backend.cpp
diff --git a/src/common/bit_field.h b/src/common/bit_field.h
index 0cc0a1be0..65e357dec 100644
--- a/src/common/bit_field.h
+++ b/src/common/bit_field.h
@@ -115,7 +115,7 @@ private:
115 // assignment would copy the full storage value, rather than just the bits 115 // assignment would copy the full storage value, rather than just the bits
116 // relevant to this particular bit field. 116 // relevant to this particular bit field.
117 // We don't delete it because we want BitField to be trivially copyable. 117 // We don't delete it because we want BitField to be trivially copyable.
118 BitField& operator=(const BitField&) = default; 118 constexpr BitField& operator=(const BitField&) = default;
119 119
120 // StorageType is T for non-enum types and the underlying type of T if 120 // StorageType is T for non-enum types and the underlying type of T if
121 // T is an enumeration. Note that T is wrapped within an enable_if in the 121 // T is an enumeration. Note that T is wrapped within an enable_if in the
@@ -166,20 +166,20 @@ public:
166 // so that we can use this within unions 166 // so that we can use this within unions
167 constexpr BitField() = default; 167 constexpr BitField() = default;
168 168
169 FORCE_INLINE operator T() const { 169 constexpr FORCE_INLINE operator T() const {
170 return Value(); 170 return Value();
171 } 171 }
172 172
173 FORCE_INLINE void Assign(const T& value) { 173 constexpr FORCE_INLINE void Assign(const T& value) {
174 storage = (storage & ~mask) | FormatValue(value); 174 storage = (storage & ~mask) | FormatValue(value);
175 } 175 }
176 176
177 FORCE_INLINE T Value() const { 177 constexpr T Value() const {
178 return ExtractValue(storage); 178 return ExtractValue(storage);
179 } 179 }
180 180
181 // TODO: we may want to change this to explicit operator bool() if it's bug-free in VS2015 181 // TODO: we may want to change this to explicit operator bool() if it's bug-free in VS2015
182 FORCE_INLINE bool ToBool() const { 182 constexpr FORCE_INLINE bool ToBool() const {
183 return Value() != 0; 183 return Value() != 0;
184 } 184 }
185 185
@@ -192,11 +192,6 @@ private:
192 static_assert(position < 8 * sizeof(T), "Invalid position"); 192 static_assert(position < 8 * sizeof(T), "Invalid position");
193 static_assert(bits <= 8 * sizeof(T), "Invalid number of bits"); 193 static_assert(bits <= 8 * sizeof(T), "Invalid number of bits");
194 static_assert(bits > 0, "Invalid number of bits"); 194 static_assert(bits > 0, "Invalid number of bits");
195 static_assert(std::is_pod<T>::value, "Invalid base type"); 195 static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable in a BitField");
196}; 196};
197#pragma pack() 197#pragma pack()
198
199#if (__GNUC__ >= 5) || defined(__clang__) || defined(_MSC_VER)
200static_assert(std::is_trivially_copyable<BitField<0, 1, unsigned>>::value,
201 "BitField must be trivially copyable");
202#endif
diff --git a/src/common/cityhash.cpp b/src/common/cityhash.cpp
new file mode 100644
index 000000000..de31ffbd8
--- /dev/null
+++ b/src/common/cityhash.cpp
@@ -0,0 +1,340 @@
1// Copyright (c) 2011 Google, Inc.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19// THE SOFTWARE.
20//
21// CityHash, by Geoff Pike and Jyrki Alakuijala
22//
23// This file provides CityHash64() and related functions.
24//
25// It's probably possible to create even faster hash functions by
26// writing a program that systematically explores some of the space of
27// possible hash functions, by using SIMD instructions, or by
28// compromising on hash quality.
29
30#include <algorithm>
31#include <string.h> // for memcpy and memset
32#include "cityhash.h"
33#include "common/swap.h"
34
35// #include "config.h"
36#ifdef __GNUC__
37#define HAVE_BUILTIN_EXPECT 1
38#endif
39#ifdef COMMON_BIG_ENDIAN
40#define WORDS_BIGENDIAN 1
41#endif
42
43using namespace std;
44
45typedef uint8_t uint8;
46typedef uint32_t uint32;
47typedef uint64_t uint64;
48
49namespace Common {
50
51static uint64 UNALIGNED_LOAD64(const char* p) {
52 uint64 result;
53 memcpy(&result, p, sizeof(result));
54 return result;
55}
56
57static uint32 UNALIGNED_LOAD32(const char* p) {
58 uint32 result;
59 memcpy(&result, p, sizeof(result));
60 return result;
61}
62
63#ifdef WORDS_BIGENDIAN
64#define uint32_in_expected_order(x) (swap32(x))
65#define uint64_in_expected_order(x) (swap64(x))
66#else
67#define uint32_in_expected_order(x) (x)
68#define uint64_in_expected_order(x) (x)
69#endif
70
71#if !defined(LIKELY)
72#if HAVE_BUILTIN_EXPECT
73#define LIKELY(x) (__builtin_expect(!!(x), 1))
74#else
75#define LIKELY(x) (x)
76#endif
77#endif
78
79static uint64 Fetch64(const char* p) {
80 return uint64_in_expected_order(UNALIGNED_LOAD64(p));
81}
82
83static uint32 Fetch32(const char* p) {
84 return uint32_in_expected_order(UNALIGNED_LOAD32(p));
85}
86
87// Some primes between 2^63 and 2^64 for various uses.
88static const uint64 k0 = 0xc3a5c85c97cb3127ULL;
89static const uint64 k1 = 0xb492b66fbe98f273ULL;
90static const uint64 k2 = 0x9ae16a3b2f90404fULL;
91
92// Bitwise right rotate. Normally this will compile to a single
93// instruction, especially if the shift is a manifest constant.
94static uint64 Rotate(uint64 val, int shift) {
95 // Avoid shifting by 64: doing so yields an undefined result.
96 return shift == 0 ? val : ((val >> shift) | (val << (64 - shift)));
97}
98
99static uint64 ShiftMix(uint64 val) {
100 return val ^ (val >> 47);
101}
102
103static uint64 HashLen16(uint64 u, uint64 v) {
104 return Hash128to64(uint128(u, v));
105}
106
107static uint64 HashLen16(uint64 u, uint64 v, uint64 mul) {
108 // Murmur-inspired hashing.
109 uint64 a = (u ^ v) * mul;
110 a ^= (a >> 47);
111 uint64 b = (v ^ a) * mul;
112 b ^= (b >> 47);
113 b *= mul;
114 return b;
115}
116
117static uint64 HashLen0to16(const char* s, size_t len) {
118 if (len >= 8) {
119 uint64 mul = k2 + len * 2;
120 uint64 a = Fetch64(s) + k2;
121 uint64 b = Fetch64(s + len - 8);
122 uint64 c = Rotate(b, 37) * mul + a;
123 uint64 d = (Rotate(a, 25) + b) * mul;
124 return HashLen16(c, d, mul);
125 }
126 if (len >= 4) {
127 uint64 mul = k2 + len * 2;
128 uint64 a = Fetch32(s);
129 return HashLen16(len + (a << 3), Fetch32(s + len - 4), mul);
130 }
131 if (len > 0) {
132 uint8 a = s[0];
133 uint8 b = s[len >> 1];
134 uint8 c = s[len - 1];
135 uint32 y = static_cast<uint32>(a) + (static_cast<uint32>(b) << 8);
136 uint32 z = static_cast<uint32>(len) + (static_cast<uint32>(c) << 2);
137 return ShiftMix(y * k2 ^ z * k0) * k2;
138 }
139 return k2;
140}
141
142// This probably works well for 16-byte strings as well, but it may be overkill
143// in that case.
144static uint64 HashLen17to32(const char* s, size_t len) {
145 uint64 mul = k2 + len * 2;
146 uint64 a = Fetch64(s) * k1;
147 uint64 b = Fetch64(s + 8);
148 uint64 c = Fetch64(s + len - 8) * mul;
149 uint64 d = Fetch64(s + len - 16) * k2;
150 return HashLen16(Rotate(a + b, 43) + Rotate(c, 30) + d, a + Rotate(b + k2, 18) + c, mul);
151}
152
153// Return a 16-byte hash for 48 bytes. Quick and dirty.
154// Callers do best to use "random-looking" values for a and b.
155static pair<uint64, uint64> WeakHashLen32WithSeeds(uint64 w, uint64 x, uint64 y, uint64 z, uint64 a,
156 uint64 b) {
157 a += w;
158 b = Rotate(b + a + z, 21);
159 uint64 c = a;
160 a += x;
161 a += y;
162 b += Rotate(a, 44);
163 return make_pair(a + z, b + c);
164}
165
166// Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty.
167static pair<uint64, uint64> WeakHashLen32WithSeeds(const char* s, uint64 a, uint64 b) {
168 return WeakHashLen32WithSeeds(Fetch64(s), Fetch64(s + 8), Fetch64(s + 16), Fetch64(s + 24), a,
169 b);
170}
171
172// Return an 8-byte hash for 33 to 64 bytes.
173static uint64 HashLen33to64(const char* s, size_t len) {
174 uint64 mul = k2 + len * 2;
175 uint64 a = Fetch64(s) * k2;
176 uint64 b = Fetch64(s + 8);
177 uint64 c = Fetch64(s + len - 24);
178 uint64 d = Fetch64(s + len - 32);
179 uint64 e = Fetch64(s + 16) * k2;
180 uint64 f = Fetch64(s + 24) * 9;
181 uint64 g = Fetch64(s + len - 8);
182 uint64 h = Fetch64(s + len - 16) * mul;
183 uint64 u = Rotate(a + g, 43) + (Rotate(b, 30) + c) * 9;
184 uint64 v = ((a + g) ^ d) + f + 1;
185 uint64 w = swap64((u + v) * mul) + h;
186 uint64 x = Rotate(e + f, 42) + c;
187 uint64 y = (swap64((v + w) * mul) + g) * mul;
188 uint64 z = e + f + c;
189 a = swap64((x + z) * mul + y) + b;
190 b = ShiftMix((z + a) * mul + d + h) * mul;
191 return b + x;
192}
193
194uint64 CityHash64(const char* s, size_t len) {
195 if (len <= 32) {
196 if (len <= 16) {
197 return HashLen0to16(s, len);
198 } else {
199 return HashLen17to32(s, len);
200 }
201 } else if (len <= 64) {
202 return HashLen33to64(s, len);
203 }
204
205 // For strings over 64 bytes we hash the end first, and then as we
206 // loop we keep 56 bytes of state: v, w, x, y, and z.
207 uint64 x = Fetch64(s + len - 40);
208 uint64 y = Fetch64(s + len - 16) + Fetch64(s + len - 56);
209 uint64 z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24));
210 pair<uint64, uint64> v = WeakHashLen32WithSeeds(s + len - 64, len, z);
211 pair<uint64, uint64> w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x);
212 x = x * k1 + Fetch64(s);
213
214 // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks.
215 len = (len - 1) & ~static_cast<size_t>(63);
216 do {
217 x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
218 y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
219 x ^= w.second;
220 y += v.first + Fetch64(s + 40);
221 z = Rotate(z + w.first, 33) * k1;
222 v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
223 w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
224 std::swap(z, x);
225 s += 64;
226 len -= 64;
227 } while (len != 0);
228 return HashLen16(HashLen16(v.first, w.first) + ShiftMix(y) * k1 + z,
229 HashLen16(v.second, w.second) + x);
230}
231
232uint64 CityHash64WithSeed(const char* s, size_t len, uint64 seed) {
233 return CityHash64WithSeeds(s, len, k2, seed);
234}
235
236uint64 CityHash64WithSeeds(const char* s, size_t len, uint64 seed0, uint64 seed1) {
237 return HashLen16(CityHash64(s, len) - seed0, seed1);
238}
239
240// A subroutine for CityHash128(). Returns a decent 128-bit hash for strings
241// of any length representable in signed long. Based on City and Murmur.
242static uint128 CityMurmur(const char* s, size_t len, uint128 seed) {
243 uint64 a = Uint128Low64(seed);
244 uint64 b = Uint128High64(seed);
245 uint64 c = 0;
246 uint64 d = 0;
247 signed long l = static_cast<long>(len) - 16;
248 if (l <= 0) { // len <= 16
249 a = ShiftMix(a * k1) * k1;
250 c = b * k1 + HashLen0to16(s, len);
251 d = ShiftMix(a + (len >= 8 ? Fetch64(s) : c));
252 } else { // len > 16
253 c = HashLen16(Fetch64(s + len - 8) + k1, a);
254 d = HashLen16(b + len, c + Fetch64(s + len - 16));
255 a += d;
256 do {
257 a ^= ShiftMix(Fetch64(s) * k1) * k1;
258 a *= k1;
259 b ^= a;
260 c ^= ShiftMix(Fetch64(s + 8) * k1) * k1;
261 c *= k1;
262 d ^= c;
263 s += 16;
264 l -= 16;
265 } while (l > 0);
266 }
267 a = HashLen16(a, c);
268 b = HashLen16(d, b);
269 return uint128(a ^ b, HashLen16(b, a));
270}
271
272uint128 CityHash128WithSeed(const char* s, size_t len, uint128 seed) {
273 if (len < 128) {
274 return CityMurmur(s, len, seed);
275 }
276
277 // We expect len >= 128 to be the common case. Keep 56 bytes of state:
278 // v, w, x, y, and z.
279 pair<uint64, uint64> v, w;
280 uint64 x = Uint128Low64(seed);
281 uint64 y = Uint128High64(seed);
282 uint64 z = len * k1;
283 v.first = Rotate(y ^ k1, 49) * k1 + Fetch64(s);
284 v.second = Rotate(v.first, 42) * k1 + Fetch64(s + 8);
285 w.first = Rotate(y + z, 35) * k1 + x;
286 w.second = Rotate(x + Fetch64(s + 88), 53) * k1;
287
288 // This is the same inner loop as CityHash64(), manually unrolled.
289 do {
290 x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
291 y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
292 x ^= w.second;
293 y += v.first + Fetch64(s + 40);
294 z = Rotate(z + w.first, 33) * k1;
295 v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
296 w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
297 std::swap(z, x);
298 s += 64;
299 x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
300 y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
301 x ^= w.second;
302 y += v.first + Fetch64(s + 40);
303 z = Rotate(z + w.first, 33) * k1;
304 v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
305 w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
306 std::swap(z, x);
307 s += 64;
308 len -= 128;
309 } while (LIKELY(len >= 128));
310 x += Rotate(v.first + z, 49) * k0;
311 y = y * k0 + Rotate(w.second, 37);
312 z = z * k0 + Rotate(w.first, 27);
313 w.first *= 9;
314 v.first *= k0;
315 // If 0 < len < 128, hash up to 4 chunks of 32 bytes each from the end of s.
316 for (size_t tail_done = 0; tail_done < len;) {
317 tail_done += 32;
318 y = Rotate(x + y, 42) * k0 + v.second;
319 w.first += Fetch64(s + len - tail_done + 16);
320 x = x * k0 + w.first;
321 z += w.second + Fetch64(s + len - tail_done);
322 w.second += v.first;
323 v = WeakHashLen32WithSeeds(s + len - tail_done, v.first + z, v.second);
324 v.first *= k0;
325 }
326 // At this point our 56 bytes of state should contain more than
327 // enough information for a strong 128-bit hash. We use two
328 // different 56-byte-to-8-byte hashes to get a 16-byte final result.
329 x = HashLen16(x, v.first);
330 y = HashLen16(y + z, w.first);
331 return uint128(HashLen16(x + v.second, w.second) + y, HashLen16(x + w.second, y + v.second));
332}
333
334uint128 CityHash128(const char* s, size_t len) {
335 return len >= 16
336 ? CityHash128WithSeed(s + 16, len - 16, uint128(Fetch64(s), Fetch64(s + 8) + k0))
337 : CityHash128WithSeed(s, len, uint128(k0, k1));
338}
339
340} // namespace Common
diff --git a/src/common/cityhash.h b/src/common/cityhash.h
new file mode 100644
index 000000000..bcebdb150
--- /dev/null
+++ b/src/common/cityhash.h
@@ -0,0 +1,110 @@
1// Copyright (c) 2011 Google, Inc.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19// THE SOFTWARE.
20//
21// CityHash, by Geoff Pike and Jyrki Alakuijala
22//
23// http://code.google.com/p/cityhash/
24//
25// This file provides a few functions for hashing strings. All of them are
26// high-quality functions in the sense that they pass standard tests such
27// as Austin Appleby's SMHasher. They are also fast.
28//
29// For 64-bit x86 code, on short strings, we don't know of anything faster than
30// CityHash64 that is of comparable quality. We believe our nearest competitor
31// is Murmur3. For 64-bit x86 code, CityHash64 is an excellent choice for hash
32// tables and most other hashing (excluding cryptography).
33//
34// For 64-bit x86 code, on long strings, the picture is more complicated.
35// On many recent Intel CPUs, such as Nehalem, Westmere, Sandy Bridge, etc.,
36// CityHashCrc128 appears to be faster than all competitors of comparable
37// quality. CityHash128 is also good but not quite as fast. We believe our
38// nearest competitor is Bob Jenkins' Spooky. We don't have great data for
39// other 64-bit CPUs, but for long strings we know that Spooky is slightly
40// faster than CityHash on some relatively recent AMD x86-64 CPUs, for example.
41// Note that CityHashCrc128 is declared in citycrc.h.
42//
43// For 32-bit x86 code, we don't know of anything faster than CityHash32 that
44// is of comparable quality. We believe our nearest competitor is Murmur3A.
45// (On 64-bit CPUs, it is typically faster to use the other CityHash variants.)
46//
47// Functions in the CityHash family are not suitable for cryptography.
48//
49// Please see CityHash's README file for more details on our performance
50// measurements and so on.
51//
52// WARNING: This code has been only lightly tested on big-endian platforms!
53// It is known to work well on little-endian platforms that have a small penalty
54// for unaligned reads, such as current Intel and AMD moderate-to-high-end CPUs.
55// It should work on all 32-bit and 64-bit platforms that allow unaligned reads;
56// bug reports are welcome.
57//
58// By the way, for some hash functions, given strings a and b, the hash
59// of a+b is easily derived from the hashes of a and b. This property
60// doesn't hold for any hash functions in this file.
61
62#pragma once
63
64#include <utility>
65#include <stdint.h>
66#include <stdlib.h> // for size_t.
67
68namespace Common {
69
70typedef std::pair<uint64_t, uint64_t> uint128;
71
72inline uint64_t Uint128Low64(const uint128& x) {
73 return x.first;
74}
75inline uint64_t Uint128High64(const uint128& x) {
76 return x.second;
77}
78
79// Hash function for a byte array.
80uint64_t CityHash64(const char* buf, size_t len);
81
82// Hash function for a byte array. For convenience, a 64-bit seed is also
83// hashed into the result.
84uint64_t CityHash64WithSeed(const char* buf, size_t len, uint64_t seed);
85
86// Hash function for a byte array. For convenience, two seeds are also
87// hashed into the result.
88uint64_t CityHash64WithSeeds(const char* buf, size_t len, uint64_t seed0, uint64_t seed1);
89
90// Hash function for a byte array.
91uint128 CityHash128(const char* s, size_t len);
92
93// Hash function for a byte array. For convenience, a 128-bit seed is also
94// hashed into the result.
95uint128 CityHash128WithSeed(const char* s, size_t len, uint128 seed);
96
97// Hash 128 input bits down to 64 bits of output.
98// This is intended to be a reasonably good hash function.
99inline uint64_t Hash128to64(const uint128& x) {
100 // Murmur-inspired hashing.
101 const uint64_t kMul = 0x9ddfea08eb382d69ULL;
102 uint64_t a = (Uint128Low64(x) ^ Uint128High64(x)) * kMul;
103 a ^= (a >> 47);
104 uint64_t b = (Uint128High64(x) ^ a) * kMul;
105 b ^= (b >> 47);
106 b *= kMul;
107 return b;
108}
109
110} // namespace Common
diff --git a/src/common/code_block.h b/src/common/code_block.h
deleted file mode 100644
index 6a55a8e30..000000000
--- a/src/common/code_block.h
+++ /dev/null
@@ -1,85 +0,0 @@
1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <cstddef>
8#include "common/common_types.h"
9#include "common/memory_util.h"
10
11// Everything that needs to generate code should inherit from this.
12// You get memory management for free, plus, you can use all emitter functions without
13// having to prefix them with gen-> or something similar.
14// Example implementation:
15// class JIT : public CodeBlock<ARMXEmitter> {}
16template <class T>
17class CodeBlock : public T, NonCopyable {
18private:
19 // A privately used function to set the executable RAM space to something invalid.
20 // For debugging usefulness it should be used to set the RAM to a host specific breakpoint
21 // instruction
22 virtual void PoisonMemory() = 0;
23
24protected:
25 u8* region;
26 size_t region_size;
27
28public:
29 CodeBlock() : region(nullptr), region_size(0) {}
30 virtual ~CodeBlock() {
31 if (region)
32 FreeCodeSpace();
33 }
34
35 // Call this before you generate any code.
36 void AllocCodeSpace(int size) {
37 region_size = size;
38 region = (u8*)AllocateExecutableMemory(region_size);
39 T::SetCodePtr(region);
40 }
41
42 // Always clear code space with breakpoints, so that if someone accidentally executes
43 // uninitialized, it just breaks into the debugger.
44 void ClearCodeSpace() {
45 PoisonMemory();
46 ResetCodePtr();
47 }
48
49 // Call this when shutting down. Don't rely on the destructor, even though it'll do the job.
50 void FreeCodeSpace() {
51#ifdef __SYMBIAN32__
52 ResetExecutableMemory(region);
53#else
54 FreeMemoryPages(region, region_size);
55#endif
56 region = nullptr;
57 region_size = 0;
58 }
59
60 bool IsInSpace(const u8* ptr) {
61 return (ptr >= region) && (ptr < (region + region_size));
62 }
63
64 // Cannot currently be undone. Will write protect the entire code region.
65 // Start over if you need to change the code (call FreeCodeSpace(), AllocCodeSpace()).
66 void WriteProtect() {
67 WriteProtectMemory(region, region_size, true);
68 }
69
70 void ResetCodePtr() {
71 T::SetCodePtr(region);
72 }
73
74 size_t GetSpaceLeft() const {
75 return region_size - (T::GetCodePtr() - region);
76 }
77
78 u8* GetBasePtr() {
79 return region;
80 }
81
82 size_t GetOffset(const u8* ptr) const {
83 return ptr - region;
84 }
85};
diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h
index 6f0604958..7cf7b7997 100644
--- a/src/common/common_funcs.h
+++ b/src/common/common_funcs.h
@@ -9,8 +9,6 @@
9#endif 9#endif
10#include "common/common_types.h" 10#include "common/common_types.h"
11 11
12#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
13
14/// Textually concatenates two tokens. The double-expansion is required by the C preprocessor. 12/// Textually concatenates two tokens. The double-expansion is required by the C preprocessor.
15#define CONCAT2(x, y) DO_CONCAT2(x, y) 13#define CONCAT2(x, y) DO_CONCAT2(x, y)
16#define DO_CONCAT2(x, y) x##y 14#define DO_CONCAT2(x, y) x##y
@@ -74,11 +72,6 @@ inline u64 _rotr64(u64 x, unsigned int shift) {
74 72
75#else // _MSC_VER 73#else // _MSC_VER
76 74
77#if (_MSC_VER < 1900)
78// Function Cross-Compatibility
79#define snprintf _snprintf
80#endif
81
82// Locale Cross-Compatibility 75// Locale Cross-Compatibility
83#define locale_t _locale_t 76#define locale_t _locale_t
84 77
diff --git a/src/common/common_types.h b/src/common/common_types.h
index 844d34965..6b1766dca 100644
--- a/src/common/common_types.h
+++ b/src/common/common_types.h
@@ -27,29 +27,23 @@
27#include <array> 27#include <array>
28#include <cstdint> 28#include <cstdint>
29 29
30#ifdef _MSC_VER 30using u8 = std::uint8_t; ///< 8-bit unsigned byte
31#ifndef __func__ 31using u16 = std::uint16_t; ///< 16-bit unsigned short
32#define __func__ __FUNCTION__ 32using u32 = std::uint32_t; ///< 32-bit unsigned word
33#endif 33using u64 = std::uint64_t; ///< 64-bit unsigned int
34#endif
35 34
36typedef std::uint8_t u8; ///< 8-bit unsigned byte 35using s8 = std::int8_t; ///< 8-bit signed byte
37typedef std::uint16_t u16; ///< 16-bit unsigned short 36using s16 = std::int16_t; ///< 16-bit signed short
38typedef std::uint32_t u32; ///< 32-bit unsigned word 37using s32 = std::int32_t; ///< 32-bit signed word
39typedef std::uint64_t u64; ///< 64-bit unsigned int 38using s64 = std::int64_t; ///< 64-bit signed int
40 39
41typedef std::int8_t s8; ///< 8-bit signed byte 40using f32 = float; ///< 32-bit floating point
42typedef std::int16_t s16; ///< 16-bit signed short 41using f64 = double; ///< 64-bit floating point
43typedef std::int32_t s32; ///< 32-bit signed word
44typedef std::int64_t s64; ///< 64-bit signed int
45
46typedef float f32; ///< 32-bit floating point
47typedef double f64; ///< 64-bit floating point
48 42
49// TODO: It would be nice to eventually replace these with strong types that prevent accidental 43// TODO: It would be nice to eventually replace these with strong types that prevent accidental
50// conversion between each other. 44// conversion between each other.
51typedef u64 VAddr; ///< Represents a pointer in the userspace virtual address space. 45using VAddr = u64; ///< Represents a pointer in the userspace virtual address space.
52typedef u64 PAddr; ///< Represents a pointer in the ARM11 physical address space. 46using PAddr = u64; ///< Represents a pointer in the ARM11 physical address space.
53 47
54using u128 = std::array<std::uint64_t, 2>; 48using u128 = std::array<std::uint64_t, 2>;
55static_assert(sizeof(u128) == 16, "u128 must be 128 bits wide"); 49static_assert(sizeof(u128) == 16, "u128 must be 128 bits wide");
diff --git a/src/common/hash.cpp b/src/common/hash.cpp
deleted file mode 100644
index a02e9e5b9..000000000
--- a/src/common/hash.cpp
+++ /dev/null
@@ -1,141 +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#if defined(_MSC_VER)
6#include <stdlib.h>
7#endif
8#include "common/common_funcs.h"
9#include "common/common_types.h"
10#include "common/hash.h"
11
12namespace Common {
13
14// MurmurHash3 was written by Austin Appleby, and is placed in the public
15// domain. The author hereby disclaims copyright to this source code.
16
17// Block read - if your platform needs to do endian-swapping or can only handle aligned reads, do
18// the conversion here
19static FORCE_INLINE u64 getblock64(const u64* p, size_t i) {
20 return p[i];
21}
22
23// Finalization mix - force all bits of a hash block to avalanche
24static FORCE_INLINE u64 fmix64(u64 k) {
25 k ^= k >> 33;
26 k *= 0xff51afd7ed558ccdllu;
27 k ^= k >> 33;
28 k *= 0xc4ceb9fe1a85ec53llu;
29 k ^= k >> 33;
30
31 return k;
32}
33
34// This is the 128-bit variant of the MurmurHash3 hash function that is targeted for 64-bit
35// platforms (MurmurHash3_x64_128). It was taken from:
36// https://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp
37void MurmurHash3_128(const void* key, size_t len, u32 seed, void* out) {
38 const u8* data = (const u8*)key;
39 const size_t nblocks = len / 16;
40
41 u64 h1 = seed;
42 u64 h2 = seed;
43
44 const u64 c1 = 0x87c37b91114253d5llu;
45 const u64 c2 = 0x4cf5ad432745937fllu;
46
47 // Body
48
49 const u64* blocks = (const u64*)(data);
50
51 for (size_t i = 0; i < nblocks; i++) {
52 u64 k1 = getblock64(blocks, i * 2 + 0);
53 u64 k2 = getblock64(blocks, i * 2 + 1);
54
55 k1 *= c1;
56 k1 = _rotl64(k1, 31);
57 k1 *= c2;
58 h1 ^= k1;
59
60 h1 = _rotl64(h1, 27);
61 h1 += h2;
62 h1 = h1 * 5 + 0x52dce729;
63
64 k2 *= c2;
65 k2 = _rotl64(k2, 33);
66 k2 *= c1;
67 h2 ^= k2;
68
69 h2 = _rotl64(h2, 31);
70 h2 += h1;
71 h2 = h2 * 5 + 0x38495ab5;
72 }
73
74 // Tail
75
76 const u8* tail = (const u8*)(data + nblocks * 16);
77
78 u64 k1 = 0;
79 u64 k2 = 0;
80
81 switch (len & 15) {
82 case 15:
83 k2 ^= ((u64)tail[14]) << 48;
84 case 14:
85 k2 ^= ((u64)tail[13]) << 40;
86 case 13:
87 k2 ^= ((u64)tail[12]) << 32;
88 case 12:
89 k2 ^= ((u64)tail[11]) << 24;
90 case 11:
91 k2 ^= ((u64)tail[10]) << 16;
92 case 10:
93 k2 ^= ((u64)tail[9]) << 8;
94 case 9:
95 k2 ^= ((u64)tail[8]) << 0;
96 k2 *= c2;
97 k2 = _rotl64(k2, 33);
98 k2 *= c1;
99 h2 ^= k2;
100
101 case 8:
102 k1 ^= ((u64)tail[7]) << 56;
103 case 7:
104 k1 ^= ((u64)tail[6]) << 48;
105 case 6:
106 k1 ^= ((u64)tail[5]) << 40;
107 case 5:
108 k1 ^= ((u64)tail[4]) << 32;
109 case 4:
110 k1 ^= ((u64)tail[3]) << 24;
111 case 3:
112 k1 ^= ((u64)tail[2]) << 16;
113 case 2:
114 k1 ^= ((u64)tail[1]) << 8;
115 case 1:
116 k1 ^= ((u64)tail[0]) << 0;
117 k1 *= c1;
118 k1 = _rotl64(k1, 31);
119 k1 *= c2;
120 h1 ^= k1;
121 };
122
123 // Finalization
124
125 h1 ^= len;
126 h2 ^= len;
127
128 h1 += h2;
129 h2 += h1;
130
131 h1 = fmix64(h1);
132 h2 = fmix64(h2);
133
134 h1 += h2;
135 h2 += h1;
136
137 ((u64*)out)[0] = h1;
138 ((u64*)out)[1] = h2;
139}
140
141} // namespace Common
diff --git a/src/common/hash.h b/src/common/hash.h
index ee2560dad..73c326980 100644
--- a/src/common/hash.h
+++ b/src/common/hash.h
@@ -5,12 +5,12 @@
5#pragma once 5#pragma once
6 6
7#include <cstddef> 7#include <cstddef>
8#include <cstring>
9#include "common/cityhash.h"
8#include "common/common_types.h" 10#include "common/common_types.h"
9 11
10namespace Common { 12namespace Common {
11 13
12void MurmurHash3_128(const void* key, size_t len, u32 seed, void* out);
13
14/** 14/**
15 * Computes a 64-bit hash over the specified block of data 15 * Computes a 64-bit hash over the specified block of data
16 * @param data Block of data to compute hash over 16 * @param data Block of data to compute hash over
@@ -18,9 +18,54 @@ void MurmurHash3_128(const void* key, size_t len, u32 seed, void* out);
18 * @returns 64-bit hash value that was computed over the data block 18 * @returns 64-bit hash value that was computed over the data block
19 */ 19 */
20static inline u64 ComputeHash64(const void* data, size_t len) { 20static inline u64 ComputeHash64(const void* data, size_t len) {
21 u64 res[2]; 21 return CityHash64(static_cast<const char*>(data), len);
22 MurmurHash3_128(data, len, 0, res); 22}
23 return res[0]; 23
24/**
25 * Computes a 64-bit hash of a struct. In addition to being trivially copyable, it is also critical
26 * that either the struct includes no padding, or that any padding is initialized to a known value
27 * by memsetting the struct to 0 before filling it in.
28 */
29template <typename T>
30static inline u64 ComputeStructHash64(const T& data) {
31 static_assert(std::is_trivially_copyable<T>(),
32 "Type passed to ComputeStructHash64 must be trivially copyable");
33 return ComputeHash64(&data, sizeof(data));
24} 34}
25 35
36/// A helper template that ensures the padding in a struct is initialized by memsetting to 0.
37template <typename T>
38struct HashableStruct {
39 // In addition to being trivially copyable, T must also have a trivial default constructor,
40 // because any member initialization would be overridden by memset
41 static_assert(std::is_trivial<T>(), "Type passed to HashableStruct must be trivial");
42 /*
43 * We use a union because "implicitly-defined copy/move constructor for a union X copies the
44 * object representation of X." and "implicitly-defined copy assignment operator for a union X
45 * copies the object representation (3.9) of X." = Bytewise copy instead of memberwise copy.
46 * This is important because the padding bytes are included in the hash and comparison between
47 * objects.
48 */
49 union {
50 T state;
51 };
52
53 HashableStruct() {
54 // Memset structure to zero padding bits, so that they will be deterministic when hashing
55 std::memset(&state, 0, sizeof(T));
56 }
57
58 bool operator==(const HashableStruct<T>& o) const {
59 return std::memcmp(&state, &o.state, sizeof(T)) == 0;
60 };
61
62 bool operator!=(const HashableStruct<T>& o) const {
63 return !(*this == o);
64 };
65
66 size_t Hash() const {
67 return Common::ComputeStructHash64(state);
68 }
69};
70
26} // namespace Common 71} // namespace Common
diff --git a/src/common/math_util.h b/src/common/math_util.h
index 45a1ed367..c6a83c953 100644
--- a/src/common/math_util.h
+++ b/src/common/math_util.h
@@ -17,11 +17,6 @@ inline bool IntervalsIntersect(unsigned start0, unsigned length0, unsigned start
17 return (std::max(start0, start1) < std::min(start0 + length0, start1 + length1)); 17 return (std::max(start0, start1) < std::min(start0 + length0, start1 + length1));
18} 18}
19 19
20template <typename T>
21inline T Clamp(const T val, const T& min, const T& max) {
22 return std::max(min, std::min(max, val));
23}
24
25template <class T> 20template <class T>
26struct Rectangle { 21struct Rectangle {
27 T left; 22 T left;
diff --git a/src/common/thread.h b/src/common/thread.h
index fa475ab51..9465e1de7 100644
--- a/src/common/thread.h
+++ b/src/common/thread.h
@@ -11,25 +11,6 @@
11#include <thread> 11#include <thread>
12#include "common/common_types.h" 12#include "common/common_types.h"
13 13
14// Support for C++11's thread_local keyword was surprisingly spotty in compilers until very
15// recently. Fortunately, thread local variables have been well supported for compilers for a while,
16// but with semantics supporting only POD types, so we can use a few defines to get some amount of
17// backwards compat support.
18// WARNING: This only works correctly with POD types.
19#if defined(__clang__)
20#if !__has_feature(cxx_thread_local)
21#define thread_local __thread
22#endif
23#elif defined(__GNUC__)
24#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8)
25#define thread_local __thread
26#endif
27#elif defined(_MSC_VER)
28#if _MSC_VER < 1900
29#define thread_local __declspec(thread)
30#endif
31#endif
32
33namespace Common { 14namespace Common {
34 15
35int CurrentThreadId(); 16int CurrentThreadId();
diff --git a/src/common/vector_math.h b/src/common/vector_math.h
index 3f0057d9e..3f15ac1f4 100644
--- a/src/common/vector_math.h
+++ b/src/common/vector_math.h
@@ -55,10 +55,6 @@ public:
55 T x; 55 T x;
56 T y; 56 T y;
57 57
58 T* AsArray() {
59 return &x;
60 }
61
62 Vec2() = default; 58 Vec2() = default;
63 Vec2(const T& _x, const T& _y) : x(_x), y(_y) {} 59 Vec2(const T& _x, const T& _y) : x(_x), y(_y) {}
64 60
@@ -71,11 +67,6 @@ public:
71 return Vec2<T>(f, f); 67 return Vec2<T>(f, f);
72 } 68 }
73 69
74 void Write(T a[2]) {
75 a[0] = x;
76 a[1] = y;
77 }
78
79 Vec2<decltype(T{} + T{})> operator+(const Vec2& other) const { 70 Vec2<decltype(T{} + T{})> operator+(const Vec2& other) const {
80 return MakeVec(x + other.x, y + other.y); 71 return MakeVec(x + other.x, y + other.y);
81 } 72 }
@@ -205,10 +196,6 @@ public:
205 T y; 196 T y;
206 T z; 197 T z;
207 198
208 T* AsArray() {
209 return &x;
210 }
211
212 Vec3() = default; 199 Vec3() = default;
213 Vec3(const T& _x, const T& _y, const T& _z) : x(_x), y(_y), z(_z) {} 200 Vec3(const T& _x, const T& _y, const T& _z) : x(_x), y(_y), z(_z) {}
214 201
@@ -225,12 +212,6 @@ public:
225 return MakeVec(f, f, f); 212 return MakeVec(f, f, f);
226 } 213 }
227 214
228 void Write(T a[3]) {
229 a[0] = x;
230 a[1] = y;
231 a[2] = z;
232 }
233
234 Vec3<decltype(T{} + T{})> operator+(const Vec3& other) const { 215 Vec3<decltype(T{} + T{})> operator+(const Vec3& other) const {
235 return MakeVec(x + other.x, y + other.y, z + other.z); 216 return MakeVec(x + other.x, y + other.y, z + other.z);
236 } 217 }
@@ -416,10 +397,6 @@ public:
416 T z; 397 T z;
417 T w; 398 T w;
418 399
419 T* AsArray() {
420 return &x;
421 }
422
423 Vec4() = default; 400 Vec4() = default;
424 Vec4(const T& _x, const T& _y, const T& _z, const T& _w) : x(_x), y(_y), z(_z), w(_w) {} 401 Vec4(const T& _x, const T& _y, const T& _z, const T& _w) : x(_x), y(_y), z(_z), w(_w) {}
425 402
@@ -436,13 +413,6 @@ public:
436 return Vec4<T>(f, f, f, f); 413 return Vec4<T>(f, f, f, f);
437 } 414 }
438 415
439 void Write(T a[4]) {
440 a[0] = x;
441 a[1] = y;
442 a[2] = z;
443 a[3] = w;
444 }
445
446 Vec4<decltype(T{} + T{})> operator+(const Vec4& other) const { 416 Vec4<decltype(T{} + T{})> operator+(const Vec4& other) const {
447 return MakeVec(x + other.x, y + other.y, z + other.z, w + other.w); 417 return MakeVec(x + other.x, y + other.y, z + other.z, w + other.w);
448 } 418 }
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 9877b83fe..c1a645460 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -12,6 +12,8 @@ add_library(core STATIC
12 file_sys/errors.h 12 file_sys/errors.h
13 file_sys/filesystem.cpp 13 file_sys/filesystem.cpp
14 file_sys/filesystem.h 14 file_sys/filesystem.h
15 file_sys/partition_filesystem.cpp
16 file_sys/partition_filesystem.h
15 file_sys/path_parser.cpp 17 file_sys/path_parser.cpp
16 file_sys/path_parser.h 18 file_sys/path_parser.h
17 file_sys/program_metadata.cpp 19 file_sys/program_metadata.cpp
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 9f5507a65..ee4af4dcc 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -12,10 +12,13 @@
12#include "core/core.h" 12#include "core/core.h"
13#include "core/core_timing.h" 13#include "core/core_timing.h"
14#include "core/gdbstub/gdbstub.h" 14#include "core/gdbstub/gdbstub.h"
15#include "core/hle/kernel/client_port.h"
15#include "core/hle/kernel/kernel.h" 16#include "core/hle/kernel/kernel.h"
16#include "core/hle/kernel/process.h" 17#include "core/hle/kernel/process.h"
17#include "core/hle/kernel/thread.h" 18#include "core/hle/kernel/thread.h"
18#include "core/hle/service/service.h" 19#include "core/hle/service/service.h"
20#include "core/hle/service/sm/controller.h"
21#include "core/hle/service/sm/sm.h"
19#include "core/hw/hw.h" 22#include "core/hw/hw.h"
20#include "core/loader/loader.h" 23#include "core/loader/loader.h"
21#include "core/memory_setup.h" 24#include "core/memory_setup.h"
@@ -26,6 +29,8 @@ namespace Core {
26 29
27/*static*/ System System::s_instance; 30/*static*/ System System::s_instance;
28 31
32System::~System() = default;
33
29System::ResultStatus System::RunLoop(bool tight_loop) { 34System::ResultStatus System::RunLoop(bool tight_loop) {
30 status = ResultStatus::Success; 35 status = ResultStatus::Success;
31 if (!cpu_core) { 36 if (!cpu_core) {
@@ -167,10 +172,12 @@ System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
167 172
168 telemetry_session = std::make_unique<Core::TelemetrySession>(); 173 telemetry_session = std::make_unique<Core::TelemetrySession>();
169 174
175 service_manager = std::make_shared<Service::SM::ServiceManager>();
176
170 HW::Init(); 177 HW::Init();
171 Kernel::Init(system_mode); 178 Kernel::Init(system_mode);
172 scheduler = std::make_unique<Kernel::Scheduler>(cpu_core.get()); 179 scheduler = std::make_unique<Kernel::Scheduler>(cpu_core.get());
173 Service::Init(); 180 Service::Init(service_manager);
174 GDBStub::Init(); 181 GDBStub::Init();
175 182
176 if (!VideoCore::Init(emu_window)) { 183 if (!VideoCore::Init(emu_window)) {
@@ -200,17 +207,26 @@ void System::Shutdown() {
200 VideoCore::Shutdown(); 207 VideoCore::Shutdown();
201 GDBStub::Shutdown(); 208 GDBStub::Shutdown();
202 Service::Shutdown(); 209 Service::Shutdown();
203 scheduler = nullptr; 210 scheduler.reset();
204 Kernel::Shutdown(); 211 Kernel::Shutdown();
205 HW::Shutdown(); 212 HW::Shutdown();
206 telemetry_session = nullptr; 213 service_manager.reset();
207 gpu_core = nullptr; 214 telemetry_session.reset();
208 cpu_core = nullptr; 215 gpu_core.reset();
216 cpu_core.reset();
209 CoreTiming::Shutdown(); 217 CoreTiming::Shutdown();
210 218
211 app_loader = nullptr; 219 app_loader.reset();
212 220
213 LOG_DEBUG(Core, "Shutdown OK"); 221 LOG_DEBUG(Core, "Shutdown OK");
214} 222}
215 223
224Service::SM::ServiceManager& System::ServiceManager() {
225 return *service_manager;
226}
227
228const Service::SM::ServiceManager& System::ServiceManager() const {
229 return *service_manager;
230}
231
216} // namespace Core 232} // namespace Core
diff --git a/src/core/core.h b/src/core/core.h
index f497dc022..f81cbfb3c 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -19,10 +19,16 @@
19class EmuWindow; 19class EmuWindow;
20class ARM_Interface; 20class ARM_Interface;
21 21
22namespace Service::SM {
23class ServiceManager;
24}
25
22namespace Core { 26namespace Core {
23 27
24class System { 28class System {
25public: 29public:
30 ~System();
31
26 /** 32 /**
27 * Gets the instance of the System singleton class. 33 * Gets the instance of the System singleton class.
28 * @returns Reference to the instance of the System singleton class. 34 * @returns Reference to the instance of the System singleton class.
@@ -137,6 +143,9 @@ public:
137 return *app_loader; 143 return *app_loader;
138 } 144 }
139 145
146 Service::SM::ServiceManager& ServiceManager();
147 const Service::SM::ServiceManager& ServiceManager() const;
148
140 void SetGPUDebugContext(std::shared_ptr<Tegra::DebugContext> context) { 149 void SetGPUDebugContext(std::shared_ptr<Tegra::DebugContext> context) {
141 debug_context = std::move(context); 150 debug_context = std::move(context);
142 } 151 }
@@ -171,6 +180,9 @@ private:
171 /// When true, signals that a reschedule should happen 180 /// When true, signals that a reschedule should happen
172 bool reschedule_pending{}; 181 bool reschedule_pending{};
173 182
183 /// Service manager
184 std::shared_ptr<Service::SM::ServiceManager> service_manager;
185
174 /// Telemetry session for this emulation session 186 /// Telemetry session for this emulation session
175 std::unique_ptr<Core::TelemetrySession> telemetry_session; 187 std::unique_ptr<Core::TelemetrySession> telemetry_session;
176 188
diff --git a/src/core/file_sys/disk_filesystem.cpp b/src/core/file_sys/disk_filesystem.cpp
index 4235f3935..ca1323873 100644
--- a/src/core/file_sys/disk_filesystem.cpp
+++ b/src/core/file_sys/disk_filesystem.cpp
@@ -57,10 +57,14 @@ ResultVal<std::unique_ptr<StorageBackend>> Disk_FileSystem::OpenFile(const std::
57 std::make_unique<Disk_Storage>(std::move(file))); 57 std::make_unique<Disk_Storage>(std::move(file)));
58} 58}
59 59
60ResultCode Disk_FileSystem::DeleteFile(const Path& path) const { 60ResultCode Disk_FileSystem::DeleteFile(const std::string& path) const {
61 LOG_WARNING(Service_FS, "(STUBBED) called"); 61 if (!FileUtil::Exists(path)) {
62 // TODO(bunnei): Use correct error code 62 return ERROR_PATH_NOT_FOUND;
63 return ResultCode(-1); 63 }
64
65 FileUtil::Delete(path);
66
67 return RESULT_SUCCESS;
64} 68}
65 69
66ResultCode Disk_FileSystem::RenameFile(const Path& src_path, const Path& dest_path) const { 70ResultCode Disk_FileSystem::RenameFile(const Path& src_path, const Path& dest_path) const {
@@ -179,7 +183,7 @@ bool Disk_Storage::SetSize(const u64 size) const {
179 return true; 183 return true;
180} 184}
181 185
182Disk_Directory::Disk_Directory(const std::string& path) : directory() { 186Disk_Directory::Disk_Directory(const std::string& path) {
183 unsigned size = FileUtil::ScanDirectoryTree(path, directory); 187 unsigned size = FileUtil::ScanDirectoryTree(path, directory);
184 directory.size = size; 188 directory.size = size;
185 directory.isDirectory = true; 189 directory.isDirectory = true;
diff --git a/src/core/file_sys/disk_filesystem.h b/src/core/file_sys/disk_filesystem.h
index 742d7db1a..8f9e1145a 100644
--- a/src/core/file_sys/disk_filesystem.h
+++ b/src/core/file_sys/disk_filesystem.h
@@ -25,7 +25,7 @@ public:
25 25
26 ResultVal<std::unique_ptr<StorageBackend>> OpenFile(const std::string& path, 26 ResultVal<std::unique_ptr<StorageBackend>> OpenFile(const std::string& path,
27 Mode mode) const override; 27 Mode mode) const override;
28 ResultCode DeleteFile(const Path& path) const override; 28 ResultCode DeleteFile(const std::string& path) const override;
29 ResultCode RenameFile(const Path& src_path, const Path& dest_path) const override; 29 ResultCode RenameFile(const Path& src_path, const Path& dest_path) const override;
30 ResultCode DeleteDirectory(const Path& path) const override; 30 ResultCode DeleteDirectory(const Path& path) const override;
31 ResultCode DeleteDirectoryRecursively(const Path& path) const override; 31 ResultCode DeleteDirectoryRecursively(const Path& path) const override;
@@ -43,7 +43,7 @@ protected:
43 43
44class Disk_Storage : public StorageBackend { 44class Disk_Storage : public StorageBackend {
45public: 45public:
46 Disk_Storage(std::shared_ptr<FileUtil::IOFile> file) : file(std::move(file)) {} 46 explicit Disk_Storage(std::shared_ptr<FileUtil::IOFile> file) : file(std::move(file)) {}
47 47
48 ResultVal<size_t> Read(u64 offset, size_t length, u8* buffer) const override; 48 ResultVal<size_t> Read(u64 offset, size_t length, u8* buffer) const override;
49 ResultVal<size_t> Write(u64 offset, size_t length, bool flush, const u8* buffer) const override; 49 ResultVal<size_t> Write(u64 offset, size_t length, bool flush, const u8* buffer) const override;
@@ -60,7 +60,7 @@ private:
60 60
61class Disk_Directory : public DirectoryBackend { 61class Disk_Directory : public DirectoryBackend {
62public: 62public:
63 Disk_Directory(const std::string& path); 63 explicit Disk_Directory(const std::string& path);
64 64
65 ~Disk_Directory() override { 65 ~Disk_Directory() override {
66 Close(); 66 Close();
@@ -74,7 +74,6 @@ public:
74 } 74 }
75 75
76protected: 76protected:
77 u32 total_entries_in_directory;
78 FileUtil::FSTEntry directory; 77 FileUtil::FSTEntry directory;
79 78
80 // We need to remember the last entry we returned, so a subsequent call to Read will continue 79 // We need to remember the last entry we returned, so a subsequent call to Read will continue
diff --git a/src/core/file_sys/filesystem.h b/src/core/file_sys/filesystem.h
index 399427ca2..beefcfdb2 100644
--- a/src/core/file_sys/filesystem.h
+++ b/src/core/file_sys/filesystem.h
@@ -97,7 +97,7 @@ public:
97 * @param path Path relative to the archive 97 * @param path Path relative to the archive
98 * @return Result of the operation 98 * @return Result of the operation
99 */ 99 */
100 virtual ResultCode DeleteFile(const Path& path) const = 0; 100 virtual ResultCode DeleteFile(const std::string& path) const = 0;
101 101
102 /** 102 /**
103 * Create a directory specified by its path 103 * Create a directory specified by its path
diff --git a/src/core/file_sys/partition_filesystem.cpp b/src/core/file_sys/partition_filesystem.cpp
new file mode 100644
index 000000000..4a58a9291
--- /dev/null
+++ b/src/core/file_sys/partition_filesystem.cpp
@@ -0,0 +1,125 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <cinttypes>
6#include <utility>
7#include "common/file_util.h"
8#include "common/logging/log.h"
9#include "core/file_sys/partition_filesystem.h"
10#include "core/loader/loader.h"
11
12namespace FileSys {
13
14Loader::ResultStatus PartitionFilesystem::Load(const std::string& file_path, size_t offset) {
15 FileUtil::IOFile file(file_path, "rb");
16 if (!file.IsOpen())
17 return Loader::ResultStatus::Error;
18
19 // At least be as large as the header
20 if (file.GetSize() < sizeof(Header))
21 return Loader::ResultStatus::Error;
22
23 // For cartridges, HFSs can get very large, so we need to calculate the size up to
24 // the actual content itself instead of just blindly reading in the entire file.
25 Header pfs_header;
26 if (!file.ReadBytes(&pfs_header, sizeof(Header)))
27 return Loader::ResultStatus::Error;
28
29 bool is_hfs = (memcmp(pfs_header.magic.data(), "HFS", 3) == 0);
30 size_t entry_size = is_hfs ? sizeof(HFSEntry) : sizeof(PFSEntry);
31 size_t metadata_size =
32 sizeof(Header) + (pfs_header.num_entries * entry_size) + pfs_header.strtab_size;
33
34 // Actually read in now...
35 file.Seek(offset, SEEK_SET);
36 std::vector<u8> file_data(metadata_size);
37
38 if (!file.ReadBytes(file_data.data(), metadata_size))
39 return Loader::ResultStatus::Error;
40
41 Loader::ResultStatus result = Load(file_data);
42 if (result != Loader::ResultStatus::Success)
43 LOG_ERROR(Service_FS, "Failed to load PFS from file %s!", file_path.c_str());
44
45 return result;
46}
47
48Loader::ResultStatus PartitionFilesystem::Load(const std::vector<u8>& file_data, size_t offset) {
49 size_t total_size = file_data.size() - offset;
50 if (total_size < sizeof(Header))
51 return Loader::ResultStatus::Error;
52
53 memcpy(&pfs_header, &file_data[offset], sizeof(Header));
54 is_hfs = (memcmp(pfs_header.magic.data(), "HFS", 3) == 0);
55
56 size_t entries_offset = offset + sizeof(Header);
57 size_t entry_size = is_hfs ? sizeof(HFSEntry) : sizeof(PFSEntry);
58 size_t strtab_offset = entries_offset + (pfs_header.num_entries * entry_size);
59 for (u16 i = 0; i < pfs_header.num_entries; i++) {
60 FileEntry entry;
61
62 memcpy(&entry.fs_entry, &file_data[entries_offset + (i * entry_size)], sizeof(FSEntry));
63 entry.name = std::string(reinterpret_cast<const char*>(
64 &file_data[strtab_offset + entry.fs_entry.strtab_offset]));
65 pfs_entries.push_back(std::move(entry));
66 }
67
68 content_offset = strtab_offset + pfs_header.strtab_size;
69
70 return Loader::ResultStatus::Success;
71}
72
73u32 PartitionFilesystem::GetNumEntries() const {
74 return pfs_header.num_entries;
75}
76
77u64 PartitionFilesystem::GetEntryOffset(int index) const {
78 if (index > GetNumEntries())
79 return 0;
80
81 return content_offset + pfs_entries[index].fs_entry.offset;
82}
83
84u64 PartitionFilesystem::GetEntrySize(int index) const {
85 if (index > GetNumEntries())
86 return 0;
87
88 return pfs_entries[index].fs_entry.size;
89}
90
91std::string PartitionFilesystem::GetEntryName(int index) const {
92 if (index > GetNumEntries())
93 return "";
94
95 return pfs_entries[index].name;
96}
97
98u64 PartitionFilesystem::GetFileOffset(const std::string& name) const {
99 for (u32 i = 0; i < pfs_header.num_entries; i++) {
100 if (pfs_entries[i].name == name)
101 return content_offset + pfs_entries[i].fs_entry.offset;
102 }
103
104 return 0;
105}
106
107u64 PartitionFilesystem::GetFileSize(const std::string& name) const {
108 for (u32 i = 0; i < pfs_header.num_entries; i++) {
109 if (pfs_entries[i].name == name)
110 return pfs_entries[i].fs_entry.size;
111 }
112
113 return 0;
114}
115
116void PartitionFilesystem::Print() const {
117 NGLOG_DEBUG(Service_FS, "Magic: {:.4}", pfs_header.magic.data());
118 NGLOG_DEBUG(Service_FS, "Files: {}", pfs_header.num_entries);
119 for (u32 i = 0; i < pfs_header.num_entries; i++) {
120 NGLOG_DEBUG(Service_FS, " > File {}: {} (0x{:X} bytes, at 0x{:X})", i,
121 pfs_entries[i].name.c_str(), pfs_entries[i].fs_entry.size,
122 GetFileOffset(pfs_entries[i].name));
123 }
124}
125} // namespace FileSys
diff --git a/src/core/file_sys/partition_filesystem.h b/src/core/file_sys/partition_filesystem.h
new file mode 100644
index 000000000..573c90057
--- /dev/null
+++ b/src/core/file_sys/partition_filesystem.h
@@ -0,0 +1,87 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <array>
8#include <string>
9#include <vector>
10#include "common/common_funcs.h"
11#include "common/common_types.h"
12#include "common/swap.h"
13
14namespace Loader {
15enum class ResultStatus;
16}
17
18namespace FileSys {
19
20/**
21 * Helper which implements an interface to parse PFS/HFS filesystems.
22 * Data can either be loaded from a file path or data with an offset into it.
23 */
24class PartitionFilesystem {
25public:
26 Loader::ResultStatus Load(const std::string& file_path, size_t offset = 0);
27 Loader::ResultStatus Load(const std::vector<u8>& file_data, size_t offset = 0);
28
29 u32 GetNumEntries() const;
30 u64 GetEntryOffset(int index) const;
31 u64 GetEntrySize(int index) const;
32 std::string GetEntryName(int index) const;
33 u64 GetFileOffset(const std::string& name) const;
34 u64 GetFileSize(const std::string& name) const;
35
36 void Print() const;
37
38private:
39 struct Header {
40 std::array<char, 4> magic;
41 u32_le num_entries;
42 u32_le strtab_size;
43 INSERT_PADDING_BYTES(0x4);
44 };
45
46 static_assert(sizeof(Header) == 0x10, "PFS/HFS header structure size is wrong");
47
48#pragma pack(push, 1)
49 struct FSEntry {
50 u64_le offset;
51 u64_le size;
52 u32_le strtab_offset;
53 };
54
55 static_assert(sizeof(FSEntry) == 0x14, "FS entry structure size is wrong");
56
57 struct PFSEntry {
58 FSEntry fs_entry;
59 INSERT_PADDING_BYTES(0x4);
60 };
61
62 static_assert(sizeof(PFSEntry) == 0x18, "PFS entry structure size is wrong");
63
64 struct HFSEntry {
65 FSEntry fs_entry;
66 u32_le hash_region_size;
67 INSERT_PADDING_BYTES(0x8);
68 std::array<char, 0x20> hash;
69 };
70
71 static_assert(sizeof(HFSEntry) == 0x40, "HFS entry structure size is wrong");
72
73#pragma pack(pop)
74
75 struct FileEntry {
76 FSEntry fs_entry;
77 std::string name;
78 };
79
80 Header pfs_header;
81 bool is_hfs;
82 size_t content_offset;
83
84 std::vector<FileEntry> pfs_entries;
85};
86
87} // namespace FileSys
diff --git a/src/core/file_sys/romfs_filesystem.cpp b/src/core/file_sys/romfs_filesystem.cpp
index 0c6cc3157..3d77e2d5f 100644
--- a/src/core/file_sys/romfs_filesystem.cpp
+++ b/src/core/file_sys/romfs_filesystem.cpp
@@ -20,7 +20,7 @@ ResultVal<std::unique_ptr<StorageBackend>> RomFS_FileSystem::OpenFile(const std:
20 std::make_unique<RomFS_Storage>(romfs_file, data_offset, data_size)); 20 std::make_unique<RomFS_Storage>(romfs_file, data_offset, data_size));
21} 21}
22 22
23ResultCode RomFS_FileSystem::DeleteFile(const Path& path) const { 23ResultCode RomFS_FileSystem::DeleteFile(const std::string& path) const {
24 LOG_CRITICAL(Service_FS, "Attempted to delete a file from an ROMFS archive (%s).", 24 LOG_CRITICAL(Service_FS, "Attempted to delete a file from an ROMFS archive (%s).",
25 GetName().c_str()); 25 GetName().c_str());
26 // TODO(bunnei): Use correct error code 26 // TODO(bunnei): Use correct error code
diff --git a/src/core/file_sys/romfs_filesystem.h b/src/core/file_sys/romfs_filesystem.h
index 3f94c04d0..1b5cac409 100644
--- a/src/core/file_sys/romfs_filesystem.h
+++ b/src/core/file_sys/romfs_filesystem.h
@@ -31,7 +31,7 @@ public:
31 31
32 ResultVal<std::unique_ptr<StorageBackend>> OpenFile(const std::string& path, 32 ResultVal<std::unique_ptr<StorageBackend>> OpenFile(const std::string& path,
33 Mode mode) const override; 33 Mode mode) const override;
34 ResultCode DeleteFile(const Path& path) const override; 34 ResultCode DeleteFile(const std::string& path) const override;
35 ResultCode RenameFile(const Path& src_path, const Path& dest_path) const override; 35 ResultCode RenameFile(const Path& src_path, const Path& dest_path) const override;
36 ResultCode DeleteDirectory(const Path& path) const override; 36 ResultCode DeleteDirectory(const Path& path) const override;
37 ResultCode DeleteDirectoryRecursively(const Path& path) const override; 37 ResultCode DeleteDirectoryRecursively(const Path& path) const override;
diff --git a/src/core/hle/kernel/resource_limit.cpp b/src/core/hle/kernel/resource_limit.cpp
index 0149a3ed6..88ca8ad7e 100644
--- a/src/core/hle/kernel/resource_limit.cpp
+++ b/src/core/hle/kernel/resource_limit.cpp
@@ -34,57 +34,57 @@ SharedPtr<ResourceLimit> ResourceLimit::GetForCategory(ResourceLimitCategory cat
34 } 34 }
35} 35}
36 36
37s32 ResourceLimit::GetCurrentResourceValue(u32 resource) const { 37s32 ResourceLimit::GetCurrentResourceValue(ResourceType resource) const {
38 switch (resource) { 38 switch (resource) {
39 case COMMIT: 39 case ResourceType::Commit:
40 return current_commit; 40 return current_commit;
41 case THREAD: 41 case ResourceType::Thread:
42 return current_threads; 42 return current_threads;
43 case EVENT: 43 case ResourceType::Event:
44 return current_events; 44 return current_events;
45 case MUTEX: 45 case ResourceType::Mutex:
46 return current_mutexes; 46 return current_mutexes;
47 case SEMAPHORE: 47 case ResourceType::Semaphore:
48 return current_semaphores; 48 return current_semaphores;
49 case TIMER: 49 case ResourceType::Timer:
50 return current_timers; 50 return current_timers;
51 case SHARED_MEMORY: 51 case ResourceType::SharedMemory:
52 return current_shared_mems; 52 return current_shared_mems;
53 case ADDRESS_ARBITER: 53 case ResourceType::AddressArbiter:
54 return current_address_arbiters; 54 return current_address_arbiters;
55 case CPU_TIME: 55 case ResourceType::CPUTime:
56 return current_cpu_time; 56 return current_cpu_time;
57 default: 57 default:
58 LOG_ERROR(Kernel, "Unknown resource type=%08X", resource); 58 LOG_ERROR(Kernel, "Unknown resource type=%08X", static_cast<u32>(resource));
59 UNIMPLEMENTED(); 59 UNIMPLEMENTED();
60 return 0; 60 return 0;
61 } 61 }
62} 62}
63 63
64u32 ResourceLimit::GetMaxResourceValue(u32 resource) const { 64u32 ResourceLimit::GetMaxResourceValue(ResourceType resource) const {
65 switch (resource) { 65 switch (resource) {
66 case PRIORITY: 66 case ResourceType::Priority:
67 return max_priority; 67 return max_priority;
68 case COMMIT: 68 case ResourceType::Commit:
69 return max_commit; 69 return max_commit;
70 case THREAD: 70 case ResourceType::Thread:
71 return max_threads; 71 return max_threads;
72 case EVENT: 72 case ResourceType::Event:
73 return max_events; 73 return max_events;
74 case MUTEX: 74 case ResourceType::Mutex:
75 return max_mutexes; 75 return max_mutexes;
76 case SEMAPHORE: 76 case ResourceType::Semaphore:
77 return max_semaphores; 77 return max_semaphores;
78 case TIMER: 78 case ResourceType::Timer:
79 return max_timers; 79 return max_timers;
80 case SHARED_MEMORY: 80 case ResourceType::SharedMemory:
81 return max_shared_mems; 81 return max_shared_mems;
82 case ADDRESS_ARBITER: 82 case ResourceType::AddressArbiter:
83 return max_address_arbiters; 83 return max_address_arbiters;
84 case CPU_TIME: 84 case ResourceType::CPUTime:
85 return max_cpu_time; 85 return max_cpu_time;
86 default: 86 default:
87 LOG_ERROR(Kernel, "Unknown resource type=%08X", resource); 87 LOG_ERROR(Kernel, "Unknown resource type=%08X", static_cast<u32>(resource));
88 UNIMPLEMENTED(); 88 UNIMPLEMENTED();
89 return 0; 89 return 0;
90 } 90 }
diff --git a/src/core/hle/kernel/resource_limit.h b/src/core/hle/kernel/resource_limit.h
index 1a0ca11f1..cc689a27a 100644
--- a/src/core/hle/kernel/resource_limit.h
+++ b/src/core/hle/kernel/resource_limit.h
@@ -16,17 +16,17 @@ enum class ResourceLimitCategory : u8 {
16 OTHER = 3 16 OTHER = 3
17}; 17};
18 18
19enum ResourceTypes { 19enum class ResourceType {
20 PRIORITY = 0, 20 Priority = 0,
21 COMMIT = 1, 21 Commit = 1,
22 THREAD = 2, 22 Thread = 2,
23 EVENT = 3, 23 Event = 3,
24 MUTEX = 4, 24 Mutex = 4,
25 SEMAPHORE = 5, 25 Semaphore = 5,
26 TIMER = 6, 26 Timer = 6,
27 SHARED_MEMORY = 7, 27 SharedMemory = 7,
28 ADDRESS_ARBITER = 8, 28 AddressArbiter = 8,
29 CPU_TIME = 9, 29 CPUTime = 9,
30}; 30};
31 31
32class ResourceLimit final : public Object { 32class ResourceLimit final : public Object {
@@ -60,14 +60,14 @@ public:
60 * @param resource Requested resource type 60 * @param resource Requested resource type
61 * @returns The current value of the resource type 61 * @returns The current value of the resource type
62 */ 62 */
63 s32 GetCurrentResourceValue(u32 resource) const; 63 s32 GetCurrentResourceValue(ResourceType resource) const;
64 64
65 /** 65 /**
66 * Gets the max value for the specified resource. 66 * Gets the max value for the specified resource.
67 * @param resource Requested resource type 67 * @param resource Requested resource type
68 * @returns The max value of the resource type 68 * @returns The max value of the resource type
69 */ 69 */
70 u32 GetMaxResourceValue(u32 resource) const; 70 u32 GetMaxResourceValue(ResourceType resource) const;
71 71
72 /// Name of resource limit object. 72 /// Name of resource limit object.
73 std::string name; 73 std::string name;
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 36ea23cd9..633740992 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -4,6 +4,7 @@
4 4
5#include <algorithm> 5#include <algorithm>
6#include <cinttypes> 6#include <cinttypes>
7#include <iterator>
7 8
8#include "common/logging/log.h" 9#include "common/logging/log.h"
9#include "common/microprofile.h" 10#include "common/microprofile.h"
@@ -406,7 +407,7 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) {
406 // Note: The kernel uses the current process's resource limit instead of 407 // Note: The kernel uses the current process's resource limit instead of
407 // the one from the thread owner's resource limit. 408 // the one from the thread owner's resource limit.
408 SharedPtr<ResourceLimit>& resource_limit = Core::CurrentProcess()->resource_limit; 409 SharedPtr<ResourceLimit>& resource_limit = Core::CurrentProcess()->resource_limit;
409 if (resource_limit->GetMaxResourceValue(ResourceTypes::PRIORITY) > priority) { 410 if (resource_limit->GetMaxResourceValue(ResourceType::Priority) > priority) {
410 return ERR_NOT_AUTHORIZED; 411 return ERR_NOT_AUTHORIZED;
411 } 412 }
412 413
@@ -540,7 +541,7 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
540 } 541 }
541 542
542 SharedPtr<ResourceLimit>& resource_limit = Core::CurrentProcess()->resource_limit; 543 SharedPtr<ResourceLimit>& resource_limit = Core::CurrentProcess()->resource_limit;
543 if (resource_limit->GetMaxResourceValue(ResourceTypes::PRIORITY) > priority) { 544 if (resource_limit->GetMaxResourceValue(ResourceType::Priority) > priority) {
544 return ERR_NOT_AUTHORIZED; 545 return ERR_NOT_AUTHORIZED;
545 } 546 }
546 547
@@ -861,14 +862,14 @@ static const FunctionDef SVC_Table[] = {
861 {0x2B, nullptr, "FlushDataCache"}, 862 {0x2B, nullptr, "FlushDataCache"},
862 {0x2C, nullptr, "MapPhysicalMemory"}, 863 {0x2C, nullptr, "MapPhysicalMemory"},
863 {0x2D, nullptr, "UnmapPhysicalMemory"}, 864 {0x2D, nullptr, "UnmapPhysicalMemory"},
864 {0x2E, nullptr, "Unknown"}, 865 {0x2E, nullptr, "GetNextThreadInfo"},
865 {0x2F, nullptr, "GetLastThreadInfo"}, 866 {0x2F, nullptr, "GetLastThreadInfo"},
866 {0x30, nullptr, "GetResourceLimitLimitValue"}, 867 {0x30, nullptr, "GetResourceLimitLimitValue"},
867 {0x31, nullptr, "GetResourceLimitCurrentValue"}, 868 {0x31, nullptr, "GetResourceLimitCurrentValue"},
868 {0x32, SvcWrap<SetThreadActivity>, "SetThreadActivity"}, 869 {0x32, SvcWrap<SetThreadActivity>, "SetThreadActivity"},
869 {0x33, SvcWrap<GetThreadContext>, "GetThreadContext"}, 870 {0x33, SvcWrap<GetThreadContext>, "GetThreadContext"},
870 {0x34, nullptr, "Unknown"}, 871 {0x34, nullptr, "WaitForAddress"},
871 {0x35, nullptr, "Unknown"}, 872 {0x35, nullptr, "SignalToAddress"},
872 {0x36, nullptr, "Unknown"}, 873 {0x36, nullptr, "Unknown"},
873 {0x37, nullptr, "Unknown"}, 874 {0x37, nullptr, "Unknown"},
874 {0x38, nullptr, "Unknown"}, 875 {0x38, nullptr, "Unknown"},
@@ -876,7 +877,7 @@ static const FunctionDef SVC_Table[] = {
876 {0x3A, nullptr, "Unknown"}, 877 {0x3A, nullptr, "Unknown"},
877 {0x3B, nullptr, "Unknown"}, 878 {0x3B, nullptr, "Unknown"},
878 {0x3C, nullptr, "DumpInfo"}, 879 {0x3C, nullptr, "DumpInfo"},
879 {0x3D, nullptr, "Unknown"}, 880 {0x3D, nullptr, "DumpInfoNew"},
880 {0x3E, nullptr, "Unknown"}, 881 {0x3E, nullptr, "Unknown"},
881 {0x3F, nullptr, "Unknown"}, 882 {0x3F, nullptr, "Unknown"},
882 {0x40, nullptr, "CreateSession"}, 883 {0x40, nullptr, "CreateSession"},
@@ -887,9 +888,9 @@ static const FunctionDef SVC_Table[] = {
887 {0x45, nullptr, "CreateEvent"}, 888 {0x45, nullptr, "CreateEvent"},
888 {0x46, nullptr, "Unknown"}, 889 {0x46, nullptr, "Unknown"},
889 {0x47, nullptr, "Unknown"}, 890 {0x47, nullptr, "Unknown"},
890 {0x48, nullptr, "Unknown"}, 891 {0x48, nullptr, "AllocateUnsafeMemory"},
891 {0x49, nullptr, "Unknown"}, 892 {0x49, nullptr, "FreeUnsafeMemory"},
892 {0x4A, nullptr, "Unknown"}, 893 {0x4A, nullptr, "SetUnsafeAllocationLimit"},
893 {0x4B, nullptr, "CreateJitMemory"}, 894 {0x4B, nullptr, "CreateJitMemory"},
894 {0x4C, nullptr, "MapJitMemory"}, 895 {0x4C, nullptr, "MapJitMemory"},
895 {0x4D, nullptr, "SleepSystem"}, 896 {0x4D, nullptr, "SleepSystem"},
@@ -926,7 +927,7 @@ static const FunctionDef SVC_Table[] = {
926 {0x6C, nullptr, "SetHardwareBreakPoint"}, 927 {0x6C, nullptr, "SetHardwareBreakPoint"},
927 {0x6D, nullptr, "GetDebugThreadParam"}, 928 {0x6D, nullptr, "GetDebugThreadParam"},
928 {0x6E, nullptr, "Unknown"}, 929 {0x6E, nullptr, "Unknown"},
929 {0x6F, nullptr, "Unknown"}, 930 {0x6F, nullptr, "GetMemoryInfo"},
930 {0x70, nullptr, "CreatePort"}, 931 {0x70, nullptr, "CreatePort"},
931 {0x71, nullptr, "ManageNamedPort"}, 932 {0x71, nullptr, "ManageNamedPort"},
932 {0x72, nullptr, "ConnectToPort"}, 933 {0x72, nullptr, "ConnectToPort"},
@@ -946,7 +947,7 @@ static const FunctionDef SVC_Table[] = {
946}; 947};
947 948
948static const FunctionDef* GetSVCInfo(u32 func_num) { 949static const FunctionDef* GetSVCInfo(u32 func_num) {
949 if (func_num >= ARRAY_SIZE(SVC_Table)) { 950 if (func_num >= std::size(SVC_Table)) {
950 LOG_ERROR(Kernel_SVC, "unknown svc=0x%02X", func_num); 951 LOG_ERROR(Kernel_SVC, "unknown svc=0x%02X", func_num);
951 return nullptr; 952 return nullptr;
952 } 953 }
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp
index 1c2f873aa..acd65ee68 100644
--- a/src/core/hle/kernel/vm_manager.cpp
+++ b/src/core/hle/kernel/vm_manager.cpp
@@ -380,7 +380,7 @@ void VMManager::UpdatePageTableForVMA(const VirtualMemoryArea& vma) {
380 380
381u64 VMManager::GetTotalMemoryUsage() { 381u64 VMManager::GetTotalMemoryUsage() {
382 LOG_WARNING(Kernel, "(STUBBED) called"); 382 LOG_WARNING(Kernel, "(STUBBED) called");
383 return 0xBE000000; 383 return 0xF8000000;
384} 384}
385 385
386u64 VMManager::GetTotalHeapUsage() { 386u64 VMManager::GetTotalHeapUsage() {
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp
index cfb6e05a5..6bafb2dce 100644
--- a/src/core/hle/service/acc/acc.cpp
+++ b/src/core/hle/service/acc/acc.cpp
@@ -10,8 +10,7 @@
10#include "core/hle/service/acc/acc_u0.h" 10#include "core/hle/service/acc/acc_u0.h"
11#include "core/hle/service/acc/acc_u1.h" 11#include "core/hle/service/acc/acc_u1.h"
12 12
13namespace Service { 13namespace Service::Account {
14namespace Account {
15 14
16// TODO: RE this structure 15// TODO: RE this structure
17struct UserData { 16struct UserData {
@@ -38,7 +37,10 @@ class IProfile final : public ServiceFramework<IProfile> {
38public: 37public:
39 IProfile() : ServiceFramework("IProfile") { 38 IProfile() : ServiceFramework("IProfile") {
40 static const FunctionInfo functions[] = { 39 static const FunctionInfo functions[] = {
40 {0, nullptr, "Get"},
41 {1, &IProfile::GetBase, "GetBase"}, 41 {1, &IProfile::GetBase, "GetBase"},
42 {10, nullptr, "GetImageSize"},
43 {11, nullptr, "LoadImage"},
42 }; 44 };
43 RegisterHandlers(functions); 45 RegisterHandlers(functions);
44 } 46 }
@@ -59,6 +61,11 @@ public:
59 static const FunctionInfo functions[] = { 61 static const FunctionInfo functions[] = {
60 {0, &IManagerForApplication::CheckAvailability, "CheckAvailability"}, 62 {0, &IManagerForApplication::CheckAvailability, "CheckAvailability"},
61 {1, &IManagerForApplication::GetAccountId, "GetAccountId"}, 63 {1, &IManagerForApplication::GetAccountId, "GetAccountId"},
64 {2, nullptr, "EnsureIdTokenCacheAsync"},
65 {3, nullptr, "LoadIdTokenCache"},
66 {130, nullptr, "GetNintendoAccountUserResourceCacheForApplication"},
67 {150, nullptr, "CreateAuthorizationRequest"},
68 {160, nullptr, "StoreOpenContext"},
62 }; 69 };
63 RegisterHandlers(functions); 70 RegisterHandlers(functions);
64 } 71 }
@@ -140,5 +147,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
140 std::make_shared<ACC_U1>(module)->InstallAsService(service_manager); 147 std::make_shared<ACC_U1>(module)->InstallAsService(service_manager);
141} 148}
142 149
143} // namespace Account 150} // namespace Service::Account
144} // namespace Service
diff --git a/src/core/hle/service/acc/acc.h b/src/core/hle/service/acc/acc.h
index 2d2f57b7d..58f8d260c 100644
--- a/src/core/hle/service/acc/acc.h
+++ b/src/core/hle/service/acc/acc.h
@@ -6,8 +6,7 @@
6 6
7#include "core/hle/service/service.h" 7#include "core/hle/service/service.h"
8 8
9namespace Service { 9namespace Service::Account {
10namespace Account {
11 10
12class Module final { 11class Module final {
13public: 12public:
@@ -31,5 +30,4 @@ public:
31/// Registers all ACC services with the specified service manager. 30/// Registers all ACC services with the specified service manager.
32void InstallInterfaces(SM::ServiceManager& service_manager); 31void InstallInterfaces(SM::ServiceManager& service_manager);
33 32
34} // namespace Account 33} // namespace Service::Account
35} // namespace Service
diff --git a/src/core/hle/service/acc/acc_aa.cpp b/src/core/hle/service/acc/acc_aa.cpp
index 76deaa07f..280b3e464 100644
--- a/src/core/hle/service/acc/acc_aa.cpp
+++ b/src/core/hle/service/acc/acc_aa.cpp
@@ -4,8 +4,7 @@
4 4
5#include "core/hle/service/acc/acc_aa.h" 5#include "core/hle/service/acc/acc_aa.h"
6 6
7namespace Service { 7namespace Service::Account {
8namespace Account {
9 8
10ACC_AA::ACC_AA(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:aa") { 9ACC_AA::ACC_AA(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:aa") {
11 static const FunctionInfo functions[] = { 10 static const FunctionInfo functions[] = {
@@ -18,5 +17,4 @@ ACC_AA::ACC_AA(std::shared_ptr<Module> module) : Module::Interface(std::move(mod
18 RegisterHandlers(functions); 17 RegisterHandlers(functions);
19} 18}
20 19
21} // namespace Account 20} // namespace Service::Account
22} // namespace Service
diff --git a/src/core/hle/service/acc/acc_aa.h b/src/core/hle/service/acc/acc_aa.h
index 5069c6890..796f7ef85 100644
--- a/src/core/hle/service/acc/acc_aa.h
+++ b/src/core/hle/service/acc/acc_aa.h
@@ -6,13 +6,11 @@
6 6
7#include "core/hle/service/acc/acc.h" 7#include "core/hle/service/acc/acc.h"
8 8
9namespace Service { 9namespace Service::Account {
10namespace Account {
11 10
12class ACC_AA final : public Module::Interface { 11class ACC_AA final : public Module::Interface {
13public: 12public:
14 explicit ACC_AA(std::shared_ptr<Module> module); 13 explicit ACC_AA(std::shared_ptr<Module> module);
15}; 14};
16 15
17} // namespace Account 16} // namespace Service::Account
18} // namespace Service
diff --git a/src/core/hle/service/acc/acc_su.cpp b/src/core/hle/service/acc/acc_su.cpp
index 538f9d9b1..9ffb40b22 100644
--- a/src/core/hle/service/acc/acc_su.cpp
+++ b/src/core/hle/service/acc/acc_su.cpp
@@ -4,8 +4,7 @@
4 4
5#include "core/hle/service/acc/acc_su.h" 5#include "core/hle/service/acc/acc_su.h"
6 6
7namespace Service { 7namespace Service::Account {
8namespace Account {
9 8
10ACC_SU::ACC_SU(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:su") { 9ACC_SU::ACC_SU(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:su") {
11 static const FunctionInfo functions[] = { 10 static const FunctionInfo functions[] = {
@@ -51,5 +50,4 @@ ACC_SU::ACC_SU(std::shared_ptr<Module> module) : Module::Interface(std::move(mod
51 RegisterHandlers(functions); 50 RegisterHandlers(functions);
52} 51}
53 52
54} // namespace Account 53} // namespace Service::Account
55} // namespace Service
diff --git a/src/core/hle/service/acc/acc_u0.cpp b/src/core/hle/service/acc/acc_u0.cpp
index 7b9c667ef..44e21ac09 100644
--- a/src/core/hle/service/acc/acc_u0.cpp
+++ b/src/core/hle/service/acc/acc_u0.cpp
@@ -4,8 +4,7 @@
4 4
5#include "core/hle/service/acc/acc_u0.h" 5#include "core/hle/service/acc/acc_u0.h"
6 6
7namespace Service { 7namespace Service::Account {
8namespace Account {
9 8
10ACC_U0::ACC_U0(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:u0") { 9ACC_U0::ACC_U0(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:u0") {
11 static const FunctionInfo functions[] = { 10 static const FunctionInfo functions[] = {
@@ -31,5 +30,4 @@ ACC_U0::ACC_U0(std::shared_ptr<Module> module) : Module::Interface(std::move(mod
31 RegisterHandlers(functions); 30 RegisterHandlers(functions);
32} 31}
33 32
34} // namespace Account 33} // namespace Service::Account
35} // namespace Service
diff --git a/src/core/hle/service/acc/acc_u0.h b/src/core/hle/service/acc/acc_u0.h
index d4f36e172..6ded596b3 100644
--- a/src/core/hle/service/acc/acc_u0.h
+++ b/src/core/hle/service/acc/acc_u0.h
@@ -6,13 +6,11 @@
6 6
7#include "core/hle/service/acc/acc.h" 7#include "core/hle/service/acc/acc.h"
8 8
9namespace Service { 9namespace Service::Account {
10namespace Account {
11 10
12class ACC_U0 final : public Module::Interface { 11class ACC_U0 final : public Module::Interface {
13public: 12public:
14 explicit ACC_U0(std::shared_ptr<Module> module); 13 explicit ACC_U0(std::shared_ptr<Module> module);
15}; 14};
16 15
17} // namespace Account 16} // namespace Service::Account
18} // namespace Service
diff --git a/src/core/hle/service/acc/acc_u1.cpp b/src/core/hle/service/acc/acc_u1.cpp
index dea353554..d101d4e0d 100644
--- a/src/core/hle/service/acc/acc_u1.cpp
+++ b/src/core/hle/service/acc/acc_u1.cpp
@@ -4,8 +4,7 @@
4 4
5#include "core/hle/service/acc/acc_u1.h" 5#include "core/hle/service/acc/acc_u1.h"
6 6
7namespace Service { 7namespace Service::Account {
8namespace Account {
9 8
10ACC_U1::ACC_U1(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:u1") { 9ACC_U1::ACC_U1(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:u1") {
11 static const FunctionInfo functions[] = { 10 static const FunctionInfo functions[] = {
@@ -38,5 +37,4 @@ ACC_U1::ACC_U1(std::shared_ptr<Module> module) : Module::Interface(std::move(mod
38 RegisterHandlers(functions); 37 RegisterHandlers(functions);
39} 38}
40 39
41} // namespace Account 40} // namespace Service::Account
42} // namespace Service
diff --git a/src/core/hle/service/acc/acc_u1.h b/src/core/hle/service/acc/acc_u1.h
index 432d5b3e9..5e3e7659b 100644
--- a/src/core/hle/service/acc/acc_u1.h
+++ b/src/core/hle/service/acc/acc_u1.h
@@ -6,13 +6,11 @@
6 6
7#include "core/hle/service/acc/acc.h" 7#include "core/hle/service/acc/acc.h"
8 8
9namespace Service { 9namespace Service::Account {
10namespace Account {
11 10
12class ACC_U1 final : public Module::Interface { 11class ACC_U1 final : public Module::Interface {
13public: 12public:
14 explicit ACC_U1(std::shared_ptr<Module> module); 13 explicit ACC_U1(std::shared_ptr<Module> module);
15}; 14};
16 15
17} // namespace Account 16} // namespace Service::Account
18} // namespace Service
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index bfc431e88..f41a59afe 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -14,8 +14,7 @@
14#include "core/hle/service/nvflinger/nvflinger.h" 14#include "core/hle/service/nvflinger/nvflinger.h"
15#include "core/settings.h" 15#include "core/settings.h"
16 16
17namespace Service { 17namespace Service::AM {
18namespace AM {
19 18
20IWindowController::IWindowController() : ServiceFramework("IWindowController") { 19IWindowController::IWindowController() : ServiceFramework("IWindowController") {
21 static const FunctionInfo functions[] = { 20 static const FunctionInfo functions[] = {
@@ -571,5 +570,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager,
571 std::make_shared<AppletOE>(nvflinger)->InstallAsService(service_manager); 570 std::make_shared<AppletOE>(nvflinger)->InstallAsService(service_manager);
572} 571}
573 572
574} // namespace AM 573} // namespace Service::AM
575} // namespace Service
diff --git a/src/core/hle/service/am/applet_ae.cpp b/src/core/hle/service/am/applet_ae.cpp
index 154d346d5..4f0698a8a 100644
--- a/src/core/hle/service/am/applet_ae.cpp
+++ b/src/core/hle/service/am/applet_ae.cpp
@@ -8,8 +8,7 @@
8#include "core/hle/service/am/applet_ae.h" 8#include "core/hle/service/am/applet_ae.h"
9#include "core/hle/service/nvflinger/nvflinger.h" 9#include "core/hle/service/nvflinger/nvflinger.h"
10 10
11namespace Service { 11namespace Service::AM {
12namespace AM {
13 12
14class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> { 13class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> {
15public: 14public:
@@ -109,5 +108,4 @@ AppletAE::AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger)
109 RegisterHandlers(functions); 108 RegisterHandlers(functions);
110} 109}
111 110
112} // namespace AM 111} // namespace Service::AM
113} // namespace Service
diff --git a/src/core/hle/service/am/applet_oe.cpp b/src/core/hle/service/am/applet_oe.cpp
index 334c38392..674b4d753 100644
--- a/src/core/hle/service/am/applet_oe.cpp
+++ b/src/core/hle/service/am/applet_oe.cpp
@@ -8,8 +8,7 @@
8#include "core/hle/service/am/applet_oe.h" 8#include "core/hle/service/am/applet_oe.h"
9#include "core/hle/service/nvflinger/nvflinger.h" 9#include "core/hle/service/nvflinger/nvflinger.h"
10 10
11namespace Service { 11namespace Service::AM {
12namespace AM {
13 12
14class IApplicationProxy final : public ServiceFramework<IApplicationProxy> { 13class IApplicationProxy final : public ServiceFramework<IApplicationProxy> {
15public: 14public:
@@ -104,5 +103,4 @@ AppletOE::AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger)
104 RegisterHandlers(functions); 103 RegisterHandlers(functions);
105} 104}
106 105
107} // namespace AM 106} // namespace Service::AM
108} // namespace Service
diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp
index f64001df3..6e7438580 100644
--- a/src/core/hle/service/aoc/aoc_u.cpp
+++ b/src/core/hle/service/aoc/aoc_u.cpp
@@ -6,8 +6,7 @@
6#include "core/hle/ipc_helpers.h" 6#include "core/hle/ipc_helpers.h"
7#include "core/hle/service/aoc/aoc_u.h" 7#include "core/hle/service/aoc/aoc_u.h"
8 8
9namespace Service { 9namespace Service::AOC {
10namespace AOC {
11 10
12AOC_U::AOC_U() : ServiceFramework("aoc:u") { 11AOC_U::AOC_U() : ServiceFramework("aoc:u") {
13 static const FunctionInfo functions[] = { 12 static const FunctionInfo functions[] = {
@@ -42,5 +41,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
42 std::make_shared<AOC_U>()->InstallAsService(service_manager); 41 std::make_shared<AOC_U>()->InstallAsService(service_manager);
43} 42}
44 43
45} // namespace AOC 44} // namespace Service::AOC
46} // namespace Service
diff --git a/src/core/hle/service/aoc/aoc_u.h b/src/core/hle/service/aoc/aoc_u.h
index 6e0ba15a5..17d48ef30 100644
--- a/src/core/hle/service/aoc/aoc_u.h
+++ b/src/core/hle/service/aoc/aoc_u.h
@@ -6,8 +6,7 @@
6 6
7#include "core/hle/service/service.h" 7#include "core/hle/service/service.h"
8 8
9namespace Service { 9namespace Service::AOC {
10namespace AOC {
11 10
12class AOC_U final : public ServiceFramework<AOC_U> { 11class AOC_U final : public ServiceFramework<AOC_U> {
13public: 12public:
@@ -22,5 +21,4 @@ private:
22/// Registers all AOC services with the specified service manager. 21/// Registers all AOC services with the specified service manager.
23void InstallInterfaces(SM::ServiceManager& service_manager); 22void InstallInterfaces(SM::ServiceManager& service_manager);
24 23
25} // namespace AOC 24} // namespace Service::AOC
26} // namespace Service
diff --git a/src/core/hle/service/apm/apm.cpp b/src/core/hle/service/apm/apm.cpp
index c4b09b435..7a185c6c8 100644
--- a/src/core/hle/service/apm/apm.cpp
+++ b/src/core/hle/service/apm/apm.cpp
@@ -7,8 +7,7 @@
7#include "core/hle/service/apm/apm.h" 7#include "core/hle/service/apm/apm.h"
8#include "core/hle/service/apm/interface.h" 8#include "core/hle/service/apm/interface.h"
9 9
10namespace Service { 10namespace Service::APM {
11namespace APM {
12 11
13void InstallInterfaces(SM::ServiceManager& service_manager) { 12void InstallInterfaces(SM::ServiceManager& service_manager) {
14 auto module_ = std::make_shared<Module>(); 13 auto module_ = std::make_shared<Module>();
@@ -16,5 +15,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
16 std::make_shared<APM>(module_, "apm:p")->InstallAsService(service_manager); 15 std::make_shared<APM>(module_, "apm:p")->InstallAsService(service_manager);
17} 16}
18 17
19} // namespace APM 18} // namespace Service::APM
20} // namespace Service
diff --git a/src/core/hle/service/apm/apm.h b/src/core/hle/service/apm/apm.h
index 070ab21f8..90a80d51b 100644
--- a/src/core/hle/service/apm/apm.h
+++ b/src/core/hle/service/apm/apm.h
@@ -6,8 +6,7 @@
6 6
7#include "core/hle/service/service.h" 7#include "core/hle/service/service.h"
8 8
9namespace Service { 9namespace Service::APM {
10namespace APM {
11 10
12enum class PerformanceMode : u8 { 11enum class PerformanceMode : u8 {
13 Handheld = 0, 12 Handheld = 0,
@@ -23,5 +22,4 @@ public:
23/// Registers all AM services with the specified service manager. 22/// Registers all AM services with the specified service manager.
24void InstallInterfaces(SM::ServiceManager& service_manager); 23void InstallInterfaces(SM::ServiceManager& service_manager);
25 24
26} // namespace APM 25} // namespace Service::APM
27} // namespace Service
diff --git a/src/core/hle/service/apm/interface.cpp b/src/core/hle/service/apm/interface.cpp
index 0179351ba..4e11f3f14 100644
--- a/src/core/hle/service/apm/interface.cpp
+++ b/src/core/hle/service/apm/interface.cpp
@@ -7,8 +7,7 @@
7#include "core/hle/service/apm/apm.h" 7#include "core/hle/service/apm/apm.h"
8#include "core/hle/service/apm/interface.h" 8#include "core/hle/service/apm/interface.h"
9 9
10namespace Service { 10namespace Service::APM {
11namespace APM {
12 11
13class ISession final : public ServiceFramework<ISession> { 12class ISession final : public ServiceFramework<ISession> {
14public: 13public:
@@ -62,5 +61,4 @@ void APM::OpenSession(Kernel::HLERequestContext& ctx) {
62 rb.PushIpcInterface<ISession>(); 61 rb.PushIpcInterface<ISession>();
63} 62}
64 63
65} // namespace APM 64} // namespace Service::APM
66} // namespace Service
diff --git a/src/core/hle/service/apm/interface.h b/src/core/hle/service/apm/interface.h
index 7d53721de..b99dbb412 100644
--- a/src/core/hle/service/apm/interface.h
+++ b/src/core/hle/service/apm/interface.h
@@ -6,8 +6,7 @@
6 6
7#include "core/hle/service/service.h" 7#include "core/hle/service/service.h"
8 8
9namespace Service { 9namespace Service::APM {
10namespace APM {
11 10
12class APM final : public ServiceFramework<APM> { 11class APM final : public ServiceFramework<APM> {
13public: 12public:
@@ -23,5 +22,4 @@ private:
23/// Registers all AM services with the specified service manager. 22/// Registers all AM services with the specified service manager.
24void InstallInterfaces(SM::ServiceManager& service_manager); 23void InstallInterfaces(SM::ServiceManager& service_manager);
25 24
26} // namespace APM 25} // namespace Service::APM
27} // namespace Service
diff --git a/src/core/hle/service/audio/audin_u.cpp b/src/core/hle/service/audio/audin_u.cpp
index 3c495b3a0..dca2bfb92 100644
--- a/src/core/hle/service/audio/audin_u.cpp
+++ b/src/core/hle/service/audio/audin_u.cpp
@@ -7,8 +7,7 @@
7#include "core/hle/kernel/hle_ipc.h" 7#include "core/hle/kernel/hle_ipc.h"
8#include "core/hle/service/audio/audin_u.h" 8#include "core/hle/service/audio/audin_u.h"
9 9
10namespace Service { 10namespace Service::Audio {
11namespace Audio {
12 11
13class IAudioIn final : public ServiceFramework<IAudioIn> { 12class IAudioIn final : public ServiceFramework<IAudioIn> {
14public: 13public:
@@ -44,5 +43,4 @@ AudInU::AudInU() : ServiceFramework("audin:u") {
44 RegisterHandlers(functions); 43 RegisterHandlers(functions);
45} 44}
46 45
47} // namespace Audio 46} // namespace Service::Audio
48} // namespace Service
diff --git a/src/core/hle/service/audio/audin_u.h b/src/core/hle/service/audio/audin_u.h
index 2b8576756..2e65efb5b 100644
--- a/src/core/hle/service/audio/audin_u.h
+++ b/src/core/hle/service/audio/audin_u.h
@@ -10,8 +10,7 @@ namespace Kernel {
10class HLERequestContext; 10class HLERequestContext;
11} 11}
12 12
13namespace Service { 13namespace Service::Audio {
14namespace Audio {
15 14
16class AudInU final : public ServiceFramework<AudInU> { 15class AudInU final : public ServiceFramework<AudInU> {
17public: 16public:
@@ -19,5 +18,4 @@ public:
19 ~AudInU() = default; 18 ~AudInU() = default;
20}; 19};
21 20
22} // namespace Audio 21} // namespace Service::Audio
23} // namespace Service
diff --git a/src/core/hle/service/audio/audio.cpp b/src/core/hle/service/audio/audio.cpp
index 3f7fb44eb..92f910b5f 100644
--- a/src/core/hle/service/audio/audio.cpp
+++ b/src/core/hle/service/audio/audio.cpp
@@ -9,8 +9,7 @@
9#include "core/hle/service/audio/audren_u.h" 9#include "core/hle/service/audio/audren_u.h"
10#include "core/hle/service/audio/codecctl.h" 10#include "core/hle/service/audio/codecctl.h"
11 11
12namespace Service { 12namespace Service::Audio {
13namespace Audio {
14 13
15void InstallInterfaces(SM::ServiceManager& service_manager) { 14void InstallInterfaces(SM::ServiceManager& service_manager) {
16 std::make_shared<AudOutU>()->InstallAsService(service_manager); 15 std::make_shared<AudOutU>()->InstallAsService(service_manager);
@@ -20,5 +19,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
20 std::make_shared<CodecCtl>()->InstallAsService(service_manager); 19 std::make_shared<CodecCtl>()->InstallAsService(service_manager);
21} 20}
22 21
23} // namespace Audio 22} // namespace Service::Audio
24} // namespace Service
diff --git a/src/core/hle/service/audio/audio.h b/src/core/hle/service/audio/audio.h
index cbd56b2a8..95e5691f7 100644
--- a/src/core/hle/service/audio/audio.h
+++ b/src/core/hle/service/audio/audio.h
@@ -6,11 +6,9 @@
6 6
7#include "core/hle/service/service.h" 7#include "core/hle/service/service.h"
8 8
9namespace Service { 9namespace Service::Audio {
10namespace Audio {
11 10
12/// Registers all Audio services with the specified service manager. 11/// Registers all Audio services with the specified service manager.
13void InstallInterfaces(SM::ServiceManager& service_manager); 12void InstallInterfaces(SM::ServiceManager& service_manager);
14 13
15} // namespace Audio 14} // namespace Service::Audio
16} // namespace Service
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp
index db6e6647c..2d7f8cb04 100644
--- a/src/core/hle/service/audio/audout_u.cpp
+++ b/src/core/hle/service/audio/audout_u.cpp
@@ -10,8 +10,7 @@
10#include "core/hle/kernel/hle_ipc.h" 10#include "core/hle/kernel/hle_ipc.h"
11#include "core/hle/service/audio/audout_u.h" 11#include "core/hle/service/audio/audout_u.h"
12 12
13namespace Service { 13namespace Service::Audio {
14namespace Audio {
15 14
16/// Switch sample rate frequency 15/// Switch sample rate frequency
17constexpr u32 sample_rate{48000}; 16constexpr u32 sample_rate{48000};
@@ -204,5 +203,4 @@ AudOutU::AudOutU() : ServiceFramework("audout:u") {
204 RegisterHandlers(functions); 203 RegisterHandlers(functions);
205} 204}
206 205
207} // namespace Audio 206} // namespace Service::Audio
208} // namespace Service
diff --git a/src/core/hle/service/audio/audout_u.h b/src/core/hle/service/audio/audout_u.h
index 7fbce2225..1f9bb9bcf 100644
--- a/src/core/hle/service/audio/audout_u.h
+++ b/src/core/hle/service/audio/audout_u.h
@@ -10,8 +10,7 @@ namespace Kernel {
10class HLERequestContext; 10class HLERequestContext;
11} 11}
12 12
13namespace Service { 13namespace Service::Audio {
14namespace Audio {
15 14
16class IAudioOut; 15class IAudioOut;
17 16
@@ -37,5 +36,4 @@ private:
37 }; 36 };
38}; 37};
39 38
40} // namespace Audio 39} // namespace Service::Audio
41} // namespace Service
diff --git a/src/core/hle/service/audio/audrec_u.cpp b/src/core/hle/service/audio/audrec_u.cpp
index 953104f19..b2be10919 100644
--- a/src/core/hle/service/audio/audrec_u.cpp
+++ b/src/core/hle/service/audio/audrec_u.cpp
@@ -7,8 +7,7 @@
7#include "core/hle/kernel/hle_ipc.h" 7#include "core/hle/kernel/hle_ipc.h"
8#include "core/hle/service/audio/audrec_u.h" 8#include "core/hle/service/audio/audrec_u.h"
9 9
10namespace Service { 10namespace Service::Audio {
11namespace Audio {
12 11
13class IFinalOutputRecorder final : public ServiceFramework<IFinalOutputRecorder> { 12class IFinalOutputRecorder final : public ServiceFramework<IFinalOutputRecorder> {
14public: 13public:
@@ -36,5 +35,4 @@ AudRecU::AudRecU() : ServiceFramework("audrec:u") {
36 RegisterHandlers(functions); 35 RegisterHandlers(functions);
37} 36}
38 37
39} // namespace Audio 38} // namespace Service::Audio
40} // namespace Service
diff --git a/src/core/hle/service/audio/audrec_u.h b/src/core/hle/service/audio/audrec_u.h
index c31e412c1..46daa33a4 100644
--- a/src/core/hle/service/audio/audrec_u.h
+++ b/src/core/hle/service/audio/audrec_u.h
@@ -10,8 +10,7 @@ namespace Kernel {
10class HLERequestContext; 10class HLERequestContext;
11} 11}
12 12
13namespace Service { 13namespace Service::Audio {
14namespace Audio {
15 14
16class AudRecU final : public ServiceFramework<AudRecU> { 15class AudRecU final : public ServiceFramework<AudRecU> {
17public: 16public:
@@ -19,5 +18,4 @@ public:
19 ~AudRecU() = default; 18 ~AudRecU() = default;
20}; 19};
21 20
22} // namespace Audio 21} // namespace Service::Audio
23} // namespace Service
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index 0e78c57e9..d9245cb19 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -9,8 +9,7 @@
9#include "core/hle/kernel/hle_ipc.h" 9#include "core/hle/kernel/hle_ipc.h"
10#include "core/hle/service/audio/audren_u.h" 10#include "core/hle/service/audio/audren_u.h"
11 11
12namespace Service { 12namespace Service::Audio {
13namespace Audio {
14 13
15/// TODO(bunnei): Find a proper value for the audio_ticks 14/// TODO(bunnei): Find a proper value for the audio_ticks
16constexpr u64 audio_ticks{static_cast<u64>(BASE_CLOCK_RATE / 200)}; 15constexpr u64 audio_ticks{static_cast<u64>(BASE_CLOCK_RATE / 200)};
@@ -272,5 +271,4 @@ void AudRenU::GetAudioDevice(Kernel::HLERequestContext& ctx) {
272 LOG_DEBUG(Service_Audio, "called"); 271 LOG_DEBUG(Service_Audio, "called");
273} 272}
274 273
275} // namespace Audio 274} // namespace Service::Audio
276} // namespace Service
diff --git a/src/core/hle/service/audio/audren_u.h b/src/core/hle/service/audio/audren_u.h
index f59d1627d..71b632e80 100644
--- a/src/core/hle/service/audio/audren_u.h
+++ b/src/core/hle/service/audio/audren_u.h
@@ -10,8 +10,7 @@ namespace Kernel {
10class HLERequestContext; 10class HLERequestContext;
11} 11}
12 12
13namespace Service { 13namespace Service::Audio {
14namespace Audio {
15 14
16class AudRenU final : public ServiceFramework<AudRenU> { 15class AudRenU final : public ServiceFramework<AudRenU> {
17public: 16public:
@@ -24,5 +23,4 @@ private:
24 void GetAudioDevice(Kernel::HLERequestContext& ctx); 23 void GetAudioDevice(Kernel::HLERequestContext& ctx);
25}; 24};
26 25
27} // namespace Audio 26} // namespace Service::Audio
28} // namespace Service
diff --git a/src/core/hle/service/audio/codecctl.cpp b/src/core/hle/service/audio/codecctl.cpp
index 1c86d8d17..ba0f1d228 100644
--- a/src/core/hle/service/audio/codecctl.cpp
+++ b/src/core/hle/service/audio/codecctl.cpp
@@ -7,8 +7,7 @@
7#include "core/hle/kernel/hle_ipc.h" 7#include "core/hle/kernel/hle_ipc.h"
8#include "core/hle/service/audio/codecctl.h" 8#include "core/hle/service/audio/codecctl.h"
9 9
10namespace Service { 10namespace Service::Audio {
11namespace Audio {
12 11
13CodecCtl::CodecCtl() : ServiceFramework("codecctl") { 12CodecCtl::CodecCtl() : ServiceFramework("codecctl") {
14 static const FunctionInfo functions[] = { 13 static const FunctionInfo functions[] = {
@@ -29,5 +28,4 @@ CodecCtl::CodecCtl() : ServiceFramework("codecctl") {
29 RegisterHandlers(functions); 28 RegisterHandlers(functions);
30} 29}
31 30
32} // namespace Audio 31} // namespace Service::Audio
33} // namespace Service
diff --git a/src/core/hle/service/audio/codecctl.h b/src/core/hle/service/audio/codecctl.h
index 1121ab0b1..d9ac29b67 100644
--- a/src/core/hle/service/audio/codecctl.h
+++ b/src/core/hle/service/audio/codecctl.h
@@ -10,8 +10,7 @@ namespace Kernel {
10class HLERequestContext; 10class HLERequestContext;
11} 11}
12 12
13namespace Service { 13namespace Service::Audio {
14namespace Audio {
15 14
16class CodecCtl final : public ServiceFramework<CodecCtl> { 15class CodecCtl final : public ServiceFramework<CodecCtl> {
17public: 16public:
@@ -19,5 +18,4 @@ public:
19 ~CodecCtl() = default; 18 ~CodecCtl() = default;
20}; 19};
21 20
22} // namespace Audio 21} // namespace Service::Audio
23} // namespace Service
diff --git a/src/core/hle/service/fatal/fatal.cpp b/src/core/hle/service/fatal/fatal.cpp
index 1a18e0051..41d58f999 100644
--- a/src/core/hle/service/fatal/fatal.cpp
+++ b/src/core/hle/service/fatal/fatal.cpp
@@ -8,8 +8,7 @@
8#include "core/hle/service/fatal/fatal_p.h" 8#include "core/hle/service/fatal/fatal_p.h"
9#include "core/hle/service/fatal/fatal_u.h" 9#include "core/hle/service/fatal/fatal_u.h"
10 10
11namespace Service { 11namespace Service::Fatal {
12namespace Fatal {
13 12
14Module::Interface::Interface(std::shared_ptr<Module> module, const char* name) 13Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
15 : ServiceFramework(name), module(std::move(module)) {} 14 : ServiceFramework(name), module(std::move(module)) {}
@@ -34,5 +33,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
34 std::make_shared<Fatal_U>(module)->InstallAsService(service_manager); 33 std::make_shared<Fatal_U>(module)->InstallAsService(service_manager);
35} 34}
36 35
37} // namespace Fatal 36} // namespace Service::Fatal
38} // namespace Service
diff --git a/src/core/hle/service/fatal/fatal.h b/src/core/hle/service/fatal/fatal.h
index 85272b4be..2d8d08320 100644
--- a/src/core/hle/service/fatal/fatal.h
+++ b/src/core/hle/service/fatal/fatal.h
@@ -6,8 +6,7 @@
6 6
7#include "core/hle/service/service.h" 7#include "core/hle/service/service.h"
8 8
9namespace Service { 9namespace Service::Fatal {
10namespace Fatal {
11 10
12class Module final { 11class Module final {
13public: 12public:
@@ -25,5 +24,4 @@ public:
25 24
26void InstallInterfaces(SM::ServiceManager& service_manager); 25void InstallInterfaces(SM::ServiceManager& service_manager);
27 26
28} // namespace Fatal 27} // namespace Service::Fatal
29} // namespace Service
diff --git a/src/core/hle/service/fatal/fatal_p.cpp b/src/core/hle/service/fatal/fatal_p.cpp
index ba194e340..a5254ac2f 100644
--- a/src/core/hle/service/fatal/fatal_p.cpp
+++ b/src/core/hle/service/fatal/fatal_p.cpp
@@ -4,11 +4,9 @@
4 4
5#include "core/hle/service/fatal/fatal_p.h" 5#include "core/hle/service/fatal/fatal_p.h"
6 6
7namespace Service { 7namespace Service::Fatal {
8namespace Fatal {
9 8
10Fatal_P::Fatal_P(std::shared_ptr<Module> module) 9Fatal_P::Fatal_P(std::shared_ptr<Module> module)
11 : Module::Interface(std::move(module), "fatal:p") {} 10 : Module::Interface(std::move(module), "fatal:p") {}
12 11
13} // namespace Fatal 12} // namespace Service::Fatal
14} // namespace Service
diff --git a/src/core/hle/service/fatal/fatal_p.h b/src/core/hle/service/fatal/fatal_p.h
index d77b24bc4..bfd8c8b74 100644
--- a/src/core/hle/service/fatal/fatal_p.h
+++ b/src/core/hle/service/fatal/fatal_p.h
@@ -6,13 +6,11 @@
6 6
7#include "core/hle/service/fatal/fatal.h" 7#include "core/hle/service/fatal/fatal.h"
8 8
9namespace Service { 9namespace Service::Fatal {
10namespace Fatal {
11 10
12class Fatal_P final : public Module::Interface { 11class Fatal_P final : public Module::Interface {
13public: 12public:
14 explicit Fatal_P(std::shared_ptr<Module> module); 13 explicit Fatal_P(std::shared_ptr<Module> module);
15}; 14};
16 15
17} // namespace Fatal 16} // namespace Service::Fatal
18} // namespace Service
diff --git a/src/core/hle/service/fatal/fatal_u.cpp b/src/core/hle/service/fatal/fatal_u.cpp
index 065cc868d..26aa9f3b7 100644
--- a/src/core/hle/service/fatal/fatal_u.cpp
+++ b/src/core/hle/service/fatal/fatal_u.cpp
@@ -4,8 +4,7 @@
4 4
5#include "core/hle/service/fatal/fatal_u.h" 5#include "core/hle/service/fatal/fatal_u.h"
6 6
7namespace Service { 7namespace Service::Fatal {
8namespace Fatal {
9 8
10Fatal_U::Fatal_U(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "fatal:u") { 9Fatal_U::Fatal_U(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "fatal:u") {
11 static const FunctionInfo functions[] = { 10 static const FunctionInfo functions[] = {
@@ -15,5 +14,4 @@ Fatal_U::Fatal_U(std::shared_ptr<Module> module) : Module::Interface(std::move(m
15 RegisterHandlers(functions); 14 RegisterHandlers(functions);
16} 15}
17 16
18} // namespace Fatal 17} // namespace Service::Fatal
19} // namespace Service
diff --git a/src/core/hle/service/fatal/fatal_u.h b/src/core/hle/service/fatal/fatal_u.h
index 22374755e..9b1a9e97a 100644
--- a/src/core/hle/service/fatal/fatal_u.h
+++ b/src/core/hle/service/fatal/fatal_u.h
@@ -6,13 +6,11 @@
6 6
7#include "core/hle/service/fatal/fatal.h" 7#include "core/hle/service/fatal/fatal.h"
8 8
9namespace Service { 9namespace Service::Fatal {
10namespace Fatal {
11 10
12class Fatal_U final : public Module::Interface { 11class Fatal_U final : public Module::Interface {
13public: 12public:
14 explicit Fatal_U(std::shared_ptr<Module> module); 13 explicit Fatal_U(std::shared_ptr<Module> module);
15}; 14};
16 15
17} // namespace Fatal 16} // namespace Service::Fatal
18} // namespace Service
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index 945832e98..9e504992f 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -10,8 +10,7 @@
10#include "core/hle/service/filesystem/filesystem.h" 10#include "core/hle/service/filesystem/filesystem.h"
11#include "core/hle/service/filesystem/fsp_srv.h" 11#include "core/hle/service/filesystem/fsp_srv.h"
12 12
13namespace Service { 13namespace Service::FileSystem {
14namespace FileSystem {
15 14
16/** 15/**
17 * Map of registered file systems, identified by type. Once an file system is registered here, it 16 * Map of registered file systems, identified by type. Once an file system is registered here, it
@@ -75,5 +74,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
75 std::make_shared<FSP_SRV>()->InstallAsService(service_manager); 74 std::make_shared<FSP_SRV>()->InstallAsService(service_manager);
76} 75}
77 76
78} // namespace FileSystem 77} // namespace Service::FileSystem
79} // namespace Service
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp
index 48c45b1b4..2f476c869 100644
--- a/src/core/hle/service/filesystem/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp_srv.cpp
@@ -14,8 +14,7 @@
14#include "core/hle/service/filesystem/filesystem.h" 14#include "core/hle/service/filesystem/filesystem.h"
15#include "core/hle/service/filesystem/fsp_srv.h" 15#include "core/hle/service/filesystem/fsp_srv.h"
16 16
17namespace Service { 17namespace Service::FileSystem {
18namespace FileSystem {
19 18
20class IStorage final : public ServiceFramework<IStorage> { 19class IStorage final : public ServiceFramework<IStorage> {
21public: 20public:
@@ -73,7 +72,7 @@ public:
73 : ServiceFramework("IFile"), backend(std::move(backend)) { 72 : ServiceFramework("IFile"), backend(std::move(backend)) {
74 static const FunctionInfo functions[] = { 73 static const FunctionInfo functions[] = {
75 {0, &IFile::Read, "Read"}, {1, &IFile::Write, "Write"}, 74 {0, &IFile::Read, "Read"}, {1, &IFile::Write, "Write"},
76 {2, nullptr, "Flush"}, {3, &IFile::SetSize, "SetSize"}, 75 {2, &IFile::Flush, "Flush"}, {3, &IFile::SetSize, "SetSize"},
77 {4, &IFile::GetSize, "GetSize"}, {5, nullptr, "OperateRange"}, 76 {4, &IFile::GetSize, "GetSize"}, {5, nullptr, "OperateRange"},
78 }; 77 };
79 RegisterHandlers(functions); 78 RegisterHandlers(functions);
@@ -152,6 +151,14 @@ private:
152 rb.Push(RESULT_SUCCESS); 151 rb.Push(RESULT_SUCCESS);
153 } 152 }
154 153
154 void Flush(Kernel::HLERequestContext& ctx) {
155 LOG_DEBUG(Service_FS, "called");
156 backend->Flush();
157
158 IPC::ResponseBuilder rb{ctx, 2};
159 rb.Push(RESULT_SUCCESS);
160 }
161
155 void SetSize(Kernel::HLERequestContext& ctx) { 162 void SetSize(Kernel::HLERequestContext& ctx) {
156 IPC::RequestParser rp{ctx}; 163 IPC::RequestParser rp{ctx};
157 const u64 size = rp.Pop<u64>(); 164 const u64 size = rp.Pop<u64>();
@@ -228,7 +235,7 @@ public:
228 : ServiceFramework("IFileSystem"), backend(std::move(backend)) { 235 : ServiceFramework("IFileSystem"), backend(std::move(backend)) {
229 static const FunctionInfo functions[] = { 236 static const FunctionInfo functions[] = {
230 {0, &IFileSystem::CreateFile, "CreateFile"}, 237 {0, &IFileSystem::CreateFile, "CreateFile"},
231 {1, nullptr, "DeleteFile"}, 238 {1, &IFileSystem::DeleteFile, "DeleteFile"},
232 {2, &IFileSystem::CreateDirectory, "CreateDirectory"}, 239 {2, &IFileSystem::CreateDirectory, "CreateDirectory"},
233 {3, nullptr, "DeleteDirectory"}, 240 {3, nullptr, "DeleteDirectory"},
234 {4, nullptr, "DeleteDirectoryRecursively"}, 241 {4, nullptr, "DeleteDirectoryRecursively"},
@@ -265,6 +272,20 @@ public:
265 rb.Push(backend->CreateFile(name, size)); 272 rb.Push(backend->CreateFile(name, size));
266 } 273 }
267 274
275 void DeleteFile(Kernel::HLERequestContext& ctx) {
276 IPC::RequestParser rp{ctx};
277
278 auto file_buffer = ctx.ReadBuffer();
279 auto end = std::find(file_buffer.begin(), file_buffer.end(), '\0');
280
281 std::string name(file_buffer.begin(), end);
282
283 LOG_DEBUG(Service_FS, "called file %s", name.c_str());
284
285 IPC::ResponseBuilder rb{ctx, 2};
286 rb.Push(backend->DeleteFile(name));
287 }
288
268 void CreateDirectory(Kernel::HLERequestContext& ctx) { 289 void CreateDirectory(Kernel::HLERequestContext& ctx) {
269 IPC::RequestParser rp{ctx}; 290 IPC::RequestParser rp{ctx};
270 291
@@ -551,5 +572,4 @@ void FSP_SRV::OpenRomStorage(Kernel::HLERequestContext& ctx) {
551 OpenDataStorageByCurrentProcess(ctx); 572 OpenDataStorageByCurrentProcess(ctx);
552} 573}
553 574
554} // namespace FileSystem 575} // namespace Service::FileSystem
555} // namespace Service
diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp_srv.h
index 6dc5874c0..acb78fac1 100644
--- a/src/core/hle/service/filesystem/fsp_srv.h
+++ b/src/core/hle/service/filesystem/fsp_srv.h
@@ -11,8 +11,7 @@ namespace FileSys {
11class FileSystemBackend; 11class FileSystemBackend;
12} 12}
13 13
14namespace Service { 14namespace Service::FileSystem {
15namespace FileSystem {
16 15
17class FSP_SRV final : public ServiceFramework<FSP_SRV> { 16class FSP_SRV final : public ServiceFramework<FSP_SRV> {
18public: 17public:
@@ -33,5 +32,4 @@ private:
33 std::unique_ptr<FileSys::FileSystemBackend> romfs; 32 std::unique_ptr<FileSys::FileSystemBackend> romfs;
34}; 33};
35 34
36} // namespace FileSystem 35} // namespace Service::FileSystem
37} // namespace Service
diff --git a/src/core/hle/service/friend/friend.cpp b/src/core/hle/service/friend/friend.cpp
index 051448b2a..c98a46e05 100644
--- a/src/core/hle/service/friend/friend.cpp
+++ b/src/core/hle/service/friend/friend.cpp
@@ -8,8 +8,7 @@
8#include "core/hle/service/friend/friend_a.h" 8#include "core/hle/service/friend/friend_a.h"
9#include "core/hle/service/friend/friend_u.h" 9#include "core/hle/service/friend/friend_u.h"
10 10
11namespace Service { 11namespace Service::Friend {
12namespace Friend {
13 12
14void Module::Interface::CreateFriendService(Kernel::HLERequestContext& ctx) { 13void Module::Interface::CreateFriendService(Kernel::HLERequestContext& ctx) {
15 IPC::ResponseBuilder rb{ctx, 2}; 14 IPC::ResponseBuilder rb{ctx, 2};
@@ -26,5 +25,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
26 std::make_shared<Friend_U>(module)->InstallAsService(service_manager); 25 std::make_shared<Friend_U>(module)->InstallAsService(service_manager);
27} 26}
28 27
29} // namespace Friend 28} // namespace Service::Friend
30} // namespace Service
diff --git a/src/core/hle/service/friend/friend.h b/src/core/hle/service/friend/friend.h
index 2b21b4e15..4b72115c0 100644
--- a/src/core/hle/service/friend/friend.h
+++ b/src/core/hle/service/friend/friend.h
@@ -6,8 +6,7 @@
6 6
7#include "core/hle/service/service.h" 7#include "core/hle/service/service.h"
8 8
9namespace Service { 9namespace Service::Friend {
10namespace Friend {
11 10
12class Module final { 11class Module final {
13public: 12public:
@@ -25,5 +24,4 @@ public:
25/// Registers all Friend services with the specified service manager. 24/// Registers all Friend services with the specified service manager.
26void InstallInterfaces(SM::ServiceManager& service_manager); 25void InstallInterfaces(SM::ServiceManager& service_manager);
27 26
28} // namespace Friend 27} // namespace Service::Friend
29} // namespace Service
diff --git a/src/core/hle/service/friend/friend_a.cpp b/src/core/hle/service/friend/friend_a.cpp
index d64fe846a..a2cc81926 100644
--- a/src/core/hle/service/friend/friend_a.cpp
+++ b/src/core/hle/service/friend/friend_a.cpp
@@ -4,8 +4,7 @@
4 4
5#include "core/hle/service/friend/friend_a.h" 5#include "core/hle/service/friend/friend_a.h"
6 6
7namespace Service { 7namespace Service::Friend {
8namespace Friend {
9 8
10Friend_A::Friend_A(std::shared_ptr<Module> module) 9Friend_A::Friend_A(std::shared_ptr<Module> module)
11 : Module::Interface(std::move(module), "friend:a") { 10 : Module::Interface(std::move(module), "friend:a") {
@@ -16,5 +15,4 @@ Friend_A::Friend_A(std::shared_ptr<Module> module)
16 RegisterHandlers(functions); 15 RegisterHandlers(functions);
17} 16}
18 17
19} // namespace Friend 18} // namespace Service::Friend
20} // namespace Service
diff --git a/src/core/hle/service/friend/friend_a.h b/src/core/hle/service/friend/friend_a.h
index 68fa58297..81257583b 100644
--- a/src/core/hle/service/friend/friend_a.h
+++ b/src/core/hle/service/friend/friend_a.h
@@ -6,13 +6,11 @@
6 6
7#include "core/hle/service/friend/friend.h" 7#include "core/hle/service/friend/friend.h"
8 8
9namespace Service { 9namespace Service::Friend {
10namespace Friend {
11 10
12class Friend_A final : public Module::Interface { 11class Friend_A final : public Module::Interface {
13public: 12public:
14 explicit Friend_A(std::shared_ptr<Module> module); 13 explicit Friend_A(std::shared_ptr<Module> module);
15}; 14};
16 15
17} // namespace Friend 16} // namespace Service::Friend
18} // namespace Service
diff --git a/src/core/hle/service/friend/friend_u.cpp b/src/core/hle/service/friend/friend_u.cpp
index 9a4b05b38..90b30883f 100644
--- a/src/core/hle/service/friend/friend_u.cpp
+++ b/src/core/hle/service/friend/friend_u.cpp
@@ -4,8 +4,7 @@
4 4
5#include "core/hle/service/friend/friend_u.h" 5#include "core/hle/service/friend/friend_u.h"
6 6
7namespace Service { 7namespace Service::Friend {
8namespace Friend {
9 8
10Friend_U::Friend_U(std::shared_ptr<Module> module) 9Friend_U::Friend_U(std::shared_ptr<Module> module)
11 : Module::Interface(std::move(module), "friend:u") { 10 : Module::Interface(std::move(module), "friend:u") {
@@ -16,5 +15,4 @@ Friend_U::Friend_U(std::shared_ptr<Module> module)
16 RegisterHandlers(functions); 15 RegisterHandlers(functions);
17} 16}
18 17
19} // namespace Friend 18} // namespace Service::Friend
20} // namespace Service
diff --git a/src/core/hle/service/friend/friend_u.h b/src/core/hle/service/friend/friend_u.h
index 6be49ff01..0d953d807 100644
--- a/src/core/hle/service/friend/friend_u.h
+++ b/src/core/hle/service/friend/friend_u.h
@@ -6,13 +6,11 @@
6 6
7#include "core/hle/service/friend/friend.h" 7#include "core/hle/service/friend/friend.h"
8 8
9namespace Service { 9namespace Service::Friend {
10namespace Friend {
11 10
12class Friend_U final : public Module::Interface { 11class Friend_U final : public Module::Interface {
13public: 12public:
14 explicit Friend_U(std::shared_ptr<Module> module); 13 explicit Friend_U(std::shared_ptr<Module> module);
15}; 14};
16 15
17} // namespace Friend 16} // namespace Service::Friend
18} // namespace Service
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index b59c52f07..aad5e688b 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -14,8 +14,7 @@
14#include "core/hle/service/hid/hid.h" 14#include "core/hle/service/hid/hid.h"
15#include "core/hle/service/service.h" 15#include "core/hle/service/service.h"
16 16
17namespace Service { 17namespace Service::HID {
18namespace HID {
19 18
20// Updating period for each HID device. 19// Updating period for each HID device.
21// TODO(shinyquagsire23): These need better values. 20// TODO(shinyquagsire23): These need better values.
@@ -434,5 +433,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
434 std::make_shared<Hid>()->InstallAsService(service_manager); 433 std::make_shared<Hid>()->InstallAsService(service_manager);
435} 434}
436 435
437} // namespace HID 436} // namespace Service::HID
438} // namespace Service
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index 3de9adb4b..350174ccd 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -7,8 +7,7 @@
7#include "core/hle/service/service.h" 7#include "core/hle/service/service.h"
8#include "core/settings.h" 8#include "core/settings.h"
9 9
10namespace Service { 10namespace Service::HID {
11namespace HID {
12 11
13// Begin enums and output structs 12// Begin enums and output structs
14 13
@@ -337,5 +336,4 @@ void ReloadInputDevices();
337/// Registers all HID services with the specified service manager. 336/// Registers all HID services with the specified service manager.
338void InstallInterfaces(SM::ServiceManager& service_manager); 337void InstallInterfaces(SM::ServiceManager& service_manager);
339 338
340} // namespace HID 339} // namespace Service::HID
341} // namespace Service
diff --git a/src/core/hle/service/lm/lm.cpp b/src/core/hle/service/lm/lm.cpp
index b8e53d2c7..b87172dff 100644
--- a/src/core/hle/service/lm/lm.cpp
+++ b/src/core/hle/service/lm/lm.cpp
@@ -9,8 +9,7 @@
9#include "core/hle/kernel/client_session.h" 9#include "core/hle/kernel/client_session.h"
10#include "core/hle/service/lm/lm.h" 10#include "core/hle/service/lm/lm.h"
11 11
12namespace Service { 12namespace Service::LM {
13namespace LM {
14 13
15class Logger final : public ServiceFramework<Logger> { 14class Logger final : public ServiceFramework<Logger> {
16public: 15public:
@@ -189,5 +188,4 @@ LM::LM() : ServiceFramework("lm") {
189 RegisterHandlers(functions); 188 RegisterHandlers(functions);
190} 189}
191 190
192} // namespace LM 191} // namespace Service::LM
193} // namespace Service
diff --git a/src/core/hle/service/lm/lm.h b/src/core/hle/service/lm/lm.h
index 371135057..63d6506fe 100644
--- a/src/core/hle/service/lm/lm.h
+++ b/src/core/hle/service/lm/lm.h
@@ -8,8 +8,7 @@
8#include "core/hle/kernel/kernel.h" 8#include "core/hle/kernel/kernel.h"
9#include "core/hle/service/service.h" 9#include "core/hle/service/service.h"
10 10
11namespace Service { 11namespace Service::LM {
12namespace LM {
13 12
14class LM final : public ServiceFramework<LM> { 13class LM final : public ServiceFramework<LM> {
15public: 14public:
@@ -23,5 +22,4 @@ private:
23/// Registers all LM services with the specified service manager. 22/// Registers all LM services with the specified service manager.
24void InstallInterfaces(SM::ServiceManager& service_manager); 23void InstallInterfaces(SM::ServiceManager& service_manager);
25 24
26} // namespace LM 25} // namespace Service::LM
27} // namespace Service
diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp
index 49870841c..91e5f527a 100644
--- a/src/core/hle/service/nfp/nfp.cpp
+++ b/src/core/hle/service/nfp/nfp.cpp
@@ -7,8 +7,7 @@
7#include "core/hle/service/nfp/nfp.h" 7#include "core/hle/service/nfp/nfp.h"
8#include "core/hle/service/nfp/nfp_user.h" 8#include "core/hle/service/nfp/nfp_user.h"
9 9
10namespace Service { 10namespace Service::NFP {
11namespace NFP {
12 11
13Module::Interface::Interface(std::shared_ptr<Module> module, const char* name) 12Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
14 : ServiceFramework(name), module(std::move(module)) {} 13 : ServiceFramework(name), module(std::move(module)) {}
@@ -24,5 +23,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
24 std::make_shared<NFP_User>(module)->InstallAsService(service_manager); 23 std::make_shared<NFP_User>(module)->InstallAsService(service_manager);
25} 24}
26 25
27} // namespace NFP 26} // namespace Service::NFP
28} // namespace Service
diff --git a/src/core/hle/service/nfp/nfp.h b/src/core/hle/service/nfp/nfp.h
index 1163e9954..095209ad8 100644
--- a/src/core/hle/service/nfp/nfp.h
+++ b/src/core/hle/service/nfp/nfp.h
@@ -6,8 +6,7 @@
6 6
7#include "core/hle/service/service.h" 7#include "core/hle/service/service.h"
8 8
9namespace Service { 9namespace Service::NFP {
10namespace NFP {
11 10
12class Module final { 11class Module final {
13public: 12public:
@@ -24,5 +23,4 @@ public:
24 23
25void InstallInterfaces(SM::ServiceManager& service_manager); 24void InstallInterfaces(SM::ServiceManager& service_manager);
26 25
27} // namespace NFP 26} // namespace Service::NFP
28} // namespace Service
diff --git a/src/core/hle/service/nfp/nfp_user.cpp b/src/core/hle/service/nfp/nfp_user.cpp
index 14e5647c4..e94c271e7 100644
--- a/src/core/hle/service/nfp/nfp_user.cpp
+++ b/src/core/hle/service/nfp/nfp_user.cpp
@@ -4,8 +4,7 @@
4 4
5#include "core/hle/service/nfp/nfp_user.h" 5#include "core/hle/service/nfp/nfp_user.h"
6 6
7namespace Service { 7namespace Service::NFP {
8namespace NFP {
9 8
10NFP_User::NFP_User(std::shared_ptr<Module> module) 9NFP_User::NFP_User(std::shared_ptr<Module> module)
11 : Module::Interface(std::move(module), "nfp:user") { 10 : Module::Interface(std::move(module), "nfp:user") {
@@ -15,5 +14,4 @@ NFP_User::NFP_User(std::shared_ptr<Module> module)
15 RegisterHandlers(functions); 14 RegisterHandlers(functions);
16} 15}
17 16
18} // namespace NFP 17} // namespace Service::NFP
19} // namespace Service
diff --git a/src/core/hle/service/nfp/nfp_user.h b/src/core/hle/service/nfp/nfp_user.h
index 1606444ca..700043114 100644
--- a/src/core/hle/service/nfp/nfp_user.h
+++ b/src/core/hle/service/nfp/nfp_user.h
@@ -6,13 +6,11 @@
6 6
7#include "core/hle/service/nfp/nfp.h" 7#include "core/hle/service/nfp/nfp.h"
8 8
9namespace Service { 9namespace Service::NFP {
10namespace NFP {
11 10
12class NFP_User final : public Module::Interface { 11class NFP_User final : public Module::Interface {
13public: 12public:
14 explicit NFP_User(std::shared_ptr<Module> module); 13 explicit NFP_User(std::shared_ptr<Module> module);
15}; 14};
16 15
17} // namespace NFP 16} // namespace Service::NFP
18} // namespace Service
diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp
index b32112db3..df1e7f8fe 100644
--- a/src/core/hle/service/nifm/nifm.cpp
+++ b/src/core/hle/service/nifm/nifm.cpp
@@ -9,8 +9,7 @@
9#include "core/hle/service/nifm/nifm_s.h" 9#include "core/hle/service/nifm/nifm_s.h"
10#include "core/hle/service/nifm/nifm_u.h" 10#include "core/hle/service/nifm/nifm_u.h"
11 11
12namespace Service { 12namespace Service::NIFM {
13namespace NIFM {
14 13
15class IScanRequest final : public ServiceFramework<IScanRequest> { 14class IScanRequest final : public ServiceFramework<IScanRequest> {
16public: 15public:
@@ -208,5 +207,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
208 std::make_shared<NIFM_U>(module)->InstallAsService(service_manager); 207 std::make_shared<NIFM_U>(module)->InstallAsService(service_manager);
209} 208}
210 209
211} // namespace NIFM 210} // namespace Service::NIFM
212} // namespace Service
diff --git a/src/core/hle/service/nifm/nifm.h b/src/core/hle/service/nifm/nifm.h
index 11d263b12..4ad3f3bcf 100644
--- a/src/core/hle/service/nifm/nifm.h
+++ b/src/core/hle/service/nifm/nifm.h
@@ -6,8 +6,7 @@
6 6
7#include "core/hle/service/service.h" 7#include "core/hle/service/service.h"
8 8
9namespace Service { 9namespace Service::NIFM {
10namespace NIFM {
11 10
12class Module final { 11class Module final {
13public: 12public:
@@ -25,5 +24,4 @@ public:
25 24
26void InstallInterfaces(SM::ServiceManager& service_manager); 25void InstallInterfaces(SM::ServiceManager& service_manager);
27 26
28} // namespace NIFM 27} // namespace Service::NIFM
29} // namespace Service
diff --git a/src/core/hle/service/nifm/nifm_a.cpp b/src/core/hle/service/nifm/nifm_a.cpp
index f75df8c04..b7f296a20 100644
--- a/src/core/hle/service/nifm/nifm_a.cpp
+++ b/src/core/hle/service/nifm/nifm_a.cpp
@@ -4,8 +4,7 @@
4 4
5#include "core/hle/service/nifm/nifm_a.h" 5#include "core/hle/service/nifm/nifm_a.h"
6 6
7namespace Service { 7namespace Service::NIFM {
8namespace NIFM {
9 8
10NIFM_A::NIFM_A(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "nifm:a") { 9NIFM_A::NIFM_A(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "nifm:a") {
11 static const FunctionInfo functions[] = { 10 static const FunctionInfo functions[] = {
@@ -15,5 +14,4 @@ NIFM_A::NIFM_A(std::shared_ptr<Module> module) : Module::Interface(std::move(mod
15 RegisterHandlers(functions); 14 RegisterHandlers(functions);
16} 15}
17 16
18} // namespace NIFM 17} // namespace Service::NIFM
19} // namespace Service
diff --git a/src/core/hle/service/nifm/nifm_a.h b/src/core/hle/service/nifm/nifm_a.h
index eaea14e29..c3ba33110 100644
--- a/src/core/hle/service/nifm/nifm_a.h
+++ b/src/core/hle/service/nifm/nifm_a.h
@@ -6,13 +6,11 @@
6 6
7#include "core/hle/service/nifm/nifm.h" 7#include "core/hle/service/nifm/nifm.h"
8 8
9namespace Service { 9namespace Service::NIFM {
10namespace NIFM {
11 10
12class NIFM_A final : public Module::Interface { 11class NIFM_A final : public Module::Interface {
13public: 12public:
14 explicit NIFM_A(std::shared_ptr<Module> module); 13 explicit NIFM_A(std::shared_ptr<Module> module);
15}; 14};
16 15
17} // namespace NIFM 16} // namespace Service::NIFM
18} // namespace Service
diff --git a/src/core/hle/service/nifm/nifm_s.cpp b/src/core/hle/service/nifm/nifm_s.cpp
index 9c0b300e4..96e3c0cee 100644
--- a/src/core/hle/service/nifm/nifm_s.cpp
+++ b/src/core/hle/service/nifm/nifm_s.cpp
@@ -4,8 +4,7 @@
4 4
5#include "core/hle/service/nifm/nifm_s.h" 5#include "core/hle/service/nifm/nifm_s.h"
6 6
7namespace Service { 7namespace Service::NIFM {
8namespace NIFM {
9 8
10NIFM_S::NIFM_S(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "nifm:s") { 9NIFM_S::NIFM_S(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "nifm:s") {
11 static const FunctionInfo functions[] = { 10 static const FunctionInfo functions[] = {
@@ -15,5 +14,4 @@ NIFM_S::NIFM_S(std::shared_ptr<Module> module) : Module::Interface(std::move(mod
15 RegisterHandlers(functions); 14 RegisterHandlers(functions);
16} 15}
17 16
18} // namespace NIFM 17} // namespace Service::NIFM
19} // namespace Service
diff --git a/src/core/hle/service/nifm/nifm_s.h b/src/core/hle/service/nifm/nifm_s.h
index f9e2d8039..8d1635a5d 100644
--- a/src/core/hle/service/nifm/nifm_s.h
+++ b/src/core/hle/service/nifm/nifm_s.h
@@ -6,13 +6,11 @@
6 6
7#include "core/hle/service/nifm/nifm.h" 7#include "core/hle/service/nifm/nifm.h"
8 8
9namespace Service { 9namespace Service::NIFM {
10namespace NIFM {
11 10
12class NIFM_S final : public Module::Interface { 11class NIFM_S final : public Module::Interface {
13public: 12public:
14 explicit NIFM_S(std::shared_ptr<Module> module); 13 explicit NIFM_S(std::shared_ptr<Module> module);
15}; 14};
16 15
17} // namespace NIFM 16} // namespace Service::NIFM
18} // namespace Service
diff --git a/src/core/hle/service/nifm/nifm_u.cpp b/src/core/hle/service/nifm/nifm_u.cpp
index 44e6f483d..8cb75b903 100644
--- a/src/core/hle/service/nifm/nifm_u.cpp
+++ b/src/core/hle/service/nifm/nifm_u.cpp
@@ -4,8 +4,7 @@
4 4
5#include "core/hle/service/nifm/nifm_u.h" 5#include "core/hle/service/nifm/nifm_u.h"
6 6
7namespace Service { 7namespace Service::NIFM {
8namespace NIFM {
9 8
10NIFM_U::NIFM_U(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "nifm:u") { 9NIFM_U::NIFM_U(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "nifm:u") {
11 static const FunctionInfo functions[] = { 10 static const FunctionInfo functions[] = {
@@ -15,5 +14,4 @@ NIFM_U::NIFM_U(std::shared_ptr<Module> module) : Module::Interface(std::move(mod
15 RegisterHandlers(functions); 14 RegisterHandlers(functions);
16} 15}
17 16
18} // namespace NIFM 17} // namespace Service::NIFM
19} // namespace Service
diff --git a/src/core/hle/service/nifm/nifm_u.h b/src/core/hle/service/nifm/nifm_u.h
index 912006775..def9726b1 100644
--- a/src/core/hle/service/nifm/nifm_u.h
+++ b/src/core/hle/service/nifm/nifm_u.h
@@ -6,13 +6,11 @@
6 6
7#include "core/hle/service/nifm/nifm.h" 7#include "core/hle/service/nifm/nifm.h"
8 8
9namespace Service { 9namespace Service::NIFM {
10namespace NIFM {
11 10
12class NIFM_U final : public Module::Interface { 11class NIFM_U final : public Module::Interface {
13public: 12public:
14 explicit NIFM_U(std::shared_ptr<Module> module); 13 explicit NIFM_U(std::shared_ptr<Module> module);
15}; 14};
16 15
17} // namespace NIFM 16} // namespace Service::NIFM
18} // namespace Service
diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp
index 45681c50f..89c703310 100644
--- a/src/core/hle/service/ns/ns.cpp
+++ b/src/core/hle/service/ns/ns.cpp
@@ -5,12 +5,10 @@
5#include "core/hle/service/ns/ns.h" 5#include "core/hle/service/ns/ns.h"
6#include "core/hle/service/ns/pl_u.h" 6#include "core/hle/service/ns/pl_u.h"
7 7
8namespace Service { 8namespace Service::NS {
9namespace NS {
10 9
11void InstallInterfaces(SM::ServiceManager& service_manager) { 10void InstallInterfaces(SM::ServiceManager& service_manager) {
12 std::make_shared<PL_U>()->InstallAsService(service_manager); 11 std::make_shared<PL_U>()->InstallAsService(service_manager);
13} 12}
14 13
15} // namespace NS 14} // namespace Service::NS
16} // namespace Service
diff --git a/src/core/hle/service/ns/ns.h b/src/core/hle/service/ns/ns.h
index a4b7e3ded..b81ca8f1e 100644
--- a/src/core/hle/service/ns/ns.h
+++ b/src/core/hle/service/ns/ns.h
@@ -6,11 +6,9 @@
6 6
7#include "core/hle/service/service.h" 7#include "core/hle/service/service.h"
8 8
9namespace Service { 9namespace Service::NS {
10namespace NS {
11 10
12/// Registers all NS services with the specified service manager. 11/// Registers all NS services with the specified service manager.
13void InstallInterfaces(SM::ServiceManager& service_manager); 12void InstallInterfaces(SM::ServiceManager& service_manager);
14 13
15} // namespace NS 14} // namespace Service::NS
16} // namespace Service
diff --git a/src/core/hle/service/ns/pl_u.cpp b/src/core/hle/service/ns/pl_u.cpp
index d5e0b5f14..c416ad720 100644
--- a/src/core/hle/service/ns/pl_u.cpp
+++ b/src/core/hle/service/ns/pl_u.cpp
@@ -8,8 +8,7 @@
8#include "core/hle/ipc_helpers.h" 8#include "core/hle/ipc_helpers.h"
9#include "core/hle/service/ns/pl_u.h" 9#include "core/hle/service/ns/pl_u.h"
10 10
11namespace Service { 11namespace Service::NS {
12namespace NS {
13 12
14struct FontRegion { 13struct FontRegion {
15 u32 offset; 14 u32 offset;
@@ -47,10 +46,10 @@ PL_U::PL_U() : ServiceFramework("pl:u") {
47 FileUtil::CreateFullPath(filepath); // Create path if not already created 46 FileUtil::CreateFullPath(filepath); // Create path if not already created
48 FileUtil::IOFile file(filepath, "rb"); 47 FileUtil::IOFile file(filepath, "rb");
49 48
49 shared_font = std::make_shared<std::vector<u8>>(SHARED_FONT_MEM_SIZE);
50 if (file.IsOpen()) { 50 if (file.IsOpen()) {
51 // Read shared font data 51 // Read shared font data
52 ASSERT(file.GetSize() == SHARED_FONT_MEM_SIZE); 52 ASSERT(file.GetSize() == SHARED_FONT_MEM_SIZE);
53 shared_font = std::make_shared<std::vector<u8>>(static_cast<size_t>(file.GetSize()));
54 file.ReadBytes(shared_font->data(), shared_font->size()); 53 file.ReadBytes(shared_font->data(), shared_font->size());
55 } else { 54 } else {
56 LOG_WARNING(Service_NS, "Unable to load shared font: %s", filepath.c_str()); 55 LOG_WARNING(Service_NS, "Unable to load shared font: %s", filepath.c_str());
@@ -97,22 +96,19 @@ void PL_U::GetSharedMemoryAddressOffset(Kernel::HLERequestContext& ctx) {
97} 96}
98 97
99void PL_U::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) { 98void PL_U::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) {
100 if (shared_font != nullptr) { 99 // TODO(bunnei): This is a less-than-ideal solution to load a RAM dump of the Switch shared
101 // TODO(bunnei): This is a less-than-ideal solution to load a RAM dump of the Switch shared 100 // font data. This (likely) relies on exact address, size, and offsets from the original
102 // font data. This (likely) relies on exact address, size, and offsets from the original 101 // dump. In the future, we need to replace this with a more robust solution.
103 // dump. In the future, we need to replace this with a more robust solution. 102
104 103 // Map backing memory for the font data
105 // Map backing memory for the font data 104 Core::CurrentProcess()->vm_manager.MapMemoryBlock(
106 Core::CurrentProcess()->vm_manager.MapMemoryBlock(SHARED_FONT_MEM_VADDR, shared_font, 0, 105 SHARED_FONT_MEM_VADDR, shared_font, 0, SHARED_FONT_MEM_SIZE, Kernel::MemoryState::Shared);
107 SHARED_FONT_MEM_SIZE, 106
108 Kernel::MemoryState::Shared); 107 // Create shared font memory object
109 108 shared_font_mem = Kernel::SharedMemory::Create(
110 // Create shared font memory object 109 Core::CurrentProcess(), SHARED_FONT_MEM_SIZE, Kernel::MemoryPermission::ReadWrite,
111 shared_font_mem = Kernel::SharedMemory::Create( 110 Kernel::MemoryPermission::Read, SHARED_FONT_MEM_VADDR, Kernel::MemoryRegion::BASE,
112 Core::CurrentProcess(), SHARED_FONT_MEM_SIZE, Kernel::MemoryPermission::ReadWrite, 111 "PL_U:shared_font_mem");
113 Kernel::MemoryPermission::Read, SHARED_FONT_MEM_VADDR, Kernel::MemoryRegion::BASE,
114 "PL_U:shared_font_mem");
115 }
116 112
117 LOG_DEBUG(Service_NS, "called"); 113 LOG_DEBUG(Service_NS, "called");
118 IPC::ResponseBuilder rb{ctx, 2, 1}; 114 IPC::ResponseBuilder rb{ctx, 2, 1};
@@ -120,5 +116,4 @@ void PL_U::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) {
120 rb.PushCopyObjects(shared_font_mem); 116 rb.PushCopyObjects(shared_font_mem);
121} 117}
122 118
123} // namespace NS 119} // namespace Service::NS
124} // namespace Service
diff --git a/src/core/hle/service/ns/pl_u.h b/src/core/hle/service/ns/pl_u.h
index 360482d13..b175c9c44 100644
--- a/src/core/hle/service/ns/pl_u.h
+++ b/src/core/hle/service/ns/pl_u.h
@@ -8,8 +8,7 @@
8#include "core/hle/kernel/shared_memory.h" 8#include "core/hle/kernel/shared_memory.h"
9#include "core/hle/service/service.h" 9#include "core/hle/service/service.h"
10 10
11namespace Service { 11namespace Service::NS {
12namespace NS {
13 12
14class PL_U final : public ServiceFramework<PL_U> { 13class PL_U final : public ServiceFramework<PL_U> {
15public: 14public:
@@ -30,5 +29,4 @@ private:
30 std::shared_ptr<std::vector<u8>> shared_font; 29 std::shared_ptr<std::vector<u8>> shared_font;
31}; 30};
32 31
33} // namespace NS 32} // namespace Service::NS
34} // namespace Service
diff --git a/src/core/hle/service/nvdrv/devices/nvdevice.h b/src/core/hle/service/nvdrv/devices/nvdevice.h
index cdc25b059..0f02a1a18 100644
--- a/src/core/hle/service/nvdrv/devices/nvdevice.h
+++ b/src/core/hle/service/nvdrv/devices/nvdevice.h
@@ -9,9 +9,7 @@
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "common/swap.h" 10#include "common/swap.h"
11 11
12namespace Service { 12namespace Service::Nvidia::Devices {
13namespace Nvidia {
14namespace Devices {
15 13
16/// Represents an abstract nvidia device node. It is to be subclassed by concrete device nodes to 14/// Represents an abstract nvidia device node. It is to be subclassed by concrete device nodes to
17/// implement the ioctl interface. 15/// implement the ioctl interface.
@@ -38,6 +36,4 @@ public:
38 virtual u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) = 0; 36 virtual u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) = 0;
39}; 37};
40 38
41} // namespace Devices 39} // namespace Service::Nvidia::Devices
42} // namespace Nvidia
43} // namespace Service
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
index 87b3a2d74..61f22b1a5 100644
--- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
@@ -10,9 +10,7 @@
10#include "video_core/renderer_base.h" 10#include "video_core/renderer_base.h"
11#include "video_core/video_core.h" 11#include "video_core/video_core.h"
12 12
13namespace Service { 13namespace Service::Nvidia::Devices {
14namespace Nvidia {
15namespace Devices {
16 14
17u32 nvdisp_disp0::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { 15u32 nvdisp_disp0::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
18 UNIMPLEMENTED(); 16 UNIMPLEMENTED();
@@ -35,6 +33,4 @@ void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u3
35 VideoCore::g_renderer->SwapBuffers(framebuffer); 33 VideoCore::g_renderer->SwapBuffers(framebuffer);
36} 34}
37 35
38} // namespace Devices 36} // namespace Service::Nvidia::Devices
39} // namespace Nvidia
40} // namespace Service
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h
index 66f56f23d..3d3979723 100644
--- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h
+++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h
@@ -10,9 +10,7 @@
10#include "core/hle/service/nvdrv/devices/nvdevice.h" 10#include "core/hle/service/nvdrv/devices/nvdevice.h"
11#include "core/hle/service/nvflinger/buffer_queue.h" 11#include "core/hle/service/nvflinger/buffer_queue.h"
12 12
13namespace Service { 13namespace Service::Nvidia::Devices {
14namespace Nvidia {
15namespace Devices {
16 14
17class nvmap; 15class nvmap;
18 16
@@ -31,6 +29,4 @@ private:
31 std::shared_ptr<nvmap> nvmap_dev; 29 std::shared_ptr<nvmap> nvmap_dev;
32}; 30};
33 31
34} // namespace Devices 32} // namespace Service::Nvidia::Devices
35} // namespace Nvidia
36} // namespace Service
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 9892402fa..71e844959 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
@@ -9,9 +9,7 @@
9#include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h" 9#include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h"
10#include "core/hle/service/nvdrv/devices/nvmap.h" 10#include "core/hle/service/nvdrv/devices/nvmap.h"
11 11
12namespace Service { 12namespace Service::Nvidia::Devices {
13namespace Nvidia {
14namespace Devices {
15 13
16u32 nvhost_as_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { 14u32 nvhost_as_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%zx, output_size=0x%zx", 15 LOG_DEBUG(Service_NVDRV, "called, command=0x%08x, input_size=0x%zx, output_size=0x%zx",
@@ -115,6 +113,4 @@ u32 nvhost_as_gpu::GetVARegions(const std::vector<u8>& input, std::vector<u8>& o
115 return 0; 113 return 0;
116} 114}
117 115
118} // namespace Devices 116} // namespace Service::Nvidia::Devices
119} // namespace Nvidia
120} // namespace Service
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 f8a60cce7..d86c3ebd9 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h
@@ -11,9 +11,7 @@
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 13
14namespace Service { 14namespace Service::Nvidia::Devices {
15namespace Nvidia {
16namespace Devices {
17 15
18class nvmap; 16class nvmap;
19 17
@@ -100,6 +98,4 @@ private:
100 std::shared_ptr<nvmap> nvmap_dev; 98 std::shared_ptr<nvmap> nvmap_dev;
101}; 99};
102 100
103} // namespace Devices 101} // namespace Service::Nvidia::Devices
104} // namespace Nvidia
105} // namespace Service
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
index 45711d686..660a0f665 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
@@ -6,9 +6,7 @@
6#include "common/logging/log.h" 6#include "common/logging/log.h"
7#include "core/hle/service/nvdrv/devices/nvhost_ctrl.h" 7#include "core/hle/service/nvdrv/devices/nvhost_ctrl.h"
8 8
9namespace Service { 9namespace Service::Nvidia::Devices {
10namespace Nvidia {
11namespace Devices {
12 10
13u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { 11u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
14 LOG_DEBUG(Service_NVDRV, "called, command=0x%08x, input_size=0x%zx, output_size=0x%zx", 12 LOG_DEBUG(Service_NVDRV, "called, command=0x%08x, input_size=0x%zx, output_size=0x%zx",
@@ -59,6 +57,4 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>&
59 return 0; 57 return 0;
60} 58}
61 59
62} // namespace Devices 60} // namespace Service::Nvidia::Devices
63} // namespace Nvidia
64} // namespace Service
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
index 0ca01aa6d..76a8b33c2 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
@@ -11,9 +11,7 @@
11#include "common/common_types.h" 11#include "common/common_types.h"
12#include "core/hle/service/nvdrv/devices/nvdevice.h" 12#include "core/hle/service/nvdrv/devices/nvdevice.h"
13 13
14namespace Service { 14namespace Service::Nvidia::Devices {
15namespace Nvidia {
16namespace Devices {
17 15
18class nvhost_ctrl final : public nvdevice { 16class nvhost_ctrl final : public nvdevice {
19public: 17public:
@@ -55,6 +53,4 @@ private:
55 u32 IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output); 53 u32 IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output);
56}; 54};
57 55
58} // namespace Devices 56} // namespace Service::Nvidia::Devices
59} // namespace Nvidia
60} // namespace Service
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 3b353d742..18ea12ef5 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
@@ -7,9 +7,7 @@
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8#include "core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h" 8#include "core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h"
9 9
10namespace Service { 10namespace Service::Nvidia::Devices {
11namespace Nvidia {
12namespace Devices {
13 11
14u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { 12u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
15 LOG_DEBUG(Service_NVDRV, "called, command=0x%08x, input_size=0x%zx, output_size=0x%zx", 13 LOG_DEBUG(Service_NVDRV, "called, command=0x%08x, input_size=0x%zx, output_size=0x%zx",
@@ -122,6 +120,4 @@ u32 nvhost_ctrl_gpu::ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>&
122 return 0; 120 return 0;
123} 121}
124 122
125} // namespace Devices 123} // namespace Service::Nvidia::Devices
126} // namespace Nvidia
127} // namespace Service
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 dc0476993..31040cdbe 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h
@@ -9,9 +9,7 @@
9#include "common/swap.h" 9#include "common/swap.h"
10#include "core/hle/service/nvdrv/devices/nvdevice.h" 10#include "core/hle/service/nvdrv/devices/nvdevice.h"
11 11
12namespace Service { 12namespace Service::Nvidia::Devices {
13namespace Nvidia {
14namespace Devices {
15 13
16class nvhost_ctrl_gpu final : public nvdevice { 14class nvhost_ctrl_gpu final : public nvdevice {
17public: 15public:
@@ -125,6 +123,5 @@ private:
125 u32 ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u8>& output); 123 u32 ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u8>& output);
126 u32 ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>& output); 124 u32 ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>& output);
127}; 125};
128} // namespace Devices 126
129} // namespace Nvidia 127} // namespace Service::Nvidia::Devices
130} // namespace Service
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
index da44c65f3..a16e90457 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
@@ -9,9 +9,7 @@
9#include "core/core.h" 9#include "core/core.h"
10#include "core/hle/service/nvdrv/devices/nvhost_gpu.h" 10#include "core/hle/service/nvdrv/devices/nvhost_gpu.h"
11 11
12namespace Service { 12namespace Service::Nvidia::Devices {
13namespace Nvidia {
14namespace Devices {
15 13
16u32 nvhost_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { 14u32 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%zx, output_size=0x%zx", 15 LOG_DEBUG(Service_NVDRV, "called, command=0x%08x, input_size=0x%zx, output_size=0x%zx",
@@ -142,6 +140,4 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& outp
142 return 0; 140 return 0;
143} 141}
144 142
145} // namespace Devices 143} // namespace Service::Nvidia::Devices
146} // namespace Nvidia
147} // namespace Service
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
index e7e9a0088..703c36bbb 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
@@ -10,9 +10,7 @@
10#include "common/swap.h" 10#include "common/swap.h"
11#include "core/hle/service/nvdrv/devices/nvdevice.h" 11#include "core/hle/service/nvdrv/devices/nvdevice.h"
12 12
13namespace Service { 13namespace Service::Nvidia::Devices {
14namespace Nvidia {
15namespace Devices {
16 14
17class nvmap; 15class nvmap;
18constexpr u32 NVGPU_IOCTL_MAGIC('H'); 16constexpr u32 NVGPU_IOCTL_MAGIC('H');
@@ -139,6 +137,4 @@ private:
139 std::shared_ptr<nvmap> nvmap_dev; 137 std::shared_ptr<nvmap> nvmap_dev;
140}; 138};
141 139
142} // namespace Devices 140} // namespace Service::Nvidia::Devices
143} // namespace Nvidia
144} // namespace Service
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp
index b3842eb4c..4bb1f57f6 100644
--- a/src/core/hle/service/nvdrv/devices/nvmap.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp
@@ -9,9 +9,7 @@
9#include "common/logging/log.h" 9#include "common/logging/log.h"
10#include "core/hle/service/nvdrv/devices/nvmap.h" 10#include "core/hle/service/nvdrv/devices/nvmap.h"
11 11
12namespace Service { 12namespace Service::Nvidia::Devices {
13namespace Nvidia {
14namespace Devices {
15 13
16VAddr nvmap::GetObjectAddress(u32 handle) const { 14VAddr nvmap::GetObjectAddress(u32 handle) const {
17 auto object = GetObject(handle); 15 auto object = GetObject(handle);
@@ -144,6 +142,4 @@ u32 nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output) {
144 return 0; 142 return 0;
145} 143}
146 144
147} // namespace Devices 145} // namespace Service::Nvidia::Devices
148} // namespace Nvidia
149} // namespace Service
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.h b/src/core/hle/service/nvdrv/devices/nvmap.h
index 4681e438b..431eb3773 100644
--- a/src/core/hle/service/nvdrv/devices/nvmap.h
+++ b/src/core/hle/service/nvdrv/devices/nvmap.h
@@ -12,9 +12,7 @@
12#include "common/swap.h" 12#include "common/swap.h"
13#include "core/hle/service/nvdrv/devices/nvdevice.h" 13#include "core/hle/service/nvdrv/devices/nvdevice.h"
14 14
15namespace Service { 15namespace Service::Nvidia::Devices {
16namespace Nvidia {
17namespace Devices {
18 16
19class nvmap final : public nvdevice { 17class nvmap final : public nvdevice {
20public: 18public:
@@ -111,6 +109,4 @@ private:
111 u32 IocParam(const std::vector<u8>& input, std::vector<u8>& output); 109 u32 IocParam(const std::vector<u8>& input, std::vector<u8>& output);
112}; 110};
113 111
114} // namespace Devices 112} // namespace Service::Nvidia::Devices
115} // namespace Nvidia
116} // namespace Service
diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp
index 567c2cd7c..d0d64a840 100644
--- a/src/core/hle/service/nvdrv/interface.cpp
+++ b/src/core/hle/service/nvdrv/interface.cpp
@@ -9,8 +9,7 @@
9#include "core/hle/service/nvdrv/interface.h" 9#include "core/hle/service/nvdrv/interface.h"
10#include "core/hle/service/nvdrv/nvdrv.h" 10#include "core/hle/service/nvdrv/nvdrv.h"
11 11
12namespace Service { 12namespace Service::Nvidia {
13namespace Nvidia {
14 13
15void NVDRV::Open(Kernel::HLERequestContext& ctx) { 14void NVDRV::Open(Kernel::HLERequestContext& ctx) {
16 LOG_DEBUG(Service_NVDRV, "called"); 15 LOG_DEBUG(Service_NVDRV, "called");
@@ -111,5 +110,4 @@ NVDRV::NVDRV(std::shared_ptr<Module> nvdrv, const char* name)
111 query_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "NVDRV::query_event"); 110 query_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "NVDRV::query_event");
112} 111}
113 112
114} // namespace Nvidia 113} // namespace Service::Nvidia
115} // namespace Service
diff --git a/src/core/hle/service/nvdrv/interface.h b/src/core/hle/service/nvdrv/interface.h
index daf2302af..959b5ba29 100644
--- a/src/core/hle/service/nvdrv/interface.h
+++ b/src/core/hle/service/nvdrv/interface.h
@@ -10,8 +10,7 @@
10#include "core/hle/service/nvdrv/nvdrv.h" 10#include "core/hle/service/nvdrv/nvdrv.h"
11#include "core/hle/service/service.h" 11#include "core/hle/service/service.h"
12 12
13namespace Service { 13namespace Service::Nvidia {
14namespace Nvidia {
15 14
16class NVDRV final : public ServiceFramework<NVDRV> { 15class NVDRV final : public ServiceFramework<NVDRV> {
17public: 16public:
@@ -34,5 +33,4 @@ private:
34 Kernel::SharedPtr<Kernel::Event> query_event; 33 Kernel::SharedPtr<Kernel::Event> query_event;
35}; 34};
36 35
37} // namespace Nvidia 36} // namespace Service::Nvidia
38} // namespace Service
diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp
index ea00240e6..170420418 100644
--- a/src/core/hle/service/nvdrv/nvdrv.cpp
+++ b/src/core/hle/service/nvdrv/nvdrv.cpp
@@ -14,8 +14,7 @@
14#include "core/hle/service/nvdrv/nvdrv.h" 14#include "core/hle/service/nvdrv/nvdrv.h"
15#include "core/hle/service/nvdrv/nvmemp.h" 15#include "core/hle/service/nvdrv/nvmemp.h"
16 16
17namespace Service { 17namespace Service::Nvidia {
18namespace Nvidia {
19 18
20std::weak_ptr<Module> nvdrv; 19std::weak_ptr<Module> nvdrv;
21 20
@@ -69,5 +68,4 @@ ResultCode Module::Close(u32 fd) {
69 return RESULT_SUCCESS; 68 return RESULT_SUCCESS;
70} 69}
71 70
72} // namespace Nvidia 71} // namespace Service::Nvidia
73} // namespace Service
diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h
index 6a55ff96d..579940817 100644
--- a/src/core/hle/service/nvdrv/nvdrv.h
+++ b/src/core/hle/service/nvdrv/nvdrv.h
@@ -10,8 +10,7 @@
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "core/hle/service/service.h" 11#include "core/hle/service/service.h"
12 12
13namespace Service { 13namespace Service::Nvidia {
14namespace Nvidia {
15 14
16namespace Devices { 15namespace Devices {
17class nvdevice; 16class nvdevice;
@@ -61,5 +60,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager);
61 60
62extern std::weak_ptr<Module> nvdrv; 61extern std::weak_ptr<Module> nvdrv;
63 62
64} // namespace Nvidia 63} // namespace Service::Nvidia
65} // namespace Service
diff --git a/src/core/hle/service/nvdrv/nvmemp.cpp b/src/core/hle/service/nvdrv/nvmemp.cpp
index 35d6c0c13..9ca6e5512 100644
--- a/src/core/hle/service/nvdrv/nvmemp.cpp
+++ b/src/core/hle/service/nvdrv/nvmemp.cpp
@@ -8,8 +8,7 @@
8#include "core/hle/service/nvdrv/nvdrv.h" 8#include "core/hle/service/nvdrv/nvdrv.h"
9#include "core/hle/service/nvdrv/nvmemp.h" 9#include "core/hle/service/nvdrv/nvmemp.h"
10 10
11namespace Service { 11namespace Service::Nvidia {
12namespace Nvidia {
13 12
14NVMEMP::NVMEMP() : ServiceFramework("nvmemp") { 13NVMEMP::NVMEMP() : ServiceFramework("nvmemp") {
15 static const FunctionInfo functions[] = { 14 static const FunctionInfo functions[] = {
@@ -27,5 +26,4 @@ void NVMEMP::Cmd1(Kernel::HLERequestContext& ctx) {
27 UNIMPLEMENTED(); 26 UNIMPLEMENTED();
28} 27}
29 28
30} // namespace Nvidia 29} // namespace Service::Nvidia
31} // namespace Service
diff --git a/src/core/hle/service/nvdrv/nvmemp.h b/src/core/hle/service/nvdrv/nvmemp.h
index fb16026b0..dfdcabf4a 100644
--- a/src/core/hle/service/nvdrv/nvmemp.h
+++ b/src/core/hle/service/nvdrv/nvmemp.h
@@ -6,8 +6,7 @@
6 6
7#include "core/hle/service/service.h" 7#include "core/hle/service/service.h"
8 8
9namespace Service { 9namespace Service::Nvidia {
10namespace Nvidia {
11 10
12class NVMEMP final : public ServiceFramework<NVMEMP> { 11class NVMEMP final : public ServiceFramework<NVMEMP> {
13public: 12public:
@@ -19,5 +18,4 @@ private:
19 void Cmd1(Kernel::HLERequestContext& ctx); 18 void Cmd1(Kernel::HLERequestContext& ctx);
20}; 19};
21 20
22} // namespace Nvidia 21} // namespace Service::Nvidia
23} // namespace Service
diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp
index e4ff2e267..03a4fed59 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.cpp
+++ b/src/core/hle/service/nvflinger/buffer_queue.cpp
@@ -9,8 +9,7 @@
9#include "core/core_timing.h" 9#include "core/core_timing.h"
10#include "core/hle/service/nvflinger/buffer_queue.h" 10#include "core/hle/service/nvflinger/buffer_queue.h"
11 11
12namespace Service { 12namespace Service::NVFlinger {
13namespace NVFlinger {
14 13
15BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) { 14BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) {
16 native_handle = Kernel::Event::Create(Kernel::ResetType::OneShot, "BufferQueue NativeHandle"); 15 native_handle = Kernel::Event::Create(Kernel::ResetType::OneShot, "BufferQueue NativeHandle");
@@ -111,5 +110,4 @@ void BufferQueue::SetBufferWaitEvent(Kernel::SharedPtr<Kernel::Event>&& wait_eve
111 buffer_wait_event = std::move(wait_event); 110 buffer_wait_event = std::move(wait_event);
112} 111}
113 112
114} // namespace NVFlinger 113} // namespace Service::NVFlinger
115} // namespace Service
diff --git a/src/core/hle/service/nvflinger/buffer_queue.h b/src/core/hle/service/nvflinger/buffer_queue.h
index 1de5767cb..95adc4706 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.h
+++ b/src/core/hle/service/nvflinger/buffer_queue.h
@@ -13,8 +13,7 @@ namespace CoreTiming {
13struct EventType; 13struct EventType;
14} 14}
15 15
16namespace Service { 16namespace Service::NVFlinger {
17namespace NVFlinger {
18 17
19struct IGBPBuffer { 18struct IGBPBuffer {
20 u32_le magic; 19 u32_le magic;
@@ -98,5 +97,4 @@ private:
98 Kernel::SharedPtr<Kernel::Event> buffer_wait_event; 97 Kernel::SharedPtr<Kernel::Event> buffer_wait_event;
99}; 98};
100 99
101} // namespace NVFlinger 100} // namespace Service::NVFlinger
102} // namespace Service
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index 0d30f54dc..a99ebc8e6 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -5,6 +5,7 @@
5#include <algorithm> 5#include <algorithm>
6 6
7#include "common/alignment.h" 7#include "common/alignment.h"
8#include "common/microprofile.h"
8#include "common/scope_exit.h" 9#include "common/scope_exit.h"
9#include "core/core.h" 10#include "core/core.h"
10#include "core/core_timing.h" 11#include "core/core_timing.h"
@@ -15,8 +16,7 @@
15#include "video_core/renderer_base.h" 16#include "video_core/renderer_base.h"
16#include "video_core/video_core.h" 17#include "video_core/video_core.h"
17 18
18namespace Service { 19namespace Service::NVFlinger {
19namespace NVFlinger {
20 20
21constexpr size_t SCREEN_REFRESH_RATE = 60; 21constexpr size_t SCREEN_REFRESH_RATE = 60;
22constexpr u64 frame_ticks = static_cast<u64>(BASE_CLOCK_RATE / SCREEN_REFRESH_RATE); 22constexpr u64 frame_ticks = static_cast<u64>(BASE_CLOCK_RATE / SCREEN_REFRESH_RATE);
@@ -128,6 +128,8 @@ void NVFlinger::Compose() {
128 // Search for a queued buffer and acquire it 128 // Search for a queued buffer and acquire it
129 auto buffer = buffer_queue->AcquireBuffer(); 129 auto buffer = buffer_queue->AcquireBuffer();
130 130
131 MicroProfileFlip();
132
131 if (buffer == boost::none) { 133 if (buffer == boost::none) {
132 // There was no queued buffer to draw, render previous frame 134 // There was no queued buffer to draw, render previous frame
133 Core::System::GetInstance().perf_stats.EndGameFrame(); 135 Core::System::GetInstance().perf_stats.EndGameFrame();
@@ -162,5 +164,4 @@ Display::Display(u64 id, std::string name) : id(id), name(std::move(name)) {
162 vsync_event = Kernel::Event::Create(Kernel::ResetType::Pulse, "Display VSync Event"); 164 vsync_event = Kernel::Event::Create(Kernel::ResetType::Pulse, "Display VSync Event");
163} 165}
164 166
165} // namespace NVFlinger 167} // namespace Service::NVFlinger
166} // namespace Service
diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h
index 3126018ad..2c908297b 100644
--- a/src/core/hle/service/nvflinger/nvflinger.h
+++ b/src/core/hle/service/nvflinger/nvflinger.h
@@ -12,8 +12,7 @@ namespace CoreTiming {
12struct EventType; 12struct EventType;
13} 13}
14 14
15namespace Service { 15namespace Service::NVFlinger {
16namespace NVFlinger {
17 16
18class BufferQueue; 17class BufferQueue;
19 18
@@ -80,5 +79,4 @@ private:
80 CoreTiming::EventType* composition_event; 79 CoreTiming::EventType* composition_event;
81}; 80};
82 81
83} // namespace NVFlinger 82} // namespace Service::NVFlinger
84} // namespace Service
diff --git a/src/core/hle/service/pctl/pctl.cpp b/src/core/hle/service/pctl/pctl.cpp
index 692b27a71..6ee81866d 100644
--- a/src/core/hle/service/pctl/pctl.cpp
+++ b/src/core/hle/service/pctl/pctl.cpp
@@ -5,12 +5,10 @@
5#include "core/hle/service/pctl/pctl.h" 5#include "core/hle/service/pctl/pctl.h"
6#include "core/hle/service/pctl/pctl_a.h" 6#include "core/hle/service/pctl/pctl_a.h"
7 7
8namespace Service { 8namespace Service::PCTL {
9namespace PCTL {
10 9
11void InstallInterfaces(SM::ServiceManager& service_manager) { 10void InstallInterfaces(SM::ServiceManager& service_manager) {
12 std::make_shared<PCTL_A>()->InstallAsService(service_manager); 11 std::make_shared<PCTL_A>()->InstallAsService(service_manager);
13} 12}
14 13
15} // namespace PCTL 14} // namespace Service::PCTL
16} // namespace Service
diff --git a/src/core/hle/service/pctl/pctl.h b/src/core/hle/service/pctl/pctl.h
index 5fa67dd1b..f0a84b115 100644
--- a/src/core/hle/service/pctl/pctl.h
+++ b/src/core/hle/service/pctl/pctl.h
@@ -6,11 +6,9 @@
6 6
7#include "core/hle/service/service.h" 7#include "core/hle/service/service.h"
8 8
9namespace Service { 9namespace Service::PCTL {
10namespace PCTL {
11 10
12/// Registers all PCTL services with the specified service manager. 11/// Registers all PCTL services with the specified service manager.
13void InstallInterfaces(SM::ServiceManager& service_manager); 12void InstallInterfaces(SM::ServiceManager& service_manager);
14 13
15} // namespace PCTL 14} // namespace Service::PCTL
16} // namespace Service
diff --git a/src/core/hle/service/pctl/pctl_a.cpp b/src/core/hle/service/pctl/pctl_a.cpp
index 4e644be64..9fb4628ad 100644
--- a/src/core/hle/service/pctl/pctl_a.cpp
+++ b/src/core/hle/service/pctl/pctl_a.cpp
@@ -6,8 +6,7 @@
6#include "core/hle/ipc_helpers.h" 6#include "core/hle/ipc_helpers.h"
7#include "core/hle/service/pctl/pctl_a.h" 7#include "core/hle/service/pctl/pctl_a.h"
8 8
9namespace Service { 9namespace Service::PCTL {
10namespace PCTL {
11 10
12class IParentalControlService final : public ServiceFramework<IParentalControlService> { 11class IParentalControlService final : public ServiceFramework<IParentalControlService> {
13public: 12public:
@@ -125,5 +124,4 @@ PCTL_A::PCTL_A() : ServiceFramework("pctl:a") {
125 RegisterHandlers(functions); 124 RegisterHandlers(functions);
126} 125}
127 126
128} // namespace PCTL 127} // namespace Service::PCTL
129} // namespace Service
diff --git a/src/core/hle/service/pctl/pctl_a.h b/src/core/hle/service/pctl/pctl_a.h
index 3aa8873a9..09ed82e1b 100644
--- a/src/core/hle/service/pctl/pctl_a.h
+++ b/src/core/hle/service/pctl/pctl_a.h
@@ -6,8 +6,7 @@
6 6
7#include "core/hle/service/service.h" 7#include "core/hle/service/service.h"
8 8
9namespace Service { 9namespace Service::PCTL {
10namespace PCTL {
11 10
12class PCTL_A final : public ServiceFramework<PCTL_A> { 11class PCTL_A final : public ServiceFramework<PCTL_A> {
13public: 12public:
@@ -18,5 +17,4 @@ private:
18 void CreateService(Kernel::HLERequestContext& ctx); 17 void CreateService(Kernel::HLERequestContext& ctx);
19}; 18};
20 19
21} // namespace PCTL 20} // namespace Service::PCTL
22} // namespace Service
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index c5490c1ae..08ce29677 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -145,7 +145,7 @@ ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::HLERequestContext& co
145 return ResultCode(ErrorModule::HIPC, ErrorDescription::RemoteProcessDead); 145 return ResultCode(ErrorModule::HIPC, ErrorDescription::RemoteProcessDead);
146 } 146 }
147 case IPC::CommandType::Control: { 147 case IPC::CommandType::Control: {
148 SM::g_service_manager->InvokeControlRequest(context); 148 Core::System::GetInstance().ServiceManager().InvokeControlRequest(context);
149 break; 149 break;
150 } 150 }
151 case IPC::CommandType::Request: { 151 case IPC::CommandType::Request: {
@@ -170,42 +170,40 @@ void AddNamedPort(std::string name, SharedPtr<ClientPort> port) {
170} 170}
171 171
172/// Initialize ServiceManager 172/// Initialize ServiceManager
173void Init() { 173void Init(std::shared_ptr<SM::ServiceManager>& sm) {
174 // NVFlinger needs to be accessed by several services like Vi and AppletOE so we instantiate it 174 // NVFlinger needs to be accessed by several services like Vi and AppletOE so we instantiate it
175 // here and pass it into the respective InstallInterfaces functions. 175 // here and pass it into the respective InstallInterfaces functions.
176 auto nv_flinger = std::make_shared<NVFlinger::NVFlinger>(); 176 auto nv_flinger = std::make_shared<NVFlinger::NVFlinger>();
177 177
178 SM::g_service_manager = std::make_shared<SM::ServiceManager>(); 178 SM::ServiceManager::InstallInterfaces(sm);
179 SM::ServiceManager::InstallInterfaces(SM::g_service_manager); 179
180 180 Account::InstallInterfaces(*sm);
181 Account::InstallInterfaces(*SM::g_service_manager); 181 AM::InstallInterfaces(*sm, nv_flinger);
182 AM::InstallInterfaces(*SM::g_service_manager, nv_flinger); 182 AOC::InstallInterfaces(*sm);
183 AOC::InstallInterfaces(*SM::g_service_manager); 183 APM::InstallInterfaces(*sm);
184 APM::InstallInterfaces(*SM::g_service_manager); 184 Audio::InstallInterfaces(*sm);
185 Audio::InstallInterfaces(*SM::g_service_manager); 185 Fatal::InstallInterfaces(*sm);
186 Fatal::InstallInterfaces(*SM::g_service_manager); 186 FileSystem::InstallInterfaces(*sm);
187 FileSystem::InstallInterfaces(*SM::g_service_manager); 187 Friend::InstallInterfaces(*sm);
188 Friend::InstallInterfaces(*SM::g_service_manager); 188 HID::InstallInterfaces(*sm);
189 HID::InstallInterfaces(*SM::g_service_manager); 189 LM::InstallInterfaces(*sm);
190 LM::InstallInterfaces(*SM::g_service_manager); 190 NFP::InstallInterfaces(*sm);
191 NFP::InstallInterfaces(*SM::g_service_manager); 191 NIFM::InstallInterfaces(*sm);
192 NIFM::InstallInterfaces(*SM::g_service_manager); 192 NS::InstallInterfaces(*sm);
193 NS::InstallInterfaces(*SM::g_service_manager); 193 Nvidia::InstallInterfaces(*sm);
194 Nvidia::InstallInterfaces(*SM::g_service_manager); 194 PCTL::InstallInterfaces(*sm);
195 PCTL::InstallInterfaces(*SM::g_service_manager); 195 Sockets::InstallInterfaces(*sm);
196 Sockets::InstallInterfaces(*SM::g_service_manager); 196 SPL::InstallInterfaces(*sm);
197 SPL::InstallInterfaces(*SM::g_service_manager); 197 SSL::InstallInterfaces(*sm);
198 SSL::InstallInterfaces(*SM::g_service_manager); 198 Time::InstallInterfaces(*sm);
199 Time::InstallInterfaces(*SM::g_service_manager); 199 VI::InstallInterfaces(*sm, nv_flinger);
200 VI::InstallInterfaces(*SM::g_service_manager, nv_flinger); 200 Set::InstallInterfaces(*sm);
201 Set::InstallInterfaces(*SM::g_service_manager);
202 201
203 LOG_DEBUG(Service, "initialized OK"); 202 LOG_DEBUG(Service, "initialized OK");
204} 203}
205 204
206/// Shutdown ServiceManager 205/// Shutdown ServiceManager
207void Shutdown() { 206void Shutdown() {
208 SM::g_service_manager = nullptr;
209 g_kernel_named_ports.clear(); 207 g_kernel_named_ports.clear();
210 LOG_DEBUG(Service, "shutdown OK"); 208 LOG_DEBUG(Service, "shutdown OK");
211} 209}
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index 9c2e826da..fee841d46 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -178,7 +178,7 @@ private:
178}; 178};
179 179
180/// Initialize ServiceManager 180/// Initialize ServiceManager
181void Init(); 181void Init(std::shared_ptr<SM::ServiceManager>& sm);
182 182
183/// Shutdown ServiceManager 183/// Shutdown ServiceManager
184void Shutdown(); 184void Shutdown();
diff --git a/src/core/hle/service/set/set.cpp b/src/core/hle/service/set/set.cpp
index aa7c924e7..fc3e424d0 100644
--- a/src/core/hle/service/set/set.cpp
+++ b/src/core/hle/service/set/set.cpp
@@ -9,8 +9,7 @@
9#include "core/hle/kernel/client_session.h" 9#include "core/hle/kernel/client_session.h"
10#include "core/hle/service/set/set.h" 10#include "core/hle/service/set/set.h"
11 11
12namespace Service { 12namespace Service::Set {
13namespace Set {
14 13
15void SET::GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx) { 14void SET::GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx) {
16 IPC::RequestParser rp{ctx}; 15 IPC::RequestParser rp{ctx};
@@ -36,9 +35,9 @@ SET::SET() : ServiceFramework("set") {
36 {5, nullptr, "GetAvailableLanguageCodes2"}, 35 {5, nullptr, "GetAvailableLanguageCodes2"},
37 {6, nullptr, "GetAvailableLanguageCodeCount2"}, 36 {6, nullptr, "GetAvailableLanguageCodeCount2"},
38 {7, nullptr, "GetKeyCodeMap"}, 37 {7, nullptr, "GetKeyCodeMap"},
38 {8, nullptr, "GetQuestFlag"},
39 }; 39 };
40 RegisterHandlers(functions); 40 RegisterHandlers(functions);
41} 41}
42 42
43} // namespace Set 43} // namespace Service::Set
44} // namespace Service
diff --git a/src/core/hle/service/set/set.h b/src/core/hle/service/set/set.h
index 7b7814ed1..6a465949f 100644
--- a/src/core/hle/service/set/set.h
+++ b/src/core/hle/service/set/set.h
@@ -6,8 +6,7 @@
6 6
7#include "core/hle/service/service.h" 7#include "core/hle/service/service.h"
8 8
9namespace Service { 9namespace Service::Set {
10namespace Set {
11 10
12class SET final : public ServiceFramework<SET> { 11class SET final : public ServiceFramework<SET> {
13public: 12public:
@@ -18,5 +17,4 @@ private:
18 void GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx); 17 void GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx);
19}; 18};
20 19
21} // namespace Set 20} // namespace Service::Set
22} // namespace Service
diff --git a/src/core/hle/service/set/set_cal.cpp b/src/core/hle/service/set/set_cal.cpp
index 6231acd96..7066ef725 100644
--- a/src/core/hle/service/set/set_cal.cpp
+++ b/src/core/hle/service/set/set_cal.cpp
@@ -4,8 +4,7 @@
4 4
5#include "core/hle/service/set/set_cal.h" 5#include "core/hle/service/set/set_cal.h"
6 6
7namespace Service { 7namespace Service::Set {
8namespace Set {
9 8
10SET_CAL::SET_CAL() : ServiceFramework("set:cal") { 9SET_CAL::SET_CAL() : ServiceFramework("set:cal") {
11 static const FunctionInfo functions[] = { 10 static const FunctionInfo functions[] = {
@@ -32,9 +31,17 @@ SET_CAL::SET_CAL() : ServiceFramework("set:cal") {
32 {21, nullptr, "GetEticketDeviceKey"}, 31 {21, nullptr, "GetEticketDeviceKey"},
33 {22, nullptr, "GetSpeakerParameter"}, 32 {22, nullptr, "GetSpeakerParameter"},
34 {23, nullptr, "GetLcdVendorId"}, 33 {23, nullptr, "GetLcdVendorId"},
34 {24, nullptr, "GetEciDeviceCertificate2"},
35 {25, nullptr, "GetEciDeviceKey2"},
36 {26, nullptr, "GetAmiiboKey"},
37 {27, nullptr, "GetAmiiboEcqvCertificate"},
38 {28, nullptr, "GetAmiiboEcdsaCertificate"},
39 {29, nullptr, "GetAmiiboEcqvBlsKey"},
40 {30, nullptr, "GetAmiiboEcqvBlsCertificate"},
41 {31, nullptr, "GetAmiiboEcqvBlsRootCertificate"},
42 {32, nullptr, "GetUnknownId"},
35 }; 43 };
36 RegisterHandlers(functions); 44 RegisterHandlers(functions);
37} 45}
38 46
39} // namespace Set 47} // namespace Service::Set
40} // namespace Service
diff --git a/src/core/hle/service/set/set_cal.h b/src/core/hle/service/set/set_cal.h
index 9c0b851d0..bb50336aa 100644
--- a/src/core/hle/service/set/set_cal.h
+++ b/src/core/hle/service/set/set_cal.h
@@ -6,8 +6,7 @@
6 6
7#include "core/hle/service/service.h" 7#include "core/hle/service/service.h"
8 8
9namespace Service { 9namespace Service::Set {
10namespace Set {
11 10
12class SET_CAL final : public ServiceFramework<SET_CAL> { 11class SET_CAL final : public ServiceFramework<SET_CAL> {
13public: 12public:
@@ -15,5 +14,4 @@ public:
15 ~SET_CAL() = default; 14 ~SET_CAL() = default;
16}; 15};
17 16
18} // namespace Set 17} // namespace Service::Set
19} // namespace Service
diff --git a/src/core/hle/service/set/set_fd.cpp b/src/core/hle/service/set/set_fd.cpp
index 8320d4250..c9f938716 100644
--- a/src/core/hle/service/set/set_fd.cpp
+++ b/src/core/hle/service/set/set_fd.cpp
@@ -4,8 +4,7 @@
4 4
5#include "core/hle/service/set/set_fd.h" 5#include "core/hle/service/set/set_fd.h"
6 6
7namespace Service { 7namespace Service::Set {
8namespace Set {
9 8
10SET_FD::SET_FD() : ServiceFramework("set:fd") { 9SET_FD::SET_FD() : ServiceFramework("set:fd") {
11 static const FunctionInfo functions[] = { 10 static const FunctionInfo functions[] = {
@@ -21,5 +20,4 @@ SET_FD::SET_FD() : ServiceFramework("set:fd") {
21 RegisterHandlers(functions); 20 RegisterHandlers(functions);
22} 21}
23 22
24} // namespace Set 23} // namespace Service::Set
25} // namespace Service
diff --git a/src/core/hle/service/set/set_fd.h b/src/core/hle/service/set/set_fd.h
index 65b36bcb3..dbd850bc7 100644
--- a/src/core/hle/service/set/set_fd.h
+++ b/src/core/hle/service/set/set_fd.h
@@ -6,8 +6,7 @@
6 6
7#include "core/hle/service/service.h" 7#include "core/hle/service/service.h"
8 8
9namespace Service { 9namespace Service::Set {
10namespace Set {
11 10
12class SET_FD final : public ServiceFramework<SET_FD> { 11class SET_FD final : public ServiceFramework<SET_FD> {
13public: 12public:
@@ -15,5 +14,4 @@ public:
15 ~SET_FD() = default; 14 ~SET_FD() = default;
16}; 15};
17 16
18} // namespace Set 17} // namespace Service::Set
19} // namespace Service
diff --git a/src/core/hle/service/set/set_sys.cpp b/src/core/hle/service/set/set_sys.cpp
index 363abd10a..fa85277fe 100644
--- a/src/core/hle/service/set/set_sys.cpp
+++ b/src/core/hle/service/set/set_sys.cpp
@@ -7,8 +7,7 @@
7#include "core/hle/kernel/client_port.h" 7#include "core/hle/kernel/client_port.h"
8#include "core/hle/service/set/set_sys.h" 8#include "core/hle/service/set/set_sys.h"
9 9
10namespace Service { 10namespace Service::Set {
11namespace Set {
12 11
13void SET_SYS::GetColorSetId(Kernel::HLERequestContext& ctx) { 12void SET_SYS::GetColorSetId(Kernel::HLERequestContext& ctx) {
14 13
@@ -27,6 +26,7 @@ SET_SYS::SET_SYS() : ServiceFramework("set:sys") {
27 {2, nullptr, "GetNetworkSettings"}, 26 {2, nullptr, "GetNetworkSettings"},
28 {3, nullptr, "GetFirmwareVersion"}, 27 {3, nullptr, "GetFirmwareVersion"},
29 {4, nullptr, "GetFirmwareVersion2"}, 28 {4, nullptr, "GetFirmwareVersion2"},
29 {5, nullptr, "GetFirmwareVersionDigest"},
30 {7, nullptr, "GetLockScreenFlag"}, 30 {7, nullptr, "GetLockScreenFlag"},
31 {8, nullptr, "SetLockScreenFlag"}, 31 {8, nullptr, "SetLockScreenFlag"},
32 {9, nullptr, "GetBacklightSettings"}, 32 {9, nullptr, "GetBacklightSettings"},
@@ -159,9 +159,17 @@ SET_SYS::SET_SYS() : ServiceFramework("set:sys") {
159 {138, nullptr, "GetWebInspectorFlag"}, 159 {138, nullptr, "GetWebInspectorFlag"},
160 {139, nullptr, "GetAllowedSslHosts"}, 160 {139, nullptr, "GetAllowedSslHosts"},
161 {140, nullptr, "GetHostFsMountPoint"}, 161 {140, nullptr, "GetHostFsMountPoint"},
162 {141, nullptr, "GetRequiresRunRepairTimeReviser"},
163 {142, nullptr, "SetRequiresRunRepairTimeReviser"},
164 {143, nullptr, "SetBlePairingSettings"},
165 {144, nullptr, "GetBlePairingSettings"},
166 {145, nullptr, "GetConsoleSixAxisSensorAngularVelocityTimeBias"},
167 {146, nullptr, "SetConsoleSixAxisSensorAngularVelocityTimeBias"},
168 {147, nullptr, "GetConsoleSixAxisSensorAngularAcceleration"},
169 {148, nullptr, "SetConsoleSixAxisSensorAngularAcceleration"},
170 {149, nullptr, "GetRebootlessSystemUpdateVersion"},
162 }; 171 };
163 RegisterHandlers(functions); 172 RegisterHandlers(functions);
164} 173}
165 174
166} // namespace Set 175} // namespace Service::Set
167} // namespace Service
diff --git a/src/core/hle/service/set/set_sys.h b/src/core/hle/service/set/set_sys.h
index 105f1a3c7..b77a97cde 100644
--- a/src/core/hle/service/set/set_sys.h
+++ b/src/core/hle/service/set/set_sys.h
@@ -6,8 +6,7 @@
6 6
7#include "core/hle/service/service.h" 7#include "core/hle/service/service.h"
8 8
9namespace Service { 9namespace Service::Set {
10namespace Set {
11 10
12class SET_SYS final : public ServiceFramework<SET_SYS> { 11class SET_SYS final : public ServiceFramework<SET_SYS> {
13public: 12public:
@@ -18,5 +17,4 @@ private:
18 void GetColorSetId(Kernel::HLERequestContext& ctx); 17 void GetColorSetId(Kernel::HLERequestContext& ctx);
19}; 18};
20 19
21} // namespace Set 20} // namespace Service::Set
22} // namespace Service
diff --git a/src/core/hle/service/set/settings.cpp b/src/core/hle/service/set/settings.cpp
index c6bc9e240..cf5541ca8 100644
--- a/src/core/hle/service/set/settings.cpp
+++ b/src/core/hle/service/set/settings.cpp
@@ -8,8 +8,7 @@
8#include "core/hle/service/set/set_sys.h" 8#include "core/hle/service/set/set_sys.h"
9#include "core/hle/service/set/settings.h" 9#include "core/hle/service/set/settings.h"
10 10
11namespace Service { 11namespace Service::Set {
12namespace Set {
13 12
14void InstallInterfaces(SM::ServiceManager& service_manager) { 13void InstallInterfaces(SM::ServiceManager& service_manager) {
15 std::make_shared<SET>()->InstallAsService(service_manager); 14 std::make_shared<SET>()->InstallAsService(service_manager);
@@ -18,5 +17,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
18 std::make_shared<SET_SYS>()->InstallAsService(service_manager); 17 std::make_shared<SET_SYS>()->InstallAsService(service_manager);
19} 18}
20 19
21} // namespace Set 20} // namespace Service::Set
22} // namespace Service
diff --git a/src/core/hle/service/set/settings.h b/src/core/hle/service/set/settings.h
index 6c8d5a58c..6606ce776 100644
--- a/src/core/hle/service/set/settings.h
+++ b/src/core/hle/service/set/settings.h
@@ -6,11 +6,9 @@
6 6
7#include "core/hle/service/service.h" 7#include "core/hle/service/service.h"
8 8
9namespace Service { 9namespace Service::Set {
10namespace Set {
11 10
12/// Registers all Settings services with the specified service manager. 11/// Registers all Settings services with the specified service manager.
13void InstallInterfaces(SM::ServiceManager& service_manager); 12void InstallInterfaces(SM::ServiceManager& service_manager);
14 13
15} // namespace Set 14} // namespace Service::Set
16} // namespace Service
diff --git a/src/core/hle/service/sm/controller.cpp b/src/core/hle/service/sm/controller.cpp
index e12c53442..13e31620d 100644
--- a/src/core/hle/service/sm/controller.cpp
+++ b/src/core/hle/service/sm/controller.cpp
@@ -7,8 +7,7 @@
7#include "core/hle/kernel/session.h" 7#include "core/hle/kernel/session.h"
8#include "core/hle/service/sm/controller.h" 8#include "core/hle/service/sm/controller.h"
9 9
10namespace Service { 10namespace Service::SM {
11namespace SM {
12 11
13void Controller::ConvertSessionToDomain(Kernel::HLERequestContext& ctx) { 12void Controller::ConvertSessionToDomain(Kernel::HLERequestContext& ctx) {
14 ASSERT_MSG(!ctx.Session()->IsDomain(), "session is alread a domain"); 13 ASSERT_MSG(!ctx.Session()->IsDomain(), "session is alread a domain");
@@ -58,5 +57,4 @@ Controller::Controller() : ServiceFramework("IpcController") {
58 RegisterHandlers(functions); 57 RegisterHandlers(functions);
59} 58}
60 59
61} // namespace SM 60} // namespace Service::SM
62} // namespace Service
diff --git a/src/core/hle/service/sm/controller.h b/src/core/hle/service/sm/controller.h
index 7b4bc4b75..a4de52cd2 100644
--- a/src/core/hle/service/sm/controller.h
+++ b/src/core/hle/service/sm/controller.h
@@ -6,8 +6,7 @@
6 6
7#include "core/hle/service/service.h" 7#include "core/hle/service/service.h"
8 8
9namespace Service { 9namespace Service::SM {
10namespace SM {
11 10
12class Controller final : public ServiceFramework<Controller> { 11class Controller final : public ServiceFramework<Controller> {
13public: 12public:
@@ -21,5 +20,4 @@ private:
21 void QueryPointerBufferSize(Kernel::HLERequestContext& ctx); 20 void QueryPointerBufferSize(Kernel::HLERequestContext& ctx);
22}; 21};
23 22
24} // namespace SM 23} // namespace Service::SM
25} // namespace Service
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp
index bc72512a0..4578fc05f 100644
--- a/src/core/hle/service/sm/sm.cpp
+++ b/src/core/hle/service/sm/sm.cpp
@@ -12,8 +12,9 @@
12#include "core/hle/service/sm/controller.h" 12#include "core/hle/service/sm/controller.h"
13#include "core/hle/service/sm/sm.h" 13#include "core/hle/service/sm/sm.h"
14 14
15namespace Service { 15namespace Service::SM {
16namespace SM { 16
17ServiceManager::~ServiceManager() = default;
17 18
18void ServiceManager::InvokeControlRequest(Kernel::HLERequestContext& context) { 19void ServiceManager::InvokeControlRequest(Kernel::HLERequestContext& context) {
19 controller_interface->InvokeRequest(context); 20 controller_interface->InvokeRequest(context);
@@ -73,7 +74,7 @@ ResultVal<Kernel::SharedPtr<Kernel::ClientSession>> ServiceManager::ConnectToSer
73 return client_port->Connect(); 74 return client_port->Connect();
74} 75}
75 76
76std::shared_ptr<ServiceManager> g_service_manager; 77SM::~SM() = default;
77 78
78/** 79/**
79 * SM::Initialize service function 80 * SM::Initialize service function
@@ -132,5 +133,4 @@ SM::SM(std::shared_ptr<ServiceManager> service_manager)
132 RegisterHandlers(functions); 133 RegisterHandlers(functions);
133} 134}
134 135
135} // namespace SM 136} // namespace Service::SM
136} // namespace Service
diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h
index 11fa788ca..13f5c4c28 100644
--- a/src/core/hle/service/sm/sm.h
+++ b/src/core/hle/service/sm/sm.h
@@ -17,14 +17,13 @@ class ServerPort;
17class SessionRequestHandler; 17class SessionRequestHandler;
18} // namespace Kernel 18} // namespace Kernel
19 19
20namespace Service { 20namespace Service::SM {
21namespace SM {
22 21
23/// Interface to "sm:" service 22/// Interface to "sm:" service
24class SM final : public ServiceFramework<SM> { 23class SM final : public ServiceFramework<SM> {
25public: 24public:
26 SM(std::shared_ptr<ServiceManager> service_manager); 25 SM(std::shared_ptr<ServiceManager> service_manager);
27 ~SM() = default; 26 ~SM() override;
28 27
29private: 28private:
30 void Initialize(Kernel::HLERequestContext& ctx); 29 void Initialize(Kernel::HLERequestContext& ctx);
@@ -45,6 +44,8 @@ class ServiceManager {
45public: 44public:
46 static void InstallInterfaces(std::shared_ptr<ServiceManager> self); 45 static void InstallInterfaces(std::shared_ptr<ServiceManager> self);
47 46
47 ~ServiceManager();
48
48 ResultVal<Kernel::SharedPtr<Kernel::ServerPort>> RegisterService(std::string name, 49 ResultVal<Kernel::SharedPtr<Kernel::ServerPort>> RegisterService(std::string name,
49 unsigned int max_sessions); 50 unsigned int max_sessions);
50 ResultVal<Kernel::SharedPtr<Kernel::ClientPort>> GetServicePort(const std::string& name); 51 ResultVal<Kernel::SharedPtr<Kernel::ClientPort>> GetServicePort(const std::string& name);
@@ -60,7 +61,4 @@ private:
60 std::unordered_map<std::string, Kernel::SharedPtr<Kernel::ClientPort>> registered_services; 61 std::unordered_map<std::string, Kernel::SharedPtr<Kernel::ClientPort>> registered_services;
61}; 62};
62 63
63extern std::shared_ptr<ServiceManager> g_service_manager; 64} // namespace Service::SM
64
65} // namespace SM
66} // namespace Service
diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp
index 790ff82b3..f99809bed 100644
--- a/src/core/hle/service/sockets/bsd.cpp
+++ b/src/core/hle/service/sockets/bsd.cpp
@@ -5,8 +5,7 @@
5#include "core/hle/ipc_helpers.h" 5#include "core/hle/ipc_helpers.h"
6#include "core/hle/service/sockets/bsd.h" 6#include "core/hle/service/sockets/bsd.h"
7 7
8namespace Service { 8namespace Service::Sockets {
9namespace Sockets {
10 9
11void BSD::RegisterClient(Kernel::HLERequestContext& ctx) { 10void BSD::RegisterClient(Kernel::HLERequestContext& ctx) {
12 LOG_WARNING(Service, "(STUBBED) called"); 11 LOG_WARNING(Service, "(STUBBED) called");
@@ -79,12 +78,36 @@ BSD::BSD(const char* name) : ServiceFramework(name) {
79 {0, &BSD::RegisterClient, "RegisterClient"}, 78 {0, &BSD::RegisterClient, "RegisterClient"},
80 {1, &BSD::StartMonitoring, "StartMonitoring"}, 79 {1, &BSD::StartMonitoring, "StartMonitoring"},
81 {2, &BSD::Socket, "Socket"}, 80 {2, &BSD::Socket, "Socket"},
81 {3, nullptr, "SocketExempt"},
82 {4, nullptr, "Open"},
83 {5, nullptr, "Select"},
84 {6, nullptr, "Poll"},
85 {7, nullptr, "Sysctl"},
86 {8, nullptr, "Recv"},
87 {9, nullptr, "RecvFrom"},
88 {10, nullptr, "Send"},
82 {11, &BSD::SendTo, "SendTo"}, 89 {11, &BSD::SendTo, "SendTo"},
90 {12, nullptr, "Accept"},
91 {13, nullptr, "Bind"},
83 {14, &BSD::Connect, "Connect"}, 92 {14, &BSD::Connect, "Connect"},
93 {15, nullptr, "GetPeerName"},
94 {16, nullptr, "GetSockName"},
95 {17, nullptr, "GetSockOpt"},
96 {18, nullptr, "Listen"},
97 {19, nullptr, "Ioctl"},
98 {20, nullptr, "Fcntl"},
99 {21, nullptr, "SetSockOpt"},
100 {22, nullptr, "Shutdown"},
101 {23, nullptr, "ShutdownAllSockets"},
102 {24, nullptr, "Write"},
103 {25, nullptr, "Read"},
84 {26, &BSD::Close, "Close"}, 104 {26, &BSD::Close, "Close"},
105 {27, nullptr, "DuplicateSocket"},
106 {28, nullptr, "GetResourceStatistics"},
107 {29, nullptr, "RecvMMsg"},
108 {30, nullptr, "SendMMsg"},
85 }; 109 };
86 RegisterHandlers(functions); 110 RegisterHandlers(functions);
87} 111}
88 112
89} // namespace Sockets 113} // namespace Service::Sockets
90} // namespace Service
diff --git a/src/core/hle/service/sockets/bsd.h b/src/core/hle/service/sockets/bsd.h
index 32d949e95..a6b1ca7d0 100644
--- a/src/core/hle/service/sockets/bsd.h
+++ b/src/core/hle/service/sockets/bsd.h
@@ -7,8 +7,7 @@
7#include "core/hle/kernel/hle_ipc.h" 7#include "core/hle/kernel/hle_ipc.h"
8#include "core/hle/service/service.h" 8#include "core/hle/service/service.h"
9 9
10namespace Service { 10namespace Service::Sockets {
11namespace Sockets {
12 11
13class BSD final : public ServiceFramework<BSD> { 12class BSD final : public ServiceFramework<BSD> {
14public: 13public:
@@ -27,5 +26,4 @@ private:
27 u32 next_fd = 1; 26 u32 next_fd = 1;
28}; 27};
29 28
30} // namespace Sockets 29} // namespace Service::Sockets
31} // namespace Service
diff --git a/src/core/hle/service/sockets/nsd.cpp b/src/core/hle/service/sockets/nsd.cpp
index e3542d325..8682dc2e0 100644
--- a/src/core/hle/service/sockets/nsd.cpp
+++ b/src/core/hle/service/sockets/nsd.cpp
@@ -4,8 +4,7 @@
4 4
5#include "core/hle/service/sockets/nsd.h" 5#include "core/hle/service/sockets/nsd.h"
6 6
7namespace Service { 7namespace Service::Sockets {
8namespace Sockets {
9 8
10NSD::NSD(const char* name) : ServiceFramework(name) { 9NSD::NSD(const char* name) : ServiceFramework(name) {
11 static const FunctionInfo functions[] = { 10 static const FunctionInfo functions[] = {
@@ -30,5 +29,4 @@ NSD::NSD(const char* name) : ServiceFramework(name) {
30 RegisterHandlers(functions); 29 RegisterHandlers(functions);
31} 30}
32 31
33} // namespace Sockets 32} // namespace Service::Sockets
34} // namespace Service
diff --git a/src/core/hle/service/sockets/nsd.h b/src/core/hle/service/sockets/nsd.h
index a7c15a860..3b7edfc43 100644
--- a/src/core/hle/service/sockets/nsd.h
+++ b/src/core/hle/service/sockets/nsd.h
@@ -7,8 +7,7 @@
7#include "core/hle/kernel/hle_ipc.h" 7#include "core/hle/kernel/hle_ipc.h"
8#include "core/hle/service/service.h" 8#include "core/hle/service/service.h"
9 9
10namespace Service { 10namespace Service::Sockets {
11namespace Sockets {
12 11
13class NSD final : public ServiceFramework<NSD> { 12class NSD final : public ServiceFramework<NSD> {
14public: 13public:
@@ -16,5 +15,4 @@ public:
16 ~NSD() = default; 15 ~NSD() = default;
17}; 16};
18 17
19} // namespace Sockets 18} // namespace Service::Sockets
20} // namespace Service
diff --git a/src/core/hle/service/sockets/sfdnsres.cpp b/src/core/hle/service/sockets/sfdnsres.cpp
index eb4b5fa57..d235c4cfd 100644
--- a/src/core/hle/service/sockets/sfdnsres.cpp
+++ b/src/core/hle/service/sockets/sfdnsres.cpp
@@ -5,8 +5,7 @@
5#include "core/hle/ipc_helpers.h" 5#include "core/hle/ipc_helpers.h"
6#include "core/hle/service/sockets/sfdnsres.h" 6#include "core/hle/service/sockets/sfdnsres.h"
7 7
8namespace Service { 8namespace Service::Sockets {
9namespace Sockets {
10 9
11void SFDNSRES::GetAddrInfo(Kernel::HLERequestContext& ctx) { 10void SFDNSRES::GetAddrInfo(Kernel::HLERequestContext& ctx) {
12 IPC::RequestParser rp{ctx}; 11 IPC::RequestParser rp{ctx};
@@ -30,9 +29,9 @@ SFDNSRES::SFDNSRES() : ServiceFramework("sfdnsres") {
30 {7, nullptr, "GetNameInfo"}, 29 {7, nullptr, "GetNameInfo"},
31 {8, nullptr, "RequestCancelHandle"}, 30 {8, nullptr, "RequestCancelHandle"},
32 {9, nullptr, "CancelSocketCall"}, 31 {9, nullptr, "CancelSocketCall"},
32 {11, nullptr, "ClearDnsIpServerAddressArray"},
33 }; 33 };
34 RegisterHandlers(functions); 34 RegisterHandlers(functions);
35} 35}
36 36
37} // namespace Sockets 37} // namespace Service::Sockets
38} // namespace Service
diff --git a/src/core/hle/service/sockets/sfdnsres.h b/src/core/hle/service/sockets/sfdnsres.h
index c07cc1594..62c7e35bf 100644
--- a/src/core/hle/service/sockets/sfdnsres.h
+++ b/src/core/hle/service/sockets/sfdnsres.h
@@ -7,8 +7,7 @@
7#include "core/hle/kernel/hle_ipc.h" 7#include "core/hle/kernel/hle_ipc.h"
8#include "core/hle/service/service.h" 8#include "core/hle/service/service.h"
9 9
10namespace Service { 10namespace Service::Sockets {
11namespace Sockets {
12 11
13class SFDNSRES final : public ServiceFramework<SFDNSRES> { 12class SFDNSRES final : public ServiceFramework<SFDNSRES> {
14public: 13public:
@@ -19,5 +18,4 @@ private:
19 void GetAddrInfo(Kernel::HLERequestContext& ctx); 18 void GetAddrInfo(Kernel::HLERequestContext& ctx);
20}; 19};
21 20
22} // namespace Sockets 21} // namespace Service::Sockets
23} // namespace Service
diff --git a/src/core/hle/service/sockets/sockets.cpp b/src/core/hle/service/sockets/sockets.cpp
index cedc276d9..05bd10d35 100644
--- a/src/core/hle/service/sockets/sockets.cpp
+++ b/src/core/hle/service/sockets/sockets.cpp
@@ -7,8 +7,7 @@
7#include "core/hle/service/sockets/sfdnsres.h" 7#include "core/hle/service/sockets/sfdnsres.h"
8#include "core/hle/service/sockets/sockets.h" 8#include "core/hle/service/sockets/sockets.h"
9 9
10namespace Service { 10namespace Service::Sockets {
11namespace Sockets {
12 11
13void InstallInterfaces(SM::ServiceManager& service_manager) { 12void InstallInterfaces(SM::ServiceManager& service_manager) {
14 std::make_shared<BSD>("bsd:s")->InstallAsService(service_manager); 13 std::make_shared<BSD>("bsd:s")->InstallAsService(service_manager);
@@ -18,5 +17,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
18 std::make_shared<SFDNSRES>()->InstallAsService(service_manager); 17 std::make_shared<SFDNSRES>()->InstallAsService(service_manager);
19} 18}
20 19
21} // namespace Sockets 20} // namespace Service::Sockets
22} // namespace Service
diff --git a/src/core/hle/service/sockets/sockets.h b/src/core/hle/service/sockets/sockets.h
index 7e89c8d2c..ca8a6a7e0 100644
--- a/src/core/hle/service/sockets/sockets.h
+++ b/src/core/hle/service/sockets/sockets.h
@@ -6,11 +6,9 @@
6 6
7#include "core/hle/service/service.h" 7#include "core/hle/service/service.h"
8 8
9namespace Service { 9namespace Service::Sockets {
10namespace Sockets {
11 10
12/// Registers all Sockets services with the specified service manager. 11/// Registers all Sockets services with the specified service manager.
13void InstallInterfaces(SM::ServiceManager& service_manager); 12void InstallInterfaces(SM::ServiceManager& service_manager);
14 13
15} // namespace Sockets 14} // namespace Service::Sockets
16} // namespace Service
diff --git a/src/core/hle/service/spl/csrng.cpp b/src/core/hle/service/spl/csrng.cpp
index cde05717a..b9e6b799d 100644
--- a/src/core/hle/service/spl/csrng.cpp
+++ b/src/core/hle/service/spl/csrng.cpp
@@ -4,8 +4,7 @@
4 4
5#include "core/hle/service/spl/csrng.h" 5#include "core/hle/service/spl/csrng.h"
6 6
7namespace Service { 7namespace Service::SPL {
8namespace SPL {
9 8
10CSRNG::CSRNG(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "csrng") { 9CSRNG::CSRNG(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "csrng") {
11 static const FunctionInfo functions[] = { 10 static const FunctionInfo functions[] = {
@@ -14,5 +13,4 @@ CSRNG::CSRNG(std::shared_ptr<Module> module) : Module::Interface(std::move(modul
14 RegisterHandlers(functions); 13 RegisterHandlers(functions);
15} 14}
16 15
17} // namespace SPL 16} // namespace Service::SPL
18} // namespace Service
diff --git a/src/core/hle/service/spl/csrng.h b/src/core/hle/service/spl/csrng.h
index 59ca794dd..3f849b5a7 100644
--- a/src/core/hle/service/spl/csrng.h
+++ b/src/core/hle/service/spl/csrng.h
@@ -6,13 +6,11 @@
6 6
7#include "core/hle/service/spl/module.h" 7#include "core/hle/service/spl/module.h"
8 8
9namespace Service { 9namespace Service::SPL {
10namespace SPL {
11 10
12class CSRNG final : public Module::Interface { 11class CSRNG final : public Module::Interface {
13public: 12public:
14 explicit CSRNG(std::shared_ptr<Module> module); 13 explicit CSRNG(std::shared_ptr<Module> module);
15}; 14};
16 15
17} // namespace SPL 16} // namespace Service::SPL
18} // namespace Service
diff --git a/src/core/hle/service/spl/module.cpp b/src/core/hle/service/spl/module.cpp
index fc1bcd94c..3f5a342a7 100644
--- a/src/core/hle/service/spl/module.cpp
+++ b/src/core/hle/service/spl/module.cpp
@@ -11,8 +11,7 @@
11#include "core/hle/service/spl/module.h" 11#include "core/hle/service/spl/module.h"
12#include "core/hle/service/spl/spl.h" 12#include "core/hle/service/spl/spl.h"
13 13
14namespace Service { 14namespace Service::SPL {
15namespace SPL {
16 15
17Module::Interface::Interface(std::shared_ptr<Module> module, const char* name) 16Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
18 : ServiceFramework(name), module(std::move(module)) {} 17 : ServiceFramework(name), module(std::move(module)) {}
@@ -38,5 +37,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
38 std::make_shared<SPL>(module)->InstallAsService(service_manager); 37 std::make_shared<SPL>(module)->InstallAsService(service_manager);
39} 38}
40 39
41} // namespace SPL 40} // namespace Service::SPL
42} // namespace Service
diff --git a/src/core/hle/service/spl/module.h b/src/core/hle/service/spl/module.h
index 12cdb2980..6ab91b400 100644
--- a/src/core/hle/service/spl/module.h
+++ b/src/core/hle/service/spl/module.h
@@ -6,8 +6,7 @@
6 6
7#include "core/hle/service/service.h" 7#include "core/hle/service/service.h"
8 8
9namespace Service { 9namespace Service::SPL {
10namespace SPL {
11 10
12class Module final { 11class Module final {
13public: 12public:
@@ -25,5 +24,4 @@ public:
25/// Registers all SPL services with the specified service manager. 24/// Registers all SPL services with the specified service manager.
26void InstallInterfaces(SM::ServiceManager& service_manager); 25void InstallInterfaces(SM::ServiceManager& service_manager);
27 26
28} // namespace SPL 27} // namespace Service::SPL
29} // namespace Service
diff --git a/src/core/hle/service/spl/spl.cpp b/src/core/hle/service/spl/spl.cpp
index deab29b91..bb1e03342 100644
--- a/src/core/hle/service/spl/spl.cpp
+++ b/src/core/hle/service/spl/spl.cpp
@@ -4,8 +4,7 @@
4 4
5#include "core/hle/service/spl/spl.h" 5#include "core/hle/service/spl/spl.h"
6 6
7namespace Service { 7namespace Service::SPL {
8namespace SPL {
9 8
10SPL::SPL(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "spl:") { 9SPL::SPL(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "spl:") {
11 static const FunctionInfo functions[] = { 10 static const FunctionInfo functions[] = {
@@ -33,9 +32,14 @@ SPL::SPL(std::shared_ptr<Module> module) : Module::Interface(std::move(module),
33 {23, nullptr, "GetSplWaitEvent"}, 32 {23, nullptr, "GetSplWaitEvent"},
34 {24, nullptr, "SetSharedData"}, 33 {24, nullptr, "SetSharedData"},
35 {25, nullptr, "GetSharedData"}, 34 {25, nullptr, "GetSharedData"},
35 {26, nullptr, "ImportSslRsaKey"},
36 {27, nullptr, "SecureExpModWithSslKey"},
37 {28, nullptr, "ImportEsRsaKey"},
38 {29, nullptr, "SecureExpModWithEsKey"},
39 {30, nullptr, "EncryptManuRsaKeyForImport"},
40 {31, nullptr, "GetPackage2Hash"},
36 }; 41 };
37 RegisterHandlers(functions); 42 RegisterHandlers(functions);
38} 43}
39 44
40} // namespace SPL 45} // namespace Service::SPL
41} // namespace Service
diff --git a/src/core/hle/service/spl/spl.h b/src/core/hle/service/spl/spl.h
index 9fd6059af..69c4c1747 100644
--- a/src/core/hle/service/spl/spl.h
+++ b/src/core/hle/service/spl/spl.h
@@ -6,13 +6,11 @@
6 6
7#include "core/hle/service/spl/module.h" 7#include "core/hle/service/spl/module.h"
8 8
9namespace Service { 9namespace Service::SPL {
10namespace SPL {
11 10
12class SPL final : public Module::Interface { 11class SPL final : public Module::Interface {
13public: 12public:
14 explicit SPL(std::shared_ptr<Module> module); 13 explicit SPL(std::shared_ptr<Module> module);
15}; 14};
16 15
17} // namespace SPL 16} // namespace Service::SPL
18} // namespace Service
diff --git a/src/core/hle/service/ssl/ssl.cpp b/src/core/hle/service/ssl/ssl.cpp
index 01a03ec83..11d438728 100644
--- a/src/core/hle/service/ssl/ssl.cpp
+++ b/src/core/hle/service/ssl/ssl.cpp
@@ -5,8 +5,7 @@
5#include "core/hle/ipc_helpers.h" 5#include "core/hle/ipc_helpers.h"
6#include "core/hle/service/ssl/ssl.h" 6#include "core/hle/service/ssl/ssl.h"
7 7
8namespace Service { 8namespace Service::SSL {
9namespace SSL {
10 9
11class ISslConnection final : public ServiceFramework<ISslConnection> { 10class ISslConnection final : public ServiceFramework<ISslConnection> {
12public: 11public:
@@ -107,5 +106,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
107 std::make_shared<SSL>()->InstallAsService(service_manager); 106 std::make_shared<SSL>()->InstallAsService(service_manager);
108} 107}
109 108
110} // namespace SSL 109} // namespace Service::SSL
111} // namespace Service
diff --git a/src/core/hle/service/ssl/ssl.h b/src/core/hle/service/ssl/ssl.h
index 7fcff5ccd..87538a639 100644
--- a/src/core/hle/service/ssl/ssl.h
+++ b/src/core/hle/service/ssl/ssl.h
@@ -6,8 +6,7 @@
6 6
7#include "core/hle/service/service.h" 7#include "core/hle/service/service.h"
8 8
9namespace Service { 9namespace Service::SSL {
10namespace SSL {
11 10
12class SSL final : public ServiceFramework<SSL> { 11class SSL final : public ServiceFramework<SSL> {
13public: 12public:
@@ -21,5 +20,4 @@ private:
21/// Registers all SSL services with the specified service manager. 20/// Registers all SSL services with the specified service manager.
22void InstallInterfaces(SM::ServiceManager& service_manager); 21void InstallInterfaces(SM::ServiceManager& service_manager);
23 22
24} // namespace SSL 23} // namespace Service::SSL
25} // namespace Service
diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp
index c3e46f866..2604ecc1c 100644
--- a/src/core/hle/service/time/time.cpp
+++ b/src/core/hle/service/time/time.cpp
@@ -12,15 +12,18 @@
12#include "core/hle/service/time/time_s.h" 12#include "core/hle/service/time/time_s.h"
13#include "core/hle/service/time/time_u.h" 13#include "core/hle/service/time/time_u.h"
14 14
15namespace Service { 15namespace Service::Time {
16namespace Time {
17 16
18class ISystemClock final : public ServiceFramework<ISystemClock> { 17class ISystemClock final : public ServiceFramework<ISystemClock> {
19public: 18public:
20 ISystemClock() : ServiceFramework("ISystemClock") { 19 ISystemClock() : ServiceFramework("ISystemClock") {
21 static const FunctionInfo functions[] = { 20 static const FunctionInfo functions[] = {
22 {0, &ISystemClock::GetCurrentTime, "GetCurrentTime"}, 21 {0, &ISystemClock::GetCurrentTime, "GetCurrentTime"},
23 {2, &ISystemClock::GetSystemClockContext, "GetSystemClockContext"}}; 22 {1, nullptr, "SetCurrentTime"},
23 {2, &ISystemClock::GetSystemClockContext, "GetSystemClockContext"},
24 {3, nullptr, "SetSystemClockContext"},
25
26 };
24 RegisterHandlers(functions); 27 RegisterHandlers(functions);
25 } 28 }
26 29
@@ -162,5 +165,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
162 std::make_shared<TIME_U>(time)->InstallAsService(service_manager); 165 std::make_shared<TIME_U>(time)->InstallAsService(service_manager);
163} 166}
164 167
165} // namespace Time 168} // namespace Service::Time
166} // namespace Service
diff --git a/src/core/hle/service/time/time.h b/src/core/hle/service/time/time.h
index 197029e7a..12fe1995a 100644
--- a/src/core/hle/service/time/time.h
+++ b/src/core/hle/service/time/time.h
@@ -6,8 +6,7 @@
6 6
7#include "core/hle/service/service.h" 7#include "core/hle/service/service.h"
8 8
9namespace Service { 9namespace Service::Time {
10namespace Time {
11 10
12// TODO(Rozelette) RE this structure 11// TODO(Rozelette) RE this structure
13struct LocationName { 12struct LocationName {
@@ -66,5 +65,4 @@ public:
66/// Registers all Time services with the specified service manager. 65/// Registers all Time services with the specified service manager.
67void InstallInterfaces(SM::ServiceManager& service_manager); 66void InstallInterfaces(SM::ServiceManager& service_manager);
68 67
69} // namespace Time 68} // namespace Service::Time
70} // namespace Service
diff --git a/src/core/hle/service/time/time_s.cpp b/src/core/hle/service/time/time_s.cpp
index b172b2bd6..0b599ea00 100644
--- a/src/core/hle/service/time/time_s.cpp
+++ b/src/core/hle/service/time/time_s.cpp
@@ -4,8 +4,7 @@
4 4
5#include "core/hle/service/time/time_s.h" 5#include "core/hle/service/time/time_s.h"
6 6
7namespace Service { 7namespace Service::Time {
8namespace Time {
9 8
10TIME_S::TIME_S(std::shared_ptr<Module> time) : Module::Interface(std::move(time), "time:s") { 9TIME_S::TIME_S(std::shared_ptr<Module> time) : Module::Interface(std::move(time), "time:s") {
11 static const FunctionInfo functions[] = { 10 static const FunctionInfo functions[] = {
@@ -14,9 +13,19 @@ TIME_S::TIME_S(std::shared_ptr<Module> time) : Module::Interface(std::move(time)
14 {2, &TIME_S::GetStandardSteadyClock, "GetStandardSteadyClock"}, 13 {2, &TIME_S::GetStandardSteadyClock, "GetStandardSteadyClock"},
15 {3, &TIME_S::GetTimeZoneService, "GetTimeZoneService"}, 14 {3, &TIME_S::GetTimeZoneService, "GetTimeZoneService"},
16 {4, &TIME_S::GetStandardLocalSystemClock, "GetStandardLocalSystemClock"}, 15 {4, &TIME_S::GetStandardLocalSystemClock, "GetStandardLocalSystemClock"},
16 {5, nullptr, "GetEphemeralNetworkSystemClock"},
17 {50, nullptr, "SetStandardSteadyClockInternalOffset"},
18 {100, nullptr, "IsStandardUserSystemClockAutomaticCorrectionEnabled"},
19 {101, nullptr, "SetStandardUserSystemClockAutomaticCorrectionEnabled"},
20 {102, nullptr, "GetStandardUserSystemClockInitialYear"},
21 {200, nullptr, "IsStandardNetworkSystemClockAccuracySufficient"},
22 {300, nullptr, "CalculateMonotonicSystemClockBaseTimePoint"},
23 {400, nullptr, "GetClockSnapshot"},
24 {401, nullptr, "GetClockSnapshotFromSystemClockContext"},
25 {500, nullptr, "CalculateStandardUserSystemClockDifferenceByUser"},
26 {501, nullptr, "CalculateSpanBetween"},
17 }; 27 };
18 RegisterHandlers(functions); 28 RegisterHandlers(functions);
19} 29}
20 30
21} // namespace Time 31} // namespace Service::Time
22} // namespace Service
diff --git a/src/core/hle/service/time/time_s.h b/src/core/hle/service/time/time_s.h
index abc2a8c5a..4a2daa513 100644
--- a/src/core/hle/service/time/time_s.h
+++ b/src/core/hle/service/time/time_s.h
@@ -6,13 +6,11 @@
6 6
7#include "core/hle/service/time/time.h" 7#include "core/hle/service/time/time.h"
8 8
9namespace Service { 9namespace Service::Time {
10namespace Time {
11 10
12class TIME_S final : public Module::Interface { 11class TIME_S final : public Module::Interface {
13public: 12public:
14 explicit TIME_S(std::shared_ptr<Module> time); 13 explicit TIME_S(std::shared_ptr<Module> time);
15}; 14};
16 15
17} // namespace Time 16} // namespace Service::Time
18} // namespace Service
diff --git a/src/core/hle/service/time/time_u.cpp b/src/core/hle/service/time/time_u.cpp
index fc1ace325..1ed42c419 100644
--- a/src/core/hle/service/time/time_u.cpp
+++ b/src/core/hle/service/time/time_u.cpp
@@ -4,8 +4,7 @@
4 4
5#include "core/hle/service/time/time_u.h" 5#include "core/hle/service/time/time_u.h"
6 6
7namespace Service { 7namespace Service::Time {
8namespace Time {
9 8
10TIME_U::TIME_U(std::shared_ptr<Module> time) : Module::Interface(std::move(time), "time:u") { 9TIME_U::TIME_U(std::shared_ptr<Module> time) : Module::Interface(std::move(time), "time:u") {
11 static const FunctionInfo functions[] = { 10 static const FunctionInfo functions[] = {
@@ -14,9 +13,19 @@ TIME_U::TIME_U(std::shared_ptr<Module> time) : Module::Interface(std::move(time)
14 {2, &TIME_U::GetStandardSteadyClock, "GetStandardSteadyClock"}, 13 {2, &TIME_U::GetStandardSteadyClock, "GetStandardSteadyClock"},
15 {3, &TIME_U::GetTimeZoneService, "GetTimeZoneService"}, 14 {3, &TIME_U::GetTimeZoneService, "GetTimeZoneService"},
16 {4, &TIME_U::GetStandardLocalSystemClock, "GetStandardLocalSystemClock"}, 15 {4, &TIME_U::GetStandardLocalSystemClock, "GetStandardLocalSystemClock"},
16 {5, nullptr, "GetEphemeralNetworkSystemClock"},
17 {50, nullptr, "SetStandardSteadyClockInternalOffset"},
18 {100, nullptr, "IsStandardUserSystemClockAutomaticCorrectionEnabled"},
19 {101, nullptr, "SetStandardUserSystemClockAutomaticCorrectionEnabled"},
20 {102, nullptr, "GetStandardUserSystemClockInitialYear"},
21 {200, nullptr, "IsStandardNetworkSystemClockAccuracySufficient"},
22 {300, nullptr, "CalculateMonotonicSystemClockBaseTimePoint"},
23 {400, nullptr, "GetClockSnapshot"},
24 {401, nullptr, "GetClockSnapshotFromSystemClockContext"},
25 {500, nullptr, "CalculateStandardUserSystemClockDifferenceByUser"},
26 {501, nullptr, "CalculateSpanBetween"},
17 }; 27 };
18 RegisterHandlers(functions); 28 RegisterHandlers(functions);
19} 29}
20 30
21} // namespace Time 31} // namespace Service::Time
22} // namespace Service
diff --git a/src/core/hle/service/time/time_u.h b/src/core/hle/service/time/time_u.h
index f99d25057..3724bcdc7 100644
--- a/src/core/hle/service/time/time_u.h
+++ b/src/core/hle/service/time/time_u.h
@@ -6,13 +6,11 @@
6 6
7#include "core/hle/service/time/time.h" 7#include "core/hle/service/time/time.h"
8 8
9namespace Service { 9namespace Service::Time {
10namespace Time {
11 10
12class TIME_U final : public Module::Interface { 11class TIME_U final : public Module::Interface {
13public: 12public:
14 explicit TIME_U(std::shared_ptr<Module> time); 13 explicit TIME_U(std::shared_ptr<Module> time);
15}; 14};
16 15
17} // namespace Time 16} // namespace Service::Time
18} // namespace Service
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index 715206493..36ae2215f 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -21,8 +21,7 @@
21#include "video_core/renderer_base.h" 21#include "video_core/renderer_base.h"
22#include "video_core/video_core.h" 22#include "video_core/video_core.h"
23 23
24namespace Service { 24namespace Service::VI {
25namespace VI {
26 25
27struct DisplayInfo { 26struct DisplayInfo {
28 char display_name[0x40]{"Default"}; 27 char display_name[0x40]{"Default"};
@@ -150,7 +149,7 @@ private:
150 149
151class NativeWindow : public Parcel { 150class NativeWindow : public Parcel {
152public: 151public:
153 explicit NativeWindow(u32 id) : Parcel() { 152 explicit NativeWindow(u32 id) {
154 data.id = id; 153 data.id = id;
155 } 154 }
156 ~NativeWindow() override = default; 155 ~NativeWindow() override = default;
@@ -197,7 +196,7 @@ public:
197 196
198class IGBPConnectResponseParcel : public Parcel { 197class IGBPConnectResponseParcel : public Parcel {
199public: 198public:
200 explicit IGBPConnectResponseParcel(u32 width, u32 height) : Parcel() { 199 explicit IGBPConnectResponseParcel(u32 width, u32 height) {
201 data.width = width; 200 data.width = width;
202 data.height = height; 201 data.height = height;
203 } 202 }
@@ -247,10 +246,6 @@ public:
247}; 246};
248 247
249class IGBPSetPreallocatedBufferResponseParcel : public Parcel { 248class IGBPSetPreallocatedBufferResponseParcel : public Parcel {
250public:
251 IGBPSetPreallocatedBufferResponseParcel() : Parcel() {}
252 ~IGBPSetPreallocatedBufferResponseParcel() override = default;
253
254protected: 249protected:
255 void SerializeData() override { 250 void SerializeData() override {
256 // TODO(Subv): Find out what this means 251 // TODO(Subv): Find out what this means
@@ -289,7 +284,7 @@ static_assert(sizeof(BufferProducerFence) == 36, "BufferProducerFence has wrong
289 284
290class IGBPDequeueBufferResponseParcel : public Parcel { 285class IGBPDequeueBufferResponseParcel : public Parcel {
291public: 286public:
292 explicit IGBPDequeueBufferResponseParcel(u32 slot) : Parcel(), slot(slot) {} 287 explicit IGBPDequeueBufferResponseParcel(u32 slot) : slot(slot) {}
293 ~IGBPDequeueBufferResponseParcel() override = default; 288 ~IGBPDequeueBufferResponseParcel() override = default;
294 289
295protected: 290protected:
@@ -383,7 +378,7 @@ public:
383 378
384class IGBPQueueBufferResponseParcel : public Parcel { 379class IGBPQueueBufferResponseParcel : public Parcel {
385public: 380public:
386 explicit IGBPQueueBufferResponseParcel(u32 width, u32 height) : Parcel() { 381 explicit IGBPQueueBufferResponseParcel(u32 width, u32 height) {
387 data.width = width; 382 data.width = width;
388 data.height = height; 383 data.height = height;
389 } 384 }
@@ -424,7 +419,7 @@ public:
424 419
425class IGBPQueryResponseParcel : public Parcel { 420class IGBPQueryResponseParcel : public Parcel {
426public: 421public:
427 explicit IGBPQueryResponseParcel(u32 value) : Parcel(), value(value) {} 422 explicit IGBPQueryResponseParcel(u32 value) : value(value) {}
428 ~IGBPQueryResponseParcel() override = default; 423 ~IGBPQueryResponseParcel() override = default;
429 424
430protected: 425protected:
@@ -580,7 +575,48 @@ public:
580 ISystemDisplayService() : ServiceFramework("ISystemDisplayService") { 575 ISystemDisplayService() : ServiceFramework("ISystemDisplayService") {
581 static const FunctionInfo functions[] = { 576 static const FunctionInfo functions[] = {
582 {1200, nullptr, "GetZOrderCountMin"}, 577 {1200, nullptr, "GetZOrderCountMin"},
578 {1202, nullptr, "GetZOrderCountMax"},
579 {1203, nullptr, "GetDisplayLogicalResolution"},
580 {1204, nullptr, "SetDisplayMagnification"},
581 {2201, nullptr, "SetLayerPosition"},
582 {2203, nullptr, "SetLayerSize"},
583 {2204, nullptr, "GetLayerZ"},
583 {2205, &ISystemDisplayService::SetLayerZ, "SetLayerZ"}, 584 {2205, &ISystemDisplayService::SetLayerZ, "SetLayerZ"},
585 {2207, &ISystemDisplayService::SetLayerVisibility, "SetLayerVisibility"},
586 {2209, nullptr, "SetLayerAlpha"},
587 {2312, nullptr, "CreateStrayLayer"},
588 {2400, nullptr, "OpenIndirectLayer"},
589 {2401, nullptr, "CloseIndirectLayer"},
590 {2402, nullptr, "FlipIndirectLayer"},
591 {3000, nullptr, "ListDisplayModes"},
592 {3001, nullptr, "ListDisplayRgbRanges"},
593 {3002, nullptr, "ListDisplayContentTypes"},
594 {3200, nullptr, "GetDisplayMode"},
595 {3201, nullptr, "SetDisplayMode"},
596 {3202, nullptr, "GetDisplayUnderscan"},
597 {3203, nullptr, "SetDisplayUnderscan"},
598 {3204, nullptr, "GetDisplayContentType"},
599 {3205, nullptr, "SetDisplayContentType"},
600 {3206, nullptr, "GetDisplayRgbRange"},
601 {3207, nullptr, "SetDisplayRgbRange"},
602 {3208, nullptr, "GetDisplayCmuMode"},
603 {3209, nullptr, "SetDisplayCmuMode"},
604 {3210, nullptr, "GetDisplayContrastRatio"},
605 {3211, nullptr, "SetDisplayContrastRatio"},
606 {3214, nullptr, "GetDisplayGamma"},
607 {3215, nullptr, "SetDisplayGamma"},
608 {3216, nullptr, "GetDisplayCmuLuma"},
609 {3217, nullptr, "SetDisplayCmuLuma"},
610 {8225, nullptr, "GetSharedBufferMemoryHandleId"},
611 {8250, nullptr, "OpenSharedLayer"},
612 {8251, nullptr, "CloseSharedLayer"},
613 {8252, nullptr, "ConnectSharedLayer"},
614 {8253, nullptr, "DisconnectSharedLayer"},
615 {8254, nullptr, "AcquireSharedFrameBuffer"},
616 {8255, nullptr, "PresentSharedFrameBuffer"},
617 {8256, nullptr, "GetSharedFrameBufferAcquirableEvent"},
618 {8257, nullptr, "FillSharedFrameBufferColor"},
619 {8258, nullptr, "CancelSharedFrameBuffer"},
584 }; 620 };
585 RegisterHandlers(functions); 621 RegisterHandlers(functions);
586 } 622 }
@@ -596,6 +632,16 @@ private:
596 IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0); 632 IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0);
597 rb.Push(RESULT_SUCCESS); 633 rb.Push(RESULT_SUCCESS);
598 } 634 }
635
636 void SetLayerVisibility(Kernel::HLERequestContext& ctx) {
637 IPC::RequestParser rp{ctx};
638 u64 layer_id = rp.Pop<u64>();
639 bool visibility = rp.Pop<bool>();
640 IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0);
641 rb.Push(RESULT_SUCCESS);
642 LOG_WARNING(Service_VI, "(STUBBED) called, layer_id=0x%x, visibility=%u", layer_id,
643 visibility);
644 }
599}; 645};
600 646
601class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> { 647class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> {
@@ -603,10 +649,72 @@ public:
603 explicit IManagerDisplayService(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger) 649 explicit IManagerDisplayService(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger)
604 : ServiceFramework("IManagerDisplayService"), nv_flinger(std::move(nv_flinger)) { 650 : ServiceFramework("IManagerDisplayService"), nv_flinger(std::move(nv_flinger)) {
605 static const FunctionInfo functions[] = { 651 static const FunctionInfo functions[] = {
652 {200, nullptr, "AllocateProcessHeapBlock"},
653 {201, nullptr, "FreeProcessHeapBlock"},
606 {1020, &IManagerDisplayService::CloseDisplay, "CloseDisplay"}, 654 {1020, &IManagerDisplayService::CloseDisplay, "CloseDisplay"},
607 {1102, nullptr, "GetDisplayResolution"}, 655 {1102, nullptr, "GetDisplayResolution"},
608 {2010, &IManagerDisplayService::CreateManagedLayer, "CreateManagedLayer"}, 656 {2010, &IManagerDisplayService::CreateManagedLayer, "CreateManagedLayer"},
657 {2011, nullptr, "DestroyManagedLayer"},
658 {2050, nullptr, "CreateIndirectLayer"},
659 {2051, nullptr, "DestroyIndirectLayer"},
660 {2052, nullptr, "CreateIndirectProducerEndPoint"},
661 {2053, nullptr, "DestroyIndirectProducerEndPoint"},
662 {2054, nullptr, "CreateIndirectConsumerEndPoint"},
663 {2055, nullptr, "DestroyIndirectConsumerEndPoint"},
664 {2300, nullptr, "AcquireLayerTexturePresentingEvent"},
665 {2301, nullptr, "ReleaseLayerTexturePresentingEvent"},
666 {2302, nullptr, "GetDisplayHotplugEvent"},
667 {2402, nullptr, "GetDisplayHotplugState"},
668 {2501, nullptr, "GetCompositorErrorInfo"},
669 {2601, nullptr, "GetDisplayErrorEvent"},
670 {4201, nullptr, "SetDisplayAlpha"},
671 {4203, nullptr, "SetDisplayLayerStack"},
672 {4205, nullptr, "SetDisplayPowerState"},
673 {4206, nullptr, "SetDefaultDisplay"},
609 {6000, &IManagerDisplayService::AddToLayerStack, "AddToLayerStack"}, 674 {6000, &IManagerDisplayService::AddToLayerStack, "AddToLayerStack"},
675 {6001, nullptr, "RemoveFromLayerStack"},
676 {6002, &IManagerDisplayService::SetLayerVisibility, "SetLayerVisibility"},
677 {6003, nullptr, "SetLayerConfig"},
678 {6004, nullptr, "AttachLayerPresentationTracer"},
679 {6005, nullptr, "DetachLayerPresentationTracer"},
680 {6006, nullptr, "StartLayerPresentationRecording"},
681 {6007, nullptr, "StopLayerPresentationRecording"},
682 {6008, nullptr, "StartLayerPresentationFenceWait"},
683 {6009, nullptr, "StopLayerPresentationFenceWait"},
684 {6010, nullptr, "GetLayerPresentationAllFencesExpiredEvent"},
685 {7000, nullptr, "SetContentVisibility"},
686 {8000, nullptr, "SetConductorLayer"},
687 {8100, nullptr, "SetIndirectProducerFlipOffset"},
688 {8200, nullptr, "CreateSharedBufferStaticStorage"},
689 {8201, nullptr, "CreateSharedBufferTransferMemory"},
690 {8202, nullptr, "DestroySharedBuffer"},
691 {8203, nullptr, "BindSharedLowLevelLayerToManagedLayer"},
692 {8204, nullptr, "BindSharedLowLevelLayerToIndirectLayer"},
693 {8207, nullptr, "UnbindSharedLowLevelLayer"},
694 {8208, nullptr, "ConnectSharedLowLevelLayerToSharedBuffer"},
695 {8209, nullptr, "DisconnectSharedLowLevelLayerFromSharedBuffer"},
696 {8210, nullptr, "CreateSharedLayer"},
697 {8211, nullptr, "DestroySharedLayer"},
698 {8216, nullptr, "AttachSharedLayerToLowLevelLayer"},
699 {8217, nullptr, "ForceDetachSharedLayerFromLowLevelLayer"},
700 {8218, nullptr, "StartDetachSharedLayerFromLowLevelLayer"},
701 {8219, nullptr, "FinishDetachSharedLayerFromLowLevelLayer"},
702 {8220, nullptr, "GetSharedLayerDetachReadyEvent"},
703 {8221, nullptr, "GetSharedLowLevelLayerSynchronizedEvent"},
704 {8222, nullptr, "CheckSharedLowLevelLayerSynchronized"},
705 {8223, nullptr, "RegisterSharedBufferImporterAruid"},
706 {8224, nullptr, "UnregisterSharedBufferImporterAruid"},
707 {8227, nullptr, "CreateSharedBufferProcessHeap"},
708 {8228, nullptr, "GetSharedLayerLayerStacks"},
709 {8229, nullptr, "SetSharedLayerLayerStacks"},
710 {8291, nullptr, "PresentDetachedSharedFrameBufferToLowLevelLayer"},
711 {8292, nullptr, "FillDetachedSharedFrameBufferColor"},
712 {8293, nullptr, "GetDetachedSharedFrameBufferImage"},
713 {8294, nullptr, "SetDetachedSharedFrameBufferImage"},
714 {8295, nullptr, "CopyDetachedSharedFrameBufferImage"},
715 {8296, nullptr, "SetDetachedSharedFrameBufferSubImage"},
716 {8297, nullptr, "GetSharedFrameBufferContentParameter"},
717 {8298, nullptr, "ExpandStartupLogoOnSharedFrameBuffer"},
610 }; 718 };
611 RegisterHandlers(functions); 719 RegisterHandlers(functions);
612 } 720 }
@@ -647,6 +755,16 @@ private:
647 rb.Push(RESULT_SUCCESS); 755 rb.Push(RESULT_SUCCESS);
648 } 756 }
649 757
758 void SetLayerVisibility(Kernel::HLERequestContext& ctx) {
759 IPC::RequestParser rp{ctx};
760 u64 layer_id = rp.Pop<u64>();
761 bool visibility = rp.Pop<bool>();
762 IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0);
763 rb.Push(RESULT_SUCCESS);
764 LOG_WARNING(Service_VI, "(STUBBED) called, layer_id=0x%x, visibility=%u", layer_id,
765 visibility);
766 }
767
650 std::shared_ptr<NVFlinger::NVFlinger> nv_flinger; 768 std::shared_ptr<NVFlinger::NVFlinger> nv_flinger;
651}; 769};
652 770
@@ -717,15 +835,15 @@ private:
717 IPC::RequestParser rp{ctx}; 835 IPC::RequestParser rp{ctx};
718 u64 display_id = rp.Pop<u64>(); 836 u64 display_id = rp.Pop<u64>();
719 837
720 IPC::ResponseBuilder rb = rp.MakeBuilder(4, 0, 0); 838 IPC::ResponseBuilder rb = rp.MakeBuilder(6, 0, 0);
721 rb.Push(RESULT_SUCCESS); 839 rb.Push(RESULT_SUCCESS);
722 840
723 if (Settings::values.use_docked_mode) { 841 if (Settings::values.use_docked_mode) {
724 rb.Push(static_cast<u32>(DisplayResolution::DockedWidth)); 842 rb.Push(static_cast<u64>(DisplayResolution::DockedWidth));
725 rb.Push(static_cast<u32>(DisplayResolution::DockedHeight)); 843 rb.Push(static_cast<u64>(DisplayResolution::DockedHeight));
726 } else { 844 } else {
727 rb.Push(static_cast<u32>(DisplayResolution::UndockedWidth)); 845 rb.Push(static_cast<u64>(DisplayResolution::UndockedWidth));
728 rb.Push(static_cast<u32>(DisplayResolution::UndockedHeight)); 846 rb.Push(static_cast<u64>(DisplayResolution::UndockedHeight));
729 } 847 }
730 } 848 }
731 849
@@ -825,13 +943,21 @@ IApplicationDisplayService::IApplicationDisplayService(
825 "GetIndirectDisplayTransactionService"}, 943 "GetIndirectDisplayTransactionService"},
826 {1000, &IApplicationDisplayService::ListDisplays, "ListDisplays"}, 944 {1000, &IApplicationDisplayService::ListDisplays, "ListDisplays"},
827 {1010, &IApplicationDisplayService::OpenDisplay, "OpenDisplay"}, 945 {1010, &IApplicationDisplayService::OpenDisplay, "OpenDisplay"},
946 {1011, nullptr, "OpenDefaultDisplay"},
828 {1020, &IApplicationDisplayService::CloseDisplay, "CloseDisplay"}, 947 {1020, &IApplicationDisplayService::CloseDisplay, "CloseDisplay"},
948 {1101, nullptr, "SetDisplayEnabled"},
829 {1102, &IApplicationDisplayService::GetDisplayResolution, "GetDisplayResolution"}, 949 {1102, &IApplicationDisplayService::GetDisplayResolution, "GetDisplayResolution"},
830 {2101, &IApplicationDisplayService::SetLayerScalingMode, "SetLayerScalingMode"},
831 {2020, &IApplicationDisplayService::OpenLayer, "OpenLayer"}, 950 {2020, &IApplicationDisplayService::OpenLayer, "OpenLayer"},
951 {2021, nullptr, "CloseLayer"},
832 {2030, &IApplicationDisplayService::CreateStrayLayer, "CreateStrayLayer"}, 952 {2030, &IApplicationDisplayService::CreateStrayLayer, "CreateStrayLayer"},
833 {2031, &IApplicationDisplayService::DestroyStrayLayer, "DestroyStrayLayer"}, 953 {2031, &IApplicationDisplayService::DestroyStrayLayer, "DestroyStrayLayer"},
954 {2101, &IApplicationDisplayService::SetLayerScalingMode, "SetLayerScalingMode"},
955 {2102, nullptr, "ConvertScalingMode"},
956 {2450, nullptr, "GetIndirectLayerImageMap"},
957 {2451, nullptr, "GetIndirectLayerImageCropMap"},
958 {2460, nullptr, "GetIndirectLayerImageRequiredMemoryInfo"},
834 {5202, &IApplicationDisplayService::GetDisplayVsyncEvent, "GetDisplayVsyncEvent"}, 959 {5202, &IApplicationDisplayService::GetDisplayVsyncEvent, "GetDisplayVsyncEvent"},
960 {5203, nullptr, "GetDisplayVsyncEventForDebug"},
835 }; 961 };
836 RegisterHandlers(functions); 962 RegisterHandlers(functions);
837} 963}
@@ -856,5 +982,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager,
856 std::make_shared<VI_U>(module, nv_flinger)->InstallAsService(service_manager); 982 std::make_shared<VI_U>(module, nv_flinger)->InstallAsService(service_manager);
857} 983}
858 984
859} // namespace VI 985} // namespace Service::VI
860} // namespace Service
diff --git a/src/core/hle/service/vi/vi.h b/src/core/hle/service/vi/vi.h
index 7f16fad8e..e8bda01d7 100644
--- a/src/core/hle/service/vi/vi.h
+++ b/src/core/hle/service/vi/vi.h
@@ -11,8 +11,7 @@ namespace CoreTiming {
11struct EventType; 11struct EventType;
12} 12}
13 13
14namespace Service { 14namespace Service::VI {
15namespace VI {
16 15
17enum class DisplayResolution : u32 { 16enum class DisplayResolution : u32 {
18 DockedWidth = 1920, 17 DockedWidth = 1920,
@@ -40,5 +39,4 @@ public:
40void InstallInterfaces(SM::ServiceManager& service_manager, 39void InstallInterfaces(SM::ServiceManager& service_manager,
41 std::shared_ptr<NVFlinger::NVFlinger> nv_flinger); 40 std::shared_ptr<NVFlinger::NVFlinger> nv_flinger);
42 41
43} // namespace VI 42} // namespace Service::VI
44} // namespace Service
diff --git a/src/core/hle/service/vi/vi_m.cpp b/src/core/hle/service/vi/vi_m.cpp
index 5781fa9ec..d47da565b 100644
--- a/src/core/hle/service/vi/vi_m.cpp
+++ b/src/core/hle/service/vi/vi_m.cpp
@@ -4,8 +4,7 @@
4 4
5#include "core/hle/service/vi/vi_m.h" 5#include "core/hle/service/vi/vi_m.h"
6 6
7namespace Service { 7namespace Service::VI {
8namespace VI {
9 8
10VI_M::VI_M(std::shared_ptr<Module> module, std::shared_ptr<NVFlinger::NVFlinger> nv_flinger) 9VI_M::VI_M(std::shared_ptr<Module> module, std::shared_ptr<NVFlinger::NVFlinger> nv_flinger)
11 : Module::Interface(std::move(module), "vi:m", std::move(nv_flinger)) { 10 : Module::Interface(std::move(module), "vi:m", std::move(nv_flinger)) {
@@ -16,5 +15,4 @@ VI_M::VI_M(std::shared_ptr<Module> module, std::shared_ptr<NVFlinger::NVFlinger>
16 RegisterHandlers(functions); 15 RegisterHandlers(functions);
17} 16}
18 17
19} // namespace VI 18} // namespace Service::VI
20} // namespace Service
diff --git a/src/core/hle/service/vi/vi_m.h b/src/core/hle/service/vi/vi_m.h
index 0f7b799d6..6abb9b3a3 100644
--- a/src/core/hle/service/vi/vi_m.h
+++ b/src/core/hle/service/vi/vi_m.h
@@ -6,13 +6,11 @@
6 6
7#include "core/hle/service/vi/vi.h" 7#include "core/hle/service/vi/vi.h"
8 8
9namespace Service { 9namespace Service::VI {
10namespace VI {
11 10
12class VI_M final : public Module::Interface { 11class VI_M final : public Module::Interface {
13public: 12public:
14 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);
15}; 14};
16 15
17} // namespace VI 16} // namespace Service::VI
18} // namespace Service
diff --git a/src/core/hle/service/vi/vi_s.cpp b/src/core/hle/service/vi/vi_s.cpp
index 1f937b2a8..8f82e797f 100644
--- a/src/core/hle/service/vi/vi_s.cpp
+++ b/src/core/hle/service/vi/vi_s.cpp
@@ -4,8 +4,7 @@
4 4
5#include "core/hle/service/vi/vi_s.h" 5#include "core/hle/service/vi/vi_s.h"
6 6
7namespace Service { 7namespace Service::VI {
8namespace VI {
9 8
10VI_S::VI_S(std::shared_ptr<Module> module, std::shared_ptr<NVFlinger::NVFlinger> nv_flinger) 9VI_S::VI_S(std::shared_ptr<Module> module, std::shared_ptr<NVFlinger::NVFlinger> nv_flinger)
11 : Module::Interface(std::move(module), "vi:s", std::move(nv_flinger)) { 10 : Module::Interface(std::move(module), "vi:s", std::move(nv_flinger)) {
@@ -16,5 +15,4 @@ VI_S::VI_S(std::shared_ptr<Module> module, std::shared_ptr<NVFlinger::NVFlinger>
16 RegisterHandlers(functions); 15 RegisterHandlers(functions);
17} 16}
18 17
19} // namespace VI 18} // namespace Service::VI
20} // namespace Service
diff --git a/src/core/hle/service/vi/vi_s.h b/src/core/hle/service/vi/vi_s.h
index 7b32fdddc..8f16f804f 100644
--- a/src/core/hle/service/vi/vi_s.h
+++ b/src/core/hle/service/vi/vi_s.h
@@ -6,13 +6,11 @@
6 6
7#include "core/hle/service/vi/vi.h" 7#include "core/hle/service/vi/vi.h"
8 8
9namespace Service { 9namespace Service::VI {
10namespace VI {
11 10
12class VI_S final : public Module::Interface { 11class VI_S final : public Module::Interface {
13public: 12public:
14 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);
15}; 14};
16 15
17} // namespace VI 16} // namespace Service::VI
18} // namespace Service
diff --git a/src/core/hle/service/vi/vi_u.cpp b/src/core/hle/service/vi/vi_u.cpp
index 14e375b86..b84aed1d5 100644
--- a/src/core/hle/service/vi/vi_u.cpp
+++ b/src/core/hle/service/vi/vi_u.cpp
@@ -4,17 +4,14 @@
4 4
5#include "core/hle/service/vi/vi_u.h" 5#include "core/hle/service/vi/vi_u.h"
6 6
7namespace Service { 7namespace Service::VI {
8namespace VI {
9 8
10VI_U::VI_U(std::shared_ptr<Module> module, std::shared_ptr<NVFlinger::NVFlinger> nv_flinger) 9VI_U::VI_U(std::shared_ptr<Module> module, std::shared_ptr<NVFlinger::NVFlinger> nv_flinger)
11 : Module::Interface(std::move(module), "vi:u", std::move(nv_flinger)) { 10 : Module::Interface(std::move(module), "vi:u", std::move(nv_flinger)) {
12 static const FunctionInfo functions[] = { 11 static const FunctionInfo functions[] = {
13 {0, &VI_U::GetDisplayService, "GetDisplayService"}, 12 {0, &VI_U::GetDisplayService, "GetDisplayService"},
14 {3, nullptr, "GetDisplayServiceWithProxyNameExchange"},
15 }; 13 };
16 RegisterHandlers(functions); 14 RegisterHandlers(functions);
17} 15}
18 16
19} // namespace VI 17} // namespace Service::VI
20} // namespace Service
diff --git a/src/core/hle/service/vi/vi_u.h b/src/core/hle/service/vi/vi_u.h
index c557a2235..e9b4f76b2 100644
--- a/src/core/hle/service/vi/vi_u.h
+++ b/src/core/hle/service/vi/vi_u.h
@@ -6,13 +6,11 @@
6 6
7#include "core/hle/service/vi/vi.h" 7#include "core/hle/service/vi/vi.h"
8 8
9namespace Service { 9namespace Service::VI {
10namespace VI {
11 10
12class VI_U final : public Module::Interface { 11class VI_U final : public Module::Interface {
13public: 12public:
14 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);
15}; 14};
16 15
17} // namespace VI 16} // namespace Service::VI
18} // namespace Service
diff --git a/src/core/perf_stats.cpp b/src/core/perf_stats.cpp
index ad3b56fcc..5f53b16d3 100644
--- a/src/core/perf_stats.cpp
+++ b/src/core/perf_stats.cpp
@@ -2,6 +2,7 @@
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>
5#include <chrono> 6#include <chrono>
6#include <mutex> 7#include <mutex>
7#include <thread> 8#include <thread>
@@ -87,7 +88,7 @@ void FrameLimiter::DoFrameLimiting(u64 current_system_time_us) {
87 frame_limiting_delta_err += microseconds(current_system_time_us - previous_system_time_us); 88 frame_limiting_delta_err += microseconds(current_system_time_us - previous_system_time_us);
88 frame_limiting_delta_err -= duration_cast<microseconds>(now - previous_walltime); 89 frame_limiting_delta_err -= duration_cast<microseconds>(now - previous_walltime);
89 frame_limiting_delta_err = 90 frame_limiting_delta_err =
90 MathUtil::Clamp(frame_limiting_delta_err, -MAX_LAG_TIME_US, MAX_LAG_TIME_US); 91 std::clamp(frame_limiting_delta_err, -MAX_LAG_TIME_US, MAX_LAG_TIME_US);
91 92
92 if (frame_limiting_delta_err > microseconds::zero()) { 93 if (frame_limiting_delta_err > microseconds::zero()) {
93 std::this_thread::sleep_for(frame_limiting_delta_err); 94 std::this_thread::sleep_for(frame_limiting_delta_err);
diff --git a/src/input_common/motion_emu.cpp b/src/input_common/motion_emu.cpp
index 59a035e70..caffe48cb 100644
--- a/src/input_common/motion_emu.cpp
+++ b/src/input_common/motion_emu.cpp
@@ -2,6 +2,7 @@
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>
5#include <chrono> 6#include <chrono>
6#include <mutex> 7#include <mutex>
7#include <thread> 8#include <thread>
@@ -43,8 +44,8 @@ public:
43 tilt_angle = 0; 44 tilt_angle = 0;
44 } else { 45 } else {
45 tilt_direction = mouse_move.Cast<float>(); 46 tilt_direction = mouse_move.Cast<float>();
46 tilt_angle = MathUtil::Clamp(tilt_direction.Normalize() * sensitivity, 0.0f, 47 tilt_angle =
47 MathUtil::PI * 0.5f); 48 std::clamp(tilt_direction.Normalize() * sensitivity, 0.0f, MathUtil::PI * 0.5f);
48 } 49 }
49 } 50 }
50 } 51 }
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index a710c4bc5..281810357 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -9,6 +9,7 @@ add_library(video_core STATIC
9 engines/maxwell_3d.h 9 engines/maxwell_3d.h
10 engines/maxwell_compute.cpp 10 engines/maxwell_compute.cpp
11 engines/maxwell_compute.h 11 engines/maxwell_compute.h
12 engines/shader_bytecode.h
12 gpu.cpp 13 gpu.cpp
13 gpu.h 14 gpu.h
14 macro_interpreter.cpp 15 macro_interpreter.cpp
@@ -27,6 +28,8 @@ add_library(video_core STATIC
27 renderer_opengl/gl_shader_decompiler.h 28 renderer_opengl/gl_shader_decompiler.h
28 renderer_opengl/gl_shader_gen.cpp 29 renderer_opengl/gl_shader_gen.cpp
29 renderer_opengl/gl_shader_gen.h 30 renderer_opengl/gl_shader_gen.h
31 renderer_opengl/gl_shader_manager.cpp
32 renderer_opengl/gl_shader_manager.h
30 renderer_opengl/gl_shader_util.cpp 33 renderer_opengl/gl_shader_util.cpp
31 renderer_opengl/gl_shader_util.h 34 renderer_opengl/gl_shader_util.h
32 renderer_opengl/gl_state.cpp 35 renderer_opengl/gl_state.cpp
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index 2d7c3152f..2a3ff234a 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -74,8 +74,6 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) {
74 74
75 regs.reg_array[method] = value; 75 regs.reg_array[method] = value;
76 76
77#define MAXWELL3D_REG_INDEX(field_name) (offsetof(Regs, field_name) / sizeof(u32))
78
79 switch (method) { 77 switch (method) {
80 case MAXWELL3D_REG_INDEX(code_address.code_address_high): 78 case MAXWELL3D_REG_INDEX(code_address.code_address_high):
81 case MAXWELL3D_REG_INDEX(code_address.code_address_low): { 79 case MAXWELL3D_REG_INDEX(code_address.code_address_low): {
@@ -136,7 +134,7 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) {
136 break; 134 break;
137 } 135 }
138 136
139#undef MAXWELL3D_REG_INDEX 137 VideoCore::g_renderer->Rasterizer()->NotifyMaxwellRegisterChanged(method);
140 138
141 if (debug_context) { 139 if (debug_context) {
142 debug_context->OnEvent(Tegra::DebugContext::Event::MaxwellCommandProcessed, nullptr); 140 debug_context->OnEvent(Tegra::DebugContext::Event::MaxwellCommandProcessed, nullptr);
@@ -165,6 +163,7 @@ void Maxwell3D::ProcessQueryGet() {
165void Maxwell3D::DrawArrays() { 163void Maxwell3D::DrawArrays() {
166 LOG_DEBUG(HW_GPU, "called, topology=%d, count=%d", regs.draw.topology.Value(), 164 LOG_DEBUG(HW_GPU, "called, topology=%d, count=%d", regs.draw.topology.Value(),
167 regs.vertex_buffer.count); 165 regs.vertex_buffer.count);
166 ASSERT_MSG(!(regs.index_array.count && regs.vertex_buffer.count), "Both indexed and direct?");
168 167
169 auto debug_context = Core::System::GetInstance().GetGPUDebugContext(); 168 auto debug_context = Core::System::GetInstance().GetGPUDebugContext();
170 169
@@ -176,7 +175,8 @@ void Maxwell3D::DrawArrays() {
176 debug_context->OnEvent(Tegra::DebugContext::Event::FinishedPrimitiveBatch, nullptr); 175 debug_context->OnEvent(Tegra::DebugContext::Event::FinishedPrimitiveBatch, nullptr);
177 } 176 }
178 177
179 VideoCore::g_renderer->Rasterizer()->AccelerateDrawBatch(false /*is_indexed*/); 178 const bool is_indexed{regs.index_array.count && !regs.vertex_buffer.count};
179 VideoCore::g_renderer->Rasterizer()->AccelerateDrawBatch(is_indexed);
180} 180}
181 181
182void Maxwell3D::ProcessCBBind(Regs::ShaderStage stage) { 182void Maxwell3D::ProcessCBBind(Regs::ShaderStage stage) {
@@ -218,10 +218,12 @@ Texture::TICEntry Maxwell3D::GetTICEntry(u32 tic_index) const {
218 Texture::TICEntry tic_entry; 218 Texture::TICEntry tic_entry;
219 Memory::ReadBlock(tic_address_cpu, &tic_entry, sizeof(Texture::TICEntry)); 219 Memory::ReadBlock(tic_address_cpu, &tic_entry, sizeof(Texture::TICEntry));
220 220
221 ASSERT_MSG(tic_entry.header_version == Texture::TICHeaderVersion::BlockLinear, 221 ASSERT_MSG(tic_entry.header_version == Texture::TICHeaderVersion::BlockLinear ||
222 "TIC versions other than BlockLinear are unimplemented"); 222 tic_entry.header_version == Texture::TICHeaderVersion::Pitch,
223 "TIC versions other than BlockLinear or Pitch are unimplemented");
223 224
224 ASSERT_MSG(tic_entry.texture_type == Texture::TextureType::Texture2D, 225 ASSERT_MSG((tic_entry.texture_type == Texture::TextureType::Texture2D) ||
226 (tic_entry.texture_type == Texture::TextureType::Texture2DNoMipmap),
225 "Texture types other than Texture2D are unimplemented"); 227 "Texture types other than Texture2D are unimplemented");
226 228
227 auto r_type = tic_entry.r_type.Value(); 229 auto r_type = tic_entry.r_type.Value();
@@ -301,5 +303,26 @@ u32 Maxwell3D::GetRegisterValue(u32 method) const {
301 return regs.reg_array[method]; 303 return regs.reg_array[method];
302} 304}
303 305
306bool Maxwell3D::IsShaderStageEnabled(Regs::ShaderStage stage) const {
307 // The Vertex stage is always enabled.
308 if (stage == Regs::ShaderStage::Vertex)
309 return true;
310
311 switch (stage) {
312 case Regs::ShaderStage::TesselationControl:
313 return regs.shader_config[static_cast<size_t>(Regs::ShaderProgram::TesselationControl)]
314 .enable != 0;
315 case Regs::ShaderStage::TesselationEval:
316 return regs.shader_config[static_cast<size_t>(Regs::ShaderProgram::TesselationEval)]
317 .enable != 0;
318 case Regs::ShaderStage::Geometry:
319 return regs.shader_config[static_cast<size_t>(Regs::ShaderProgram::Geometry)].enable != 0;
320 case Regs::ShaderStage::Fragment:
321 return regs.shader_config[static_cast<size_t>(Regs::ShaderProgram::Fragment)].enable != 0;
322 }
323
324 UNREACHABLE();
325}
326
304} // namespace Engines 327} // namespace Engines
305} // namespace Tegra 328} // namespace Tegra
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index 98b39b2ff..d4fcedace 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -20,6 +20,9 @@
20namespace Tegra { 20namespace Tegra {
21namespace Engines { 21namespace Engines {
22 22
23#define MAXWELL3D_REG_INDEX(field_name) \
24 (offsetof(Tegra::Engines::Maxwell3D::Regs, field_name) / sizeof(u32))
25
23class Maxwell3D final { 26class Maxwell3D final {
24public: 27public:
25 explicit Maxwell3D(MemoryManager& memory_manager); 28 explicit Maxwell3D(MemoryManager& memory_manager);
@@ -248,6 +251,52 @@ public:
248 Patches = 0xe, 251 Patches = 0xe,
249 }; 252 };
250 253
254 enum class IndexFormat : u32 {
255 UnsignedByte = 0x0,
256 UnsignedShort = 0x1,
257 UnsignedInt = 0x2,
258 };
259
260 struct Blend {
261 enum class Equation : u32 {
262 Add = 1,
263 Subtract = 2,
264 ReverseSubtract = 3,
265 Min = 4,
266 Max = 5,
267 };
268
269 enum class Factor : u32 {
270 Zero = 0x1,
271 One = 0x2,
272 SourceColor = 0x3,
273 OneMinusSourceColor = 0x4,
274 SourceAlpha = 0x5,
275 OneMinusSourceAlpha = 0x6,
276 DestAlpha = 0x7,
277 OneMinusDestAlpha = 0x8,
278 DestColor = 0x9,
279 OneMinusDestColor = 0xa,
280 SourceAlphaSaturate = 0xb,
281 Source1Color = 0x10,
282 OneMinusSource1Color = 0x11,
283 Source1Alpha = 0x12,
284 OneMinusSource1Alpha = 0x13,
285 ConstantColor = 0x61,
286 OneMinusConstantColor = 0x62,
287 ConstantAlpha = 0x63,
288 OneMinusConstantAlpha = 0x64,
289 };
290
291 u32 separate_alpha;
292 Equation equation_rgb;
293 Factor factor_source_rgb;
294 Factor factor_dest_rgb;
295 Equation equation_a;
296 Factor factor_source_a;
297 Factor factor_dest_a;
298 };
299
251 union { 300 union {
252 struct { 301 struct {
253 INSERT_PADDING_WORDS(0x200); 302 INSERT_PADDING_WORDS(0x200);
@@ -270,7 +319,15 @@ public:
270 } 319 }
271 } rt[NumRenderTargets]; 320 } rt[NumRenderTargets];
272 321
273 INSERT_PADDING_WORDS(0x80); 322 struct {
323 f32 scale_x;
324 f32 scale_y;
325 f32 scale_z;
326 u32 translate_x;
327 u32 translate_y;
328 u32 translate_z;
329 INSERT_PADDING_WORDS(2);
330 } viewport_transform[NumViewports];
274 331
275 struct { 332 struct {
276 union { 333 union {
@@ -375,7 +432,42 @@ public:
375 }; 432 };
376 } draw; 433 } draw;
377 434
378 INSERT_PADDING_WORDS(0x139); 435 INSERT_PADDING_WORDS(0x6B);
436
437 struct {
438 u32 start_addr_high;
439 u32 start_addr_low;
440 u32 end_addr_high;
441 u32 end_addr_low;
442 IndexFormat format;
443 u32 first;
444 u32 count;
445
446 unsigned FormatSizeInBytes() const {
447 switch (format) {
448 case IndexFormat::UnsignedByte:
449 return 1;
450 case IndexFormat::UnsignedShort:
451 return 2;
452 case IndexFormat::UnsignedInt:
453 return 4;
454 }
455 UNREACHABLE();
456 }
457
458 GPUVAddr StartAddress() const {
459 return static_cast<GPUVAddr>(
460 (static_cast<GPUVAddr>(start_addr_high) << 32) | start_addr_low);
461 }
462
463 GPUVAddr EndAddress() const {
464 return static_cast<GPUVAddr>((static_cast<GPUVAddr>(end_addr_high) << 32) |
465 end_addr_low);
466 }
467 } index_array;
468
469 INSERT_PADDING_WORDS(0xC7);
470
379 struct { 471 struct {
380 u32 query_address_high; 472 u32 query_address_high;
381 u32 query_address_low; 473 u32 query_address_low;
@@ -410,7 +502,9 @@ public:
410 } 502 }
411 } vertex_array[NumVertexArrays]; 503 } vertex_array[NumVertexArrays];
412 504
413 INSERT_PADDING_WORDS(0x40); 505 Blend blend;
506
507 INSERT_PADDING_WORDS(0x39);
414 508
415 struct { 509 struct {
416 u32 limit_high; 510 u32 limit_high;
@@ -427,14 +521,11 @@ public:
427 BitField<0, 1, u32> enable; 521 BitField<0, 1, u32> enable;
428 BitField<4, 4, ShaderProgram> program; 522 BitField<4, 4, ShaderProgram> program;
429 }; 523 };
430 u32 start_id; 524 u32 offset;
431 INSERT_PADDING_WORDS(1); 525 INSERT_PADDING_WORDS(14);
432 u32 gpr_alloc;
433 ShaderStage type;
434 INSERT_PADDING_WORDS(9);
435 } shader_config[MaxShaderProgram]; 526 } shader_config[MaxShaderProgram];
436 527
437 INSERT_PADDING_WORDS(0x8C); 528 INSERT_PADDING_WORDS(0x80);
438 529
439 struct { 530 struct {
440 u32 cb_size; 531 u32 cb_size;
@@ -507,6 +598,7 @@ public:
507 }; 598 };
508 599
509 State state{}; 600 State state{};
601 MemoryManager& memory_manager;
510 602
511 /// Reads a register value located at the input method address 603 /// Reads a register value located at the input method address
512 u32 GetRegisterValue(u32 method) const; 604 u32 GetRegisterValue(u32 method) const;
@@ -520,9 +612,10 @@ public:
520 /// Returns a list of enabled textures for the specified shader stage. 612 /// Returns a list of enabled textures for the specified shader stage.
521 std::vector<Texture::FullTextureInfo> GetStageTextures(Regs::ShaderStage stage) const; 613 std::vector<Texture::FullTextureInfo> GetStageTextures(Regs::ShaderStage stage) const;
522 614
523private: 615 /// Returns whether the specified shader stage is enabled or not.
524 MemoryManager& memory_manager; 616 bool IsShaderStageEnabled(Regs::ShaderStage stage) const;
525 617
618private:
526 std::unordered_map<u32, std::vector<u32>> uploaded_macros; 619 std::unordered_map<u32, std::vector<u32>> uploaded_macros;
527 620
528 /// Macro method that is currently being executed / being fed parameters. 621 /// Macro method that is currently being executed / being fed parameters.
@@ -564,6 +657,7 @@ private:
564 "Field " #field_name " has invalid position") 657 "Field " #field_name " has invalid position")
565 658
566ASSERT_REG_POSITION(rt, 0x200); 659ASSERT_REG_POSITION(rt, 0x200);
660ASSERT_REG_POSITION(viewport_transform[0], 0x280);
567ASSERT_REG_POSITION(viewport, 0x300); 661ASSERT_REG_POSITION(viewport, 0x300);
568ASSERT_REG_POSITION(vertex_buffer, 0x35D); 662ASSERT_REG_POSITION(vertex_buffer, 0x35D);
569ASSERT_REG_POSITION(zeta, 0x3F8); 663ASSERT_REG_POSITION(zeta, 0x3F8);
@@ -573,8 +667,10 @@ ASSERT_REG_POSITION(tsc, 0x557);
573ASSERT_REG_POSITION(tic, 0x55D); 667ASSERT_REG_POSITION(tic, 0x55D);
574ASSERT_REG_POSITION(code_address, 0x582); 668ASSERT_REG_POSITION(code_address, 0x582);
575ASSERT_REG_POSITION(draw, 0x585); 669ASSERT_REG_POSITION(draw, 0x585);
670ASSERT_REG_POSITION(index_array, 0x5F2);
576ASSERT_REG_POSITION(query, 0x6C0); 671ASSERT_REG_POSITION(query, 0x6C0);
577ASSERT_REG_POSITION(vertex_array[0], 0x700); 672ASSERT_REG_POSITION(vertex_array[0], 0x700);
673ASSERT_REG_POSITION(blend, 0x780);
578ASSERT_REG_POSITION(vertex_array_limit[0], 0x7C0); 674ASSERT_REG_POSITION(vertex_array_limit[0], 0x7C0);
579ASSERT_REG_POSITION(shader_config[0], 0x800); 675ASSERT_REG_POSITION(shader_config[0], 0x800);
580ASSERT_REG_POSITION(const_buffer, 0x8E0); 676ASSERT_REG_POSITION(const_buffer, 0x8E0);
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
new file mode 100644
index 000000000..5a006aee5
--- /dev/null
+++ b/src/video_core/engines/shader_bytecode.h
@@ -0,0 +1,439 @@
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 <bitset>
8#include <cstring>
9#include <map>
10#include <string>
11#include <vector>
12
13#include <boost/optional.hpp>
14
15#include "common/bit_field.h"
16#include "common/common_types.h"
17
18namespace Tegra {
19namespace Shader {
20
21struct Register {
22 // Register 255 is special cased to always be 0
23 static constexpr size_t ZeroIndex = 255;
24
25 constexpr Register() = default;
26
27 constexpr Register(u64 value) : value(value) {}
28
29 constexpr operator u64() const {
30 return value;
31 }
32
33 template <typename T>
34 constexpr u64 operator-(const T& oth) const {
35 return value - oth;
36 }
37
38 template <typename T>
39 constexpr u64 operator&(const T& oth) const {
40 return value & oth;
41 }
42
43 constexpr u64 operator&(const Register& oth) const {
44 return value & oth.value;
45 }
46
47 constexpr u64 operator~() const {
48 return ~value;
49 }
50
51private:
52 u64 value{};
53};
54
55union Attribute {
56 Attribute() = default;
57
58 constexpr explicit Attribute(u64 value) : value(value) {}
59
60 enum class Index : u64 {
61 Position = 7,
62 Attribute_0 = 8,
63 };
64
65 union {
66 BitField<22, 2, u64> element;
67 BitField<24, 6, Index> index;
68 BitField<47, 3, u64> size;
69 } fmt20;
70
71 union {
72 BitField<30, 2, u64> element;
73 BitField<32, 6, Index> index;
74 } fmt28;
75
76 BitField<39, 8, u64> reg;
77 u64 value{};
78};
79
80union Sampler {
81 Sampler() = default;
82
83 constexpr explicit Sampler(u64 value) : value(value) {}
84
85 enum class Index : u64 {
86 Sampler_0 = 8,
87 };
88
89 BitField<36, 13, Index> index;
90 u64 value{};
91};
92
93union Uniform {
94 BitField<20, 14, u64> offset;
95 BitField<34, 5, u64> index;
96};
97
98} // namespace Shader
99} // namespace Tegra
100
101namespace std {
102
103// TODO(bunnei): The below is forbidden by the C++ standard, but works fine. See #330.
104template <>
105struct make_unsigned<Tegra::Shader::Attribute> {
106 using type = Tegra::Shader::Attribute;
107};
108
109template <>
110struct make_unsigned<Tegra::Shader::Register> {
111 using type = Tegra::Shader::Register;
112};
113
114} // namespace std
115
116namespace Tegra {
117namespace Shader {
118
119enum class Pred : u64 {
120 UnusedIndex = 0x7,
121 NeverExecute = 0xF,
122};
123
124enum class PredCondition : u64 {
125 LessThan = 1,
126 Equal = 2,
127 LessEqual = 3,
128 GreaterThan = 4,
129 NotEqual = 5,
130 GreaterEqual = 6,
131 // TODO(Subv): Other condition types
132};
133
134enum class PredOperation : u64 {
135 And = 0,
136 Or = 1,
137 Xor = 2,
138};
139
140enum class SubOp : u64 {
141 Cos = 0x0,
142 Sin = 0x1,
143 Ex2 = 0x2,
144 Lg2 = 0x3,
145 Rcp = 0x4,
146 Rsq = 0x5,
147 Min = 0x8,
148};
149
150union Instruction {
151 Instruction& operator=(const Instruction& instr) {
152 value = instr.value;
153 return *this;
154 }
155
156 constexpr Instruction(u64 value) : value{value} {}
157
158 BitField<0, 8, Register> gpr0;
159 BitField<8, 8, Register> gpr8;
160 union {
161 BitField<16, 4, Pred> full_pred;
162 BitField<16, 3, u64> pred_index;
163 } pred;
164 BitField<19, 1, u64> negate_pred;
165 BitField<20, 8, Register> gpr20;
166 BitField<20, 7, SubOp> sub_op;
167 BitField<28, 8, Register> gpr28;
168 BitField<39, 8, Register> gpr39;
169 BitField<48, 16, u64> opcode;
170
171 union {
172 BitField<20, 19, u64> imm20_19;
173 BitField<20, 32, u64> imm20_32;
174 BitField<45, 1, u64> negate_b;
175 BitField<46, 1, u64> abs_a;
176 BitField<48, 1, u64> negate_a;
177 BitField<49, 1, u64> abs_b;
178 BitField<50, 1, u64> abs_d;
179 BitField<56, 1, u64> negate_imm;
180
181 float GetImm20_19() const {
182 float result{};
183 u32 imm{static_cast<u32>(imm20_19)};
184 imm <<= 12;
185 imm |= negate_imm ? 0x80000000 : 0;
186 std::memcpy(&result, &imm, sizeof(imm));
187 return result;
188 }
189
190 float GetImm20_32() const {
191 float result{};
192 u32 imm{static_cast<u32>(imm20_32)};
193 std::memcpy(&result, &imm, sizeof(imm));
194 return result;
195 }
196 } alu;
197
198 union {
199 BitField<48, 1, u64> negate_b;
200 BitField<49, 1, u64> negate_c;
201 } ffma;
202
203 union {
204 BitField<0, 3, u64> pred0;
205 BitField<3, 3, u64> pred3;
206 BitField<7, 1, u64> abs_a;
207 BitField<39, 3, u64> pred39;
208 BitField<42, 1, u64> neg_pred;
209 BitField<43, 1, u64> neg_a;
210 BitField<44, 1, u64> abs_b;
211 BitField<45, 2, PredOperation> op;
212 BitField<47, 1, u64> ftz;
213 BitField<48, 4, PredCondition> cond;
214 BitField<56, 1, u64> neg_b;
215 } fsetp;
216
217 BitField<61, 1, u64> is_b_imm;
218 BitField<60, 1, u64> is_b_gpr;
219 BitField<59, 1, u64> is_c_gpr;
220
221 Attribute attribute;
222 Uniform uniform;
223 Sampler sampler;
224
225 u64 value;
226};
227static_assert(sizeof(Instruction) == 0x8, "Incorrect structure size");
228static_assert(std::is_standard_layout<Instruction>::value,
229 "Structure does not have standard layout");
230
231class OpCode {
232public:
233 enum class Id {
234 KIL,
235 LD_A,
236 ST_A,
237 TEXQ, // Texture Query
238 TEXS, // Texture Fetch with scalar/non-vec4 source/destinations
239 TLDS, // Texture Load with scalar/non-vec4 source/destinations
240 EXIT,
241 IPA,
242 FFMA_IMM, // Fused Multiply and Add
243 FFMA_CR,
244 FFMA_RC,
245 FFMA_RR,
246 FADD_C,
247 FADD_R,
248 FADD_IMM,
249 FMUL_C,
250 FMUL_R,
251 FMUL_IMM,
252 FMUL32_IMM,
253 MUFU, // Multi-Function Operator
254 RRO, // Range Reduction Operator
255 F2F_C,
256 F2F_R,
257 F2F_IMM,
258 F2I_C,
259 F2I_R,
260 F2I_IMM,
261 I2F_C,
262 I2F_R,
263 I2F_IMM,
264 LOP32I,
265 MOV_C,
266 MOV_R,
267 MOV_IMM,
268 MOV32I,
269 SHR_C,
270 SHR_R,
271 SHR_IMM,
272 FSETP_C, // Set Predicate
273 FSETP_R,
274 FSETP_IMM,
275 ISETP_C,
276 ISETP_IMM,
277 ISETP_R,
278 };
279
280 enum class Type {
281 Trivial,
282 Arithmetic,
283 Ffma,
284 Flow,
285 Memory,
286 FloatPredicate,
287 IntegerPredicate,
288 Unknown,
289 };
290
291 class Matcher {
292 public:
293 Matcher(const char* const name, u16 mask, u16 expected, OpCode::Id id, OpCode::Type type)
294 : name{name}, mask{mask}, expected{expected}, id{id}, type{type} {}
295
296 const char* GetName() const {
297 return name;
298 }
299
300 u16 GetMask() const {
301 return mask;
302 }
303
304 Id GetId() const {
305 return id;
306 }
307
308 Type GetType() const {
309 return type;
310 }
311
312 /**
313 * Tests to see if the given instruction is the instruction this matcher represents.
314 * @param instruction The instruction to test
315 * @returns true if the given instruction matches.
316 */
317 bool Matches(u16 instruction) const {
318 return (instruction & mask) == expected;
319 }
320
321 private:
322 const char* name;
323 u16 mask;
324 u16 expected;
325 Id id;
326 Type type;
327 };
328
329 static boost::optional<const Matcher&> Decode(Instruction instr) {
330 static const auto table{GetDecodeTable()};
331
332 const auto matches_instruction = [instr](const auto& matcher) {
333 return matcher.Matches(static_cast<u16>(instr.opcode));
334 };
335
336 auto iter = std::find_if(table.begin(), table.end(), matches_instruction);
337 return iter != table.end() ? boost::optional<const Matcher&>(*iter) : boost::none;
338 }
339
340private:
341 struct Detail {
342 private:
343 static constexpr size_t opcode_bitsize = 16;
344
345 /**
346 * Generates the mask and the expected value after masking from a given bitstring.
347 * A '0' in a bitstring indicates that a zero must be present at that bit position.
348 * A '1' in a bitstring indicates that a one must be present at that bit position.
349 */
350 static auto GetMaskAndExpect(const char* const bitstring) {
351 u16 mask = 0, expect = 0;
352 for (size_t i = 0; i < opcode_bitsize; i++) {
353 const size_t bit_position = opcode_bitsize - i - 1;
354 switch (bitstring[i]) {
355 case '0':
356 mask |= 1 << bit_position;
357 break;
358 case '1':
359 expect |= 1 << bit_position;
360 mask |= 1 << bit_position;
361 break;
362 default:
363 // Ignore
364 break;
365 }
366 }
367 return std::make_tuple(mask, expect);
368 }
369
370 public:
371 /// Creates a matcher that can match and parse instructions based on bitstring.
372 static auto GetMatcher(const char* const bitstring, OpCode::Id op, OpCode::Type type,
373 const char* const name) {
374 const auto mask_expect = GetMaskAndExpect(bitstring);
375 return Matcher(name, std::get<0>(mask_expect), std::get<1>(mask_expect), op, type);
376 }
377 };
378
379 static std::vector<Matcher> GetDecodeTable() {
380 std::vector<Matcher> table = {
381#define INST(bitstring, op, type, name) Detail::GetMatcher(bitstring, op, type, name)
382 INST("111000110011----", Id::KIL, Type::Flow, "KIL"),
383 INST("1110111111011---", Id::LD_A, Type::Memory, "LD_A"),
384 INST("1110111111110---", Id::ST_A, Type::Memory, "ST_A"),
385 INST("1101111101001---", Id::TEXQ, Type::Memory, "TEXQ"),
386 INST("1101100---------", Id::TEXS, Type::Memory, "TEXS"),
387 INST("1101101---------", Id::TLDS, Type::Memory, "TLDS"),
388 INST("111000110000----", Id::EXIT, Type::Trivial, "EXIT"),
389 INST("11100000--------", Id::IPA, Type::Trivial, "IPA"),
390 INST("001100101-------", Id::FFMA_IMM, Type::Ffma, "FFMA_IMM"),
391 INST("010010011-------", Id::FFMA_CR, Type::Ffma, "FFMA_CR"),
392 INST("010100011-------", Id::FFMA_RC, Type::Ffma, "FFMA_RC"),
393 INST("010110011-------", Id::FFMA_RR, Type::Ffma, "FFMA_RR"),
394 INST("0100110001011---", Id::FADD_C, Type::Arithmetic, "FADD_C"),
395 INST("0101110001011---", Id::FADD_R, Type::Arithmetic, "FADD_R"),
396 INST("0011100-01011---", Id::FADD_IMM, Type::Arithmetic, "FADD_IMM"),
397 INST("0100110001101---", Id::FMUL_C, Type::Arithmetic, "FMUL_C"),
398 INST("0101110001101---", Id::FMUL_R, Type::Arithmetic, "FMUL_R"),
399 INST("0011100-01101---", Id::FMUL_IMM, Type::Arithmetic, "FMUL_IMM"),
400 INST("00011110--------", Id::FMUL32_IMM, Type::Arithmetic, "FMUL32_IMM"),
401 INST("0101000010000---", Id::MUFU, Type::Arithmetic, "MUFU"),
402 INST("0101110010010---", Id::RRO, Type::Arithmetic, "RRO"),
403 INST("0100110010101---", Id::F2F_C, Type::Arithmetic, "F2F_C"),
404 INST("0101110010101---", Id::F2F_R, Type::Arithmetic, "F2F_R"),
405 INST("0011100-10101---", Id::F2F_IMM, Type::Arithmetic, "F2F_IMM"),
406 INST("0100110010110---", Id::F2I_C, Type::Arithmetic, "F2I_C"),
407 INST("0101110010110---", Id::F2I_R, Type::Arithmetic, "F2I_R"),
408 INST("0011100-10110---", Id::F2I_IMM, Type::Arithmetic, "F2I_IMM"),
409 INST("0100110010111---", Id::I2F_C, Type::Arithmetic, "I2F_C"),
410 INST("0101110010111---", Id::I2F_R, Type::Arithmetic, "I2F_R"),
411 INST("0011100-10111---", Id::I2F_IMM, Type::Arithmetic, "I2F_IMM"),
412 INST("000001----------", Id::LOP32I, Type::Arithmetic, "LOP32I"),
413 INST("0100110010011---", Id::MOV_C, Type::Arithmetic, "MOV_C"),
414 INST("0101110010011---", Id::MOV_R, Type::Arithmetic, "MOV_R"),
415 INST("0011100-10011---", Id::MOV_IMM, Type::Arithmetic, "MOV_IMM"),
416 INST("000000010000----", Id::MOV32I, Type::Arithmetic, "MOV32I"),
417 INST("0100110000101---", Id::SHR_C, Type::Arithmetic, "SHR_C"),
418 INST("0101110000101---", Id::SHR_R, Type::Arithmetic, "SHR_R"),
419 INST("0011100-00101---", Id::SHR_IMM, Type::Arithmetic, "SHR_IMM"),
420 INST("010010111011----", Id::FSETP_C, Type::FloatPredicate, "FSETP_C"),
421 INST("010110111011----", Id::FSETP_R, Type::FloatPredicate, "FSETP_R"),
422 INST("0011011-1011----", Id::FSETP_IMM, Type::FloatPredicate, "FSETP_IMM"),
423 INST("010010110110----", Id::ISETP_C, Type::IntegerPredicate, "ISETP_C"),
424 INST("010110110110----", Id::ISETP_R, Type::IntegerPredicate, "ISETP_R"),
425 INST("0011011-0110----", Id::ISETP_IMM, Type::IntegerPredicate, "ISETP_IMM"),
426 };
427#undef INST
428 std::stable_sort(table.begin(), table.end(), [](const auto& a, const auto& b) {
429 // If a matcher has more bits in its mask it is more specific, so it
430 // should come first.
431 return std::bitset<16>(a.GetMask()).count() > std::bitset<16>(b.GetMask()).count();
432 });
433
434 return table;
435 }
436};
437
438} // namespace Shader
439} // namespace Tegra
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h
index 71a8661b4..2888daedc 100644
--- a/src/video_core/gpu.h
+++ b/src/video_core/gpu.h
@@ -15,7 +15,10 @@ namespace Tegra {
15 15
16enum class RenderTargetFormat : u32 { 16enum class RenderTargetFormat : u32 {
17 NONE = 0x0, 17 NONE = 0x0,
18 RGBA16_FLOAT = 0xCA,
19 RGB10_A2_UNORM = 0xD1,
18 RGBA8_UNORM = 0xD5, 20 RGBA8_UNORM = 0xD5,
21 RGBA8_SRGB = 0xD6,
19}; 22};
20 23
21class DebugContext; 24class DebugContext;
diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h
index 35d262189..36629dd11 100644
--- a/src/video_core/rasterizer_interface.h
+++ b/src/video_core/rasterizer_interface.h
@@ -19,7 +19,7 @@ public:
19 virtual void DrawArrays() = 0; 19 virtual void DrawArrays() = 0;
20 20
21 /// Notify rasterizer that the specified Maxwell register has been changed 21 /// Notify rasterizer that the specified Maxwell register has been changed
22 virtual void NotifyMaxwellRegisterChanged(u32 id) = 0; 22 virtual void NotifyMaxwellRegisterChanged(u32 method) = 0;
23 23
24 /// Notify rasterizer that all caches should be flushed to Switch memory 24 /// Notify rasterizer that all caches should be flushed to Switch memory
25 virtual void FlushAll() = 0; 25 virtual void FlushAll() = 0;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index f217a265b..2d4a0d6db 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -2,6 +2,7 @@
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>
5#include <memory> 6#include <memory>
6#include <string> 7#include <string>
7#include <tuple> 8#include <tuple>
@@ -13,7 +14,6 @@
13#include "common/math_util.h" 14#include "common/math_util.h"
14#include "common/microprofile.h" 15#include "common/microprofile.h"
15#include "common/scope_exit.h" 16#include "common/scope_exit.h"
16#include "common/vector_math.h"
17#include "core/core.h" 17#include "core/core.h"
18#include "core/hle/kernel/process.h" 18#include "core/hle/kernel/process.h"
19#include "core/settings.h" 19#include "core/settings.h"
@@ -34,33 +34,7 @@ MICROPROFILE_DEFINE(OpenGL_Drawing, "OpenGL", "Drawing", MP_RGB(128, 128, 192));
34MICROPROFILE_DEFINE(OpenGL_Blits, "OpenGL", "Blits", MP_RGB(100, 100, 255)); 34MICROPROFILE_DEFINE(OpenGL_Blits, "OpenGL", "Blits", MP_RGB(100, 100, 255));
35MICROPROFILE_DEFINE(OpenGL_CacheManagement, "OpenGL", "Cache Mgmt", MP_RGB(100, 255, 100)); 35MICROPROFILE_DEFINE(OpenGL_CacheManagement, "OpenGL", "Cache Mgmt", MP_RGB(100, 255, 100));
36 36
37enum class UniformBindings : GLuint { Common, VS, FS };
38
39static void SetShaderUniformBlockBinding(GLuint shader, const char* name, UniformBindings binding,
40 size_t expected_size) {
41 GLuint ub_index = glGetUniformBlockIndex(shader, name);
42 if (ub_index != GL_INVALID_INDEX) {
43 GLint ub_size = 0;
44 glGetActiveUniformBlockiv(shader, ub_index, GL_UNIFORM_BLOCK_DATA_SIZE, &ub_size);
45 ASSERT_MSG(ub_size == expected_size,
46 "Uniform block size did not match! Got %d, expected %zu",
47 static_cast<int>(ub_size), expected_size);
48 glUniformBlockBinding(shader, ub_index, static_cast<GLuint>(binding));
49 }
50}
51
52static void SetShaderUniformBlockBindings(GLuint shader) {
53 SetShaderUniformBlockBinding(shader, "shader_data", UniformBindings::Common,
54 sizeof(RasterizerOpenGL::UniformData));
55 SetShaderUniformBlockBinding(shader, "vs_config", UniformBindings::VS,
56 sizeof(RasterizerOpenGL::VSUniformData));
57 SetShaderUniformBlockBinding(shader, "fs_config", UniformBindings::FS,
58 sizeof(RasterizerOpenGL::FSUniformData));
59}
60
61RasterizerOpenGL::RasterizerOpenGL() { 37RasterizerOpenGL::RasterizerOpenGL() {
62 shader_dirty = true;
63
64 has_ARB_buffer_storage = false; 38 has_ARB_buffer_storage = false;
65 has_ARB_direct_state_access = false; 39 has_ARB_direct_state_access = false;
66 has_ARB_separate_shader_objects = false; 40 has_ARB_separate_shader_objects = false;
@@ -72,6 +46,14 @@ RasterizerOpenGL::RasterizerOpenGL() {
72 state.texture_units[i].sampler = texture_samplers[i].sampler.handle; 46 state.texture_units[i].sampler = texture_samplers[i].sampler.handle;
73 } 47 }
74 48
49 // Create SSBOs
50 for (size_t stage = 0; stage < ssbos.size(); ++stage) {
51 for (size_t buffer = 0; buffer < ssbos[stage].size(); ++buffer) {
52 ssbos[stage][buffer].Create();
53 state.draw.const_buffers[stage][buffer].ssbo = ssbos[stage][buffer].handle;
54 }
55 }
56
75 GLint ext_num; 57 GLint ext_num;
76 glGetIntegerv(GL_NUM_EXTENSIONS, &ext_num); 58 glGetIntegerv(GL_NUM_EXTENSIONS, &ext_num);
77 for (GLint i = 0; i < ext_num; i++) { 59 for (GLint i = 0; i < ext_num; i++) {
@@ -88,6 +70,8 @@ RasterizerOpenGL::RasterizerOpenGL() {
88 } 70 }
89 } 71 }
90 72
73 ASSERT_MSG(has_ARB_separate_shader_objects, "has_ARB_separate_shader_objects is unsupported");
74
91 // Clipping plane 0 is always enabled for PICA fixed clip plane z <= 0 75 // Clipping plane 0 is always enabled for PICA fixed clip plane z <= 0
92 state.clip_distance[0] = true; 76 state.clip_distance[0] = true;
93 77
@@ -102,36 +86,30 @@ RasterizerOpenGL::RasterizerOpenGL() {
102 state.draw.uniform_buffer = uniform_buffer.handle; 86 state.draw.uniform_buffer = uniform_buffer.handle;
103 state.Apply(); 87 state.Apply();
104 88
105 glBufferData(GL_UNIFORM_BUFFER, sizeof(UniformData), nullptr, GL_STATIC_DRAW);
106 glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniform_buffer.handle);
107
108 uniform_block_data.dirty = true;
109
110 // Create render framebuffer 89 // Create render framebuffer
111 framebuffer.Create(); 90 framebuffer.Create();
112 91
113 if (has_ARB_separate_shader_objects) { 92 hw_vao.Create();
114 hw_vao.Create(); 93 hw_vao_enabled_attributes.fill(false);
115 hw_vao_enabled_attributes.fill(false);
116 94
117 stream_buffer = OGLStreamBuffer::MakeBuffer(has_ARB_buffer_storage, GL_ARRAY_BUFFER); 95 stream_buffer = OGLStreamBuffer::MakeBuffer(has_ARB_buffer_storage, GL_ARRAY_BUFFER);
118 stream_buffer->Create(STREAM_BUFFER_SIZE, STREAM_BUFFER_SIZE / 2); 96 stream_buffer->Create(STREAM_BUFFER_SIZE, STREAM_BUFFER_SIZE / 2);
119 state.draw.vertex_buffer = stream_buffer->GetHandle(); 97 state.draw.vertex_buffer = stream_buffer->GetHandle();
120 98
121 pipeline.Create(); 99 shader_program_manager = std::make_unique<GLShader::ProgramManager>();
122 state.draw.program_pipeline = pipeline.handle; 100 state.draw.shader_program = 0;
123 state.draw.shader_program = 0; 101 state.draw.vertex_array = hw_vao.handle;
124 state.draw.vertex_array = hw_vao.handle; 102 state.Apply();
125 state.Apply();
126 103
127 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, stream_buffer->GetHandle()); 104 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, stream_buffer->GetHandle());
128 105
129 vs_uniform_buffer.Create(); 106 for (unsigned index = 0; index < uniform_buffers.size(); ++index) {
130 glBindBuffer(GL_UNIFORM_BUFFER, vs_uniform_buffer.handle); 107 auto& buffer = uniform_buffers[index];
131 glBufferData(GL_UNIFORM_BUFFER, sizeof(VSUniformData), nullptr, GL_STREAM_COPY); 108 buffer.Create();
132 glBindBufferBase(GL_UNIFORM_BUFFER, 1, vs_uniform_buffer.handle); 109 glBindBuffer(GL_UNIFORM_BUFFER, buffer.handle);
133 } else { 110 glBufferData(GL_UNIFORM_BUFFER, sizeof(GLShader::MaxwellUniformData), nullptr,
134 UNREACHABLE(); 111 GL_STREAM_COPY);
112 glBindBufferBase(GL_UNIFORM_BUFFER, index, buffer.handle);
135 } 113 }
136 114
137 accelerate_draw = AccelDraw::Disabled; 115 accelerate_draw = AccelDraw::Disabled;
@@ -149,17 +127,6 @@ RasterizerOpenGL::~RasterizerOpenGL() {
149 } 127 }
150} 128}
151 129
152void RasterizerOpenGL::AnalyzeVertexArray(bool is_indexed) {
153 const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
154
155 if (is_indexed) {
156 UNREACHABLE();
157 }
158
159 // TODO(bunnei): Add support for 1+ vertex arrays
160 vs_input_size = regs.vertex_buffer.count * regs.vertex_array[0].stride;
161}
162
163void RasterizerOpenGL::SetupVertexArray(u8* array_ptr, GLintptr buffer_offset) { 130void RasterizerOpenGL::SetupVertexArray(u8* array_ptr, GLintptr buffer_offset) {
164 MICROPROFILE_SCOPE(OpenGL_VAO); 131 MICROPROFILE_SCOPE(OpenGL_VAO);
165 const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs; 132 const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
@@ -171,6 +138,7 @@ void RasterizerOpenGL::SetupVertexArray(u8* array_ptr, GLintptr buffer_offset) {
171 138
172 // TODO(bunnei): Add support for 1+ vertex arrays 139 // TODO(bunnei): Add support for 1+ vertex arrays
173 const auto& vertex_array{regs.vertex_array[0]}; 140 const auto& vertex_array{regs.vertex_array[0]};
141 const auto& vertex_array_limit{regs.vertex_array_limit[0]};
174 ASSERT_MSG(vertex_array.enable, "vertex array 0 is disabled?"); 142 ASSERT_MSG(vertex_array.enable, "vertex array 0 is disabled?");
175 ASSERT_MSG(!vertex_array.divisor, "vertex array 0 divisor is unimplemented!"); 143 ASSERT_MSG(!vertex_array.divisor, "vertex array 0 divisor is unimplemented!");
176 for (unsigned index = 1; index < Maxwell::NumVertexArrays; ++index) { 144 for (unsigned index = 1; index < Maxwell::NumVertexArrays; ++index) {
@@ -183,6 +151,10 @@ void RasterizerOpenGL::SetupVertexArray(u8* array_ptr, GLintptr buffer_offset) {
183 // to avoid OpenGL errors. 151 // to avoid OpenGL errors.
184 for (unsigned index = 0; index < 16; ++index) { 152 for (unsigned index = 0; index < 16; ++index) {
185 auto& attrib = regs.vertex_attrib_format[index]; 153 auto& attrib = regs.vertex_attrib_format[index];
154 NGLOG_DEBUG(HW_GPU, "vertex attrib {}, count={}, size={}, type={}, offset={}, normalize={}",
155 index, attrib.ComponentCount(), attrib.SizeString(), attrib.TypeString(),
156 attrib.offset.Value(), attrib.IsNormalized());
157
186 glVertexAttribPointer(index, attrib.ComponentCount(), MaxwellToGL::VertexType(attrib), 158 glVertexAttribPointer(index, attrib.ComponentCount(), MaxwellToGL::VertexType(attrib),
187 attrib.IsNormalized() ? GL_TRUE : GL_FALSE, vertex_array.stride, 159 attrib.IsNormalized() ? GL_TRUE : GL_FALSE, vertex_array.stride,
188 reinterpret_cast<GLvoid*>(buffer_offset + attrib.offset)); 160 reinterpret_cast<GLvoid*>(buffer_offset + attrib.offset));
@@ -191,7 +163,7 @@ void RasterizerOpenGL::SetupVertexArray(u8* array_ptr, GLintptr buffer_offset) {
191 } 163 }
192 164
193 // Copy vertex array data 165 // Copy vertex array data
194 const u32 data_size{vertex_array.stride * regs.vertex_buffer.count}; 166 const u64 data_size{vertex_array_limit.LimitAddress() - vertex_array.StartAddress() + 1};
195 const VAddr data_addr{memory_manager->PhysicalToVirtualAddress(vertex_array.StartAddress())}; 167 const VAddr data_addr{memory_manager->PhysicalToVirtualAddress(vertex_array.StartAddress())};
196 res_cache.FlushRegion(data_addr, data_size, nullptr); 168 res_cache.FlushRegion(data_addr, data_size, nullptr);
197 Memory::ReadBlock(data_addr, array_ptr, data_size); 169 Memory::ReadBlock(data_addr, array_ptr, data_size);
@@ -200,26 +172,89 @@ void RasterizerOpenGL::SetupVertexArray(u8* array_ptr, GLintptr buffer_offset) {
200 buffer_offset += data_size; 172 buffer_offset += data_size;
201} 173}
202 174
203void RasterizerOpenGL::SetupVertexShader(VSUniformData* ub_ptr, GLintptr buffer_offset) { 175void RasterizerOpenGL::SetupShaders(u8* buffer_ptr, GLintptr buffer_offset, size_t ptr_pos) {
204 MICROPROFILE_SCOPE(OpenGL_VS); 176 // Helper function for uploading uniform data
205 LOG_CRITICAL(Render_OpenGL, "Emulated shaders are not supported! Using a passthrough shader."); 177 const auto copy_buffer = [&](GLuint handle, GLintptr offset, GLsizeiptr size) {
206 glUseProgramStages(pipeline.handle, GL_VERTEX_SHADER_BIT, current_shader->shader.handle); 178 if (has_ARB_direct_state_access) {
207} 179 glCopyNamedBufferSubData(stream_buffer->GetHandle(), handle, offset, 0, size);
180 } else {
181 glBindBuffer(GL_COPY_WRITE_BUFFER, handle);
182 glCopyBufferSubData(GL_ARRAY_BUFFER, GL_COPY_WRITE_BUFFER, offset, 0, size);
183 }
184 };
208 185
209void RasterizerOpenGL::SetupFragmentShader(FSUniformData* ub_ptr, GLintptr buffer_offset) { 186 auto& gpu = Core::System().GetInstance().GPU().Maxwell3D();
210 MICROPROFILE_SCOPE(OpenGL_FS); 187 ASSERT_MSG(!gpu.regs.shader_config[0].enable, "VertexA is unsupported!");
211 UNREACHABLE();
212}
213 188
214bool RasterizerOpenGL::AccelerateDrawBatch(bool is_indexed) { 189 // Next available bindpoint to use when uploading the const buffers to the GLSL shaders.
215 if (!has_ARB_separate_shader_objects) { 190 u32 current_constbuffer_bindpoint = 0;
216 UNREACHABLE(); 191
217 return false; 192 for (unsigned index = 1; index < Maxwell::MaxShaderProgram; ++index) {
193 ptr_pos += sizeof(GLShader::MaxwellUniformData);
194
195 auto& shader_config = gpu.regs.shader_config[index];
196 const Maxwell::ShaderProgram program{static_cast<Maxwell::ShaderProgram>(index)};
197
198 const auto& stage = index - 1; // Stage indices are 0 - 5
199
200 const bool is_enabled = gpu.IsShaderStageEnabled(static_cast<Maxwell::ShaderStage>(stage));
201
202 // Skip stages that are not enabled
203 if (!is_enabled) {
204 continue;
205 }
206
207 // Upload uniform data as one UBO per stage
208 const GLintptr ubo_offset = buffer_offset + static_cast<GLintptr>(ptr_pos);
209 copy_buffer(uniform_buffers[stage].handle, ubo_offset,
210 sizeof(GLShader::MaxwellUniformData));
211 GLShader::MaxwellUniformData* ub_ptr =
212 reinterpret_cast<GLShader::MaxwellUniformData*>(&buffer_ptr[ptr_pos]);
213 ub_ptr->SetFromRegs(gpu.state.shader_stages[stage]);
214
215 // Fetch program code from memory
216 GLShader::ProgramCode program_code;
217 const u64 gpu_address{gpu.regs.code_address.CodeAddress() + shader_config.offset};
218 const VAddr cpu_address{gpu.memory_manager.PhysicalToVirtualAddress(gpu_address)};
219 Memory::ReadBlock(cpu_address, program_code.data(), program_code.size() * sizeof(u64));
220 GLShader::ShaderSetup setup{std::move(program_code)};
221
222 GLShader::ShaderEntries shader_resources;
223
224 switch (program) {
225 case Maxwell::ShaderProgram::VertexB: {
226 GLShader::MaxwellVSConfig vs_config{setup};
227 shader_resources =
228 shader_program_manager->UseProgrammableVertexShader(vs_config, setup);
229 break;
230 }
231 case Maxwell::ShaderProgram::Fragment: {
232 GLShader::MaxwellFSConfig fs_config{setup};
233 shader_resources =
234 shader_program_manager->UseProgrammableFragmentShader(fs_config, setup);
235 break;
236 }
237 default:
238 LOG_CRITICAL(HW_GPU, "Unimplemented shader index=%d, enable=%d, offset=0x%08X", index,
239 shader_config.enable.Value(), shader_config.offset);
240 UNREACHABLE();
241 }
242
243 GLuint gl_stage_program = shader_program_manager->GetCurrentProgramStage(
244 static_cast<Maxwell::ShaderStage>(stage));
245
246 // Configure the const buffers for this shader stage.
247 current_constbuffer_bindpoint =
248 SetupConstBuffers(static_cast<Maxwell::ShaderStage>(stage), gl_stage_program,
249 current_constbuffer_bindpoint, shader_resources.const_buffer_entries);
218 } 250 }
219 251
252 shader_program_manager->UseTrivialGeometryShader();
253}
254
255bool RasterizerOpenGL::AccelerateDrawBatch(bool is_indexed) {
220 accelerate_draw = is_indexed ? AccelDraw::Indexed : AccelDraw::Arrays; 256 accelerate_draw = is_indexed ? AccelDraw::Indexed : AccelDraw::Arrays;
221 DrawArrays(); 257 DrawArrays();
222
223 return true; 258 return true;
224} 259}
225 260
@@ -255,18 +290,18 @@ void RasterizerOpenGL::DrawArrays() {
255 : (depth_surface == nullptr ? 1u : depth_surface->res_scale); 290 : (depth_surface == nullptr ? 1u : depth_surface->res_scale);
256 291
257 MathUtil::Rectangle<u32> draw_rect{ 292 MathUtil::Rectangle<u32> draw_rect{
258 static_cast<u32>(MathUtil::Clamp<s32>(static_cast<s32>(surfaces_rect.left) + 293 static_cast<u32>(
259 viewport_rect.left * res_scale, 294 std::clamp<s32>(static_cast<s32>(surfaces_rect.left) + viewport_rect.left * res_scale,
260 surfaces_rect.left, surfaces_rect.right)), // Left 295 surfaces_rect.left, surfaces_rect.right)), // Left
261 static_cast<u32>(MathUtil::Clamp<s32>(static_cast<s32>(surfaces_rect.bottom) + 296 static_cast<u32>(
262 viewport_rect.top * res_scale, 297 std::clamp<s32>(static_cast<s32>(surfaces_rect.bottom) + viewport_rect.top * res_scale,
263 surfaces_rect.bottom, surfaces_rect.top)), // Top 298 surfaces_rect.bottom, surfaces_rect.top)), // Top
264 static_cast<u32>(MathUtil::Clamp<s32>(static_cast<s32>(surfaces_rect.left) + 299 static_cast<u32>(
265 viewport_rect.right * res_scale, 300 std::clamp<s32>(static_cast<s32>(surfaces_rect.left) + viewport_rect.right * res_scale,
266 surfaces_rect.left, surfaces_rect.right)), // Right 301 surfaces_rect.left, surfaces_rect.right)), // Right
267 static_cast<u32>(MathUtil::Clamp<s32>(static_cast<s32>(surfaces_rect.bottom) + 302 static_cast<u32>(std::clamp<s32>(static_cast<s32>(surfaces_rect.bottom) +
268 viewport_rect.bottom * res_scale, 303 viewport_rect.bottom * res_scale,
269 surfaces_rect.bottom, surfaces_rect.top))}; // Bottom 304 surfaces_rect.bottom, surfaces_rect.top))}; // Bottom
270 305
271 // Bind the framebuffer surfaces 306 // Bind the framebuffer surfaces
272 BindFramebufferSurfaces(color_surface, depth_surface, has_stencil); 307 BindFramebufferSurfaces(color_surface, depth_surface, has_stencil);
@@ -280,18 +315,6 @@ void RasterizerOpenGL::DrawArrays() {
280 // Sync and bind the texture surfaces 315 // Sync and bind the texture surfaces
281 BindTextures(); 316 BindTextures();
282 317
283 // Sync and bind the shader
284 if (shader_dirty) {
285 SetShader();
286 shader_dirty = false;
287 }
288
289 // Sync the uniform data
290 if (uniform_block_data.dirty) {
291 glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(UniformData), &uniform_block_data.data);
292 uniform_block_data.dirty = false;
293 }
294
295 // Viewport can have negative offsets or larger dimensions than our framebuffer sub-rect. Enable 318 // Viewport can have negative offsets or larger dimensions than our framebuffer sub-rect. Enable
296 // scissor test to prevent drawing outside of the framebuffer region 319 // scissor test to prevent drawing outside of the framebuffer region
297 state.scissor.enabled = true; 320 state.scissor.enabled = true;
@@ -303,15 +326,22 @@ void RasterizerOpenGL::DrawArrays() {
303 326
304 // Draw the vertex batch 327 // Draw the vertex batch
305 const bool is_indexed = accelerate_draw == AccelDraw::Indexed; 328 const bool is_indexed = accelerate_draw == AccelDraw::Indexed;
306 AnalyzeVertexArray(is_indexed); 329 const u64 index_buffer_size{regs.index_array.count * regs.index_array.FormatSizeInBytes()};
330 const unsigned vertex_num{is_indexed ? regs.index_array.count : regs.vertex_buffer.count};
331
332 // TODO(bunnei): Add support for 1+ vertex arrays
333 vs_input_size = vertex_num * regs.vertex_array[0].stride;
334
307 state.draw.vertex_buffer = stream_buffer->GetHandle(); 335 state.draw.vertex_buffer = stream_buffer->GetHandle();
308 state.Apply(); 336 state.Apply();
309 337
310 size_t buffer_size = static_cast<size_t>(vs_input_size); 338 size_t buffer_size = static_cast<size_t>(vs_input_size);
311 if (is_indexed) { 339 if (is_indexed) {
312 UNREACHABLE(); 340 buffer_size = Common::AlignUp(buffer_size, 4) + index_buffer_size;
313 } 341 }
314 buffer_size += sizeof(VSUniformData); 342
343 // Uniform space for the 5 shader stages
344 buffer_size += sizeof(GLShader::MaxwellUniformData) * Maxwell::MaxShaderStage;
315 345
316 size_t ptr_pos = 0; 346 size_t ptr_pos = 0;
317 u8* buffer_ptr; 347 u8* buffer_ptr;
@@ -322,36 +352,37 @@ void RasterizerOpenGL::DrawArrays() {
322 SetupVertexArray(buffer_ptr, buffer_offset); 352 SetupVertexArray(buffer_ptr, buffer_offset);
323 ptr_pos += vs_input_size; 353 ptr_pos += vs_input_size;
324 354
355 // If indexed mode, copy the index buffer
325 GLintptr index_buffer_offset = 0; 356 GLintptr index_buffer_offset = 0;
326 if (is_indexed) { 357 if (is_indexed) {
327 UNREACHABLE(); 358 ptr_pos = Common::AlignUp(ptr_pos, 4);
328 }
329 359
330 SetupVertexShader(reinterpret_cast<VSUniformData*>(&buffer_ptr[ptr_pos]), 360 const auto& memory_manager = Core::System().GetInstance().GPU().memory_manager;
331 buffer_offset + static_cast<GLintptr>(ptr_pos)); 361 const VAddr index_data_addr{
332 const GLintptr vs_ubo_offset = buffer_offset + static_cast<GLintptr>(ptr_pos); 362 memory_manager->PhysicalToVirtualAddress(regs.index_array.StartAddress())};
333 ptr_pos += sizeof(VSUniformData); 363 Memory::ReadBlock(index_data_addr, &buffer_ptr[ptr_pos], index_buffer_size);
334 364
335 stream_buffer->Unmap(); 365 index_buffer_offset = buffer_offset + static_cast<GLintptr>(ptr_pos);
366 ptr_pos += index_buffer_size;
367 }
336 368
337 const auto copy_buffer = [&](GLuint handle, GLintptr offset, GLsizeiptr size) { 369 SetupShaders(buffer_ptr, buffer_offset, ptr_pos);
338 if (has_ARB_direct_state_access) {
339 glCopyNamedBufferSubData(stream_buffer->GetHandle(), handle, offset, 0, size);
340 } else {
341 glBindBuffer(GL_COPY_WRITE_BUFFER, handle);
342 glCopyBufferSubData(GL_ARRAY_BUFFER, GL_COPY_WRITE_BUFFER, offset, 0, size);
343 }
344 };
345 370
346 copy_buffer(vs_uniform_buffer.handle, vs_ubo_offset, sizeof(VSUniformData)); 371 stream_buffer->Unmap();
347 372
348 glUseProgramStages(pipeline.handle, GL_FRAGMENT_SHADER_BIT, current_shader->shader.handle); 373 shader_program_manager->ApplyTo(state);
374 state.Apply();
349 375
376 const GLenum primitive_mode{MaxwellToGL::PrimitiveTopology(regs.draw.topology)};
350 if (is_indexed) { 377 if (is_indexed) {
351 UNREACHABLE(); 378 const GLint index_min{static_cast<GLint>(regs.index_array.first)};
379 const GLint index_max{static_cast<GLint>(regs.index_array.first + regs.index_array.count)};
380 glDrawRangeElementsBaseVertex(primitive_mode, index_min, index_max, regs.index_array.count,
381 MaxwellToGL::IndexFormat(regs.index_array.format),
382 reinterpret_cast<const void*>(index_buffer_offset),
383 -index_min);
352 } else { 384 } else {
353 glDrawArrays(MaxwellToGL::PrimitiveTopology(regs.draw.topology), 0, 385 glDrawArrays(primitive_mode, 0, regs.vertex_buffer.count);
354 regs.vertex_buffer.count);
355 } 386 }
356 387
357 // Disable scissor test 388 // Disable scissor test
@@ -384,7 +415,7 @@ void RasterizerOpenGL::DrawArrays() {
384 415
385void RasterizerOpenGL::BindTextures() { 416void RasterizerOpenGL::BindTextures() {
386 using Regs = Tegra::Engines::Maxwell3D::Regs; 417 using Regs = Tegra::Engines::Maxwell3D::Regs;
387 auto maxwell3d = Core::System::GetInstance().GPU().Get3DEngine(); 418 auto& maxwell3d = Core::System::GetInstance().GPU().Get3DEngine();
388 419
389 // Each Maxwell shader stage can have an arbitrary number of textures, but we're limited to a 420 // Each Maxwell shader stage can have an arbitrary number of textures, but we're limited to a
390 // certain number in OpenGL. We try to only use the minimum amount of host textures by not 421 // certain number in OpenGL. We try to only use the minimum amount of host textures by not
@@ -415,7 +446,32 @@ void RasterizerOpenGL::BindTextures() {
415 } 446 }
416} 447}
417 448
418void RasterizerOpenGL::NotifyMaxwellRegisterChanged(u32 id) {} 449void RasterizerOpenGL::NotifyMaxwellRegisterChanged(u32 method) {
450 const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
451 switch (method) {
452 case MAXWELL3D_REG_INDEX(blend.separate_alpha):
453 ASSERT_MSG(false, "unimplemented");
454 break;
455 case MAXWELL3D_REG_INDEX(blend.equation_rgb):
456 state.blend.rgb_equation = MaxwellToGL::BlendEquation(regs.blend.equation_rgb);
457 break;
458 case MAXWELL3D_REG_INDEX(blend.factor_source_rgb):
459 state.blend.src_rgb_func = MaxwellToGL::BlendFunc(regs.blend.factor_source_rgb);
460 break;
461 case MAXWELL3D_REG_INDEX(blend.factor_dest_rgb):
462 state.blend.dst_rgb_func = MaxwellToGL::BlendFunc(regs.blend.factor_dest_rgb);
463 break;
464 case MAXWELL3D_REG_INDEX(blend.equation_a):
465 state.blend.a_equation = MaxwellToGL::BlendEquation(regs.blend.equation_a);
466 break;
467 case MAXWELL3D_REG_INDEX(blend.factor_source_a):
468 state.blend.src_a_func = MaxwellToGL::BlendFunc(regs.blend.factor_source_a);
469 break;
470 case MAXWELL3D_REG_INDEX(blend.factor_dest_a):
471 state.blend.dst_a_func = MaxwellToGL::BlendFunc(regs.blend.factor_dest_a);
472 break;
473 }
474}
419 475
420void RasterizerOpenGL::FlushAll() { 476void RasterizerOpenGL::FlushAll() {
421 MICROPROFILE_SCOPE(OpenGL_CacheManagement); 477 MICROPROFILE_SCOPE(OpenGL_CacheManagement);
@@ -467,9 +523,12 @@ bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& framebu
467 src_params.width = std::min(framebuffer.width, pixel_stride); 523 src_params.width = std::min(framebuffer.width, pixel_stride);
468 src_params.height = framebuffer.height; 524 src_params.height = framebuffer.height;
469 src_params.stride = pixel_stride; 525 src_params.stride = pixel_stride;
470 src_params.is_tiled = false; 526 src_params.is_tiled = true;
527 src_params.block_height = Tegra::Texture::TICEntry::DefaultBlockHeight;
471 src_params.pixel_format = 528 src_params.pixel_format =
472 SurfaceParams::PixelFormatFromGPUPixelFormat(framebuffer.pixel_format); 529 SurfaceParams::PixelFormatFromGPUPixelFormat(framebuffer.pixel_format);
530 src_params.component_type =
531 SurfaceParams::ComponentTypeFromGPUPixelFormat(framebuffer.pixel_format);
473 src_params.UpdateParams(); 532 src_params.UpdateParams();
474 533
475 MathUtil::Rectangle<u32> src_rect; 534 MathUtil::Rectangle<u32> src_rect;
@@ -531,70 +590,53 @@ void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::TSCEntr
531 } 590 }
532} 591}
533 592
534void RasterizerOpenGL::SetShader() { 593u32 RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, GLuint program,
535 // TODO(bunnei): The below sets up a static test shader for passing untransformed vertices to 594 u32 current_bindpoint,
536 // OpenGL for rendering. This should be removed/replaced when we start emulating Maxwell 595 const std::vector<GLShader::ConstBufferEntry>& entries) {
537 // shaders. 596 auto& gpu = Core::System::GetInstance().GPU();
538 597 auto& maxwell3d = gpu.Get3DEngine();
539 static constexpr char vertex_shader[] = R"(
540#version 150 core
541
542in vec2 vert_position;
543in vec2 vert_tex_coord;
544out vec2 frag_tex_coord;
545
546void main() {
547 // Multiply input position by the rotscale part of the matrix and then manually translate by
548 // the last column. This is equivalent to using a full 3x3 matrix and expanding the vector
549 // to `vec3(vert_position.xy, 1.0)`
550 gl_Position = vec4(mat2(mat3x2(0.0015625f, 0.0, 0.0, -0.0027778, -1.0, 1.0)) * vert_position + mat3x2(0.0015625f, 0.0, 0.0, -0.0027778, -1.0, 1.0)[2], 0.0, 1.0);
551 frag_tex_coord = vert_tex_coord;
552}
553)";
554
555 static constexpr char fragment_shader[] = R"(
556#version 150 core
557
558in vec2 frag_tex_coord;
559out vec4 color;
560
561uniform sampler2D tex[32];
562 598
563void main() { 599 ASSERT_MSG(maxwell3d.IsShaderStageEnabled(stage),
564 color = texture(tex[0], frag_tex_coord); 600 "Attempted to upload constbuffer of disabled shader stage");
565}
566)";
567 601
568 if (current_shader) { 602 // Reset all buffer draw state for this stage.
569 return; 603 for (auto& buffer : state.draw.const_buffers[static_cast<size_t>(stage)]) {
604 buffer.bindpoint = 0;
605 buffer.enabled = false;
570 } 606 }
571 607
572 LOG_CRITICAL(Render_OpenGL, "Emulated shaders are not supported! Using a passthrough shader."); 608 // Upload only the enabled buffers from the 16 constbuffers of each shader stage
573 609 auto& shader_stage = maxwell3d.state.shader_stages[static_cast<size_t>(stage)];
574 current_shader = &test_shader; 610
575 if (has_ARB_separate_shader_objects) { 611 for (u32 bindpoint = 0; bindpoint < entries.size(); ++bindpoint) {
576 test_shader.shader.Create(vertex_shader, nullptr, fragment_shader, {}, true); 612 const auto& used_buffer = entries[bindpoint];
577 glActiveShaderProgram(pipeline.handle, test_shader.shader.handle); 613 const auto& buffer = shader_stage.const_buffers[used_buffer.GetIndex()];
578 } else { 614 auto& buffer_draw_state =
579 UNREACHABLE(); 615 state.draw.const_buffers[static_cast<size_t>(stage)][used_buffer.GetIndex()];
616
617 ASSERT_MSG(buffer.enabled, "Attempted to upload disabled constbuffer");
618 buffer_draw_state.enabled = true;
619 buffer_draw_state.bindpoint = current_bindpoint + bindpoint;
620
621 VAddr addr = gpu.memory_manager->PhysicalToVirtualAddress(buffer.address);
622 std::vector<u8> data(used_buffer.GetSize() * sizeof(float));
623 Memory::ReadBlock(addr, data.data(), data.size());
624
625 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer_draw_state.ssbo);
626 glBufferData(GL_SHADER_STORAGE_BUFFER, data.size(), data.data(), GL_DYNAMIC_DRAW);
627 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
628
629 // Now configure the bindpoint of the buffer inside the shader
630 std::string buffer_name = used_buffer.GetName();
631 GLuint index =
632 glGetProgramResourceIndex(program, GL_SHADER_STORAGE_BLOCK, buffer_name.c_str());
633 if (index != -1)
634 glShaderStorageBlockBinding(program, index, buffer_draw_state.bindpoint);
580 } 635 }
581 636
582 state.draw.shader_program = test_shader.shader.handle;
583 state.Apply(); 637 state.Apply();
584 638
585 for (u32 texture = 0; texture < texture_samplers.size(); ++texture) { 639 return current_bindpoint + entries.size();
586 // Set the texture samplers to correspond to different texture units
587 std::string uniform_name = "tex[" + std::to_string(texture) + "]";
588 GLint uniform_tex = glGetUniformLocation(test_shader.shader.handle, uniform_name.c_str());
589 if (uniform_tex != -1) {
590 glUniform1i(uniform_tex, TextureUnits::MaxwellTexture(texture).id);
591 }
592 }
593
594 if (has_ARB_separate_shader_objects) {
595 state.draw.shader_program = 0;
596 state.Apply();
597 }
598} 640}
599 641
600void RasterizerOpenGL::BindFramebufferSurfaces(const Surface& color_surface, 642void RasterizerOpenGL::BindFramebufferSurfaces(const Surface& color_surface,
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index d868bf421..03e02b52a 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -6,19 +6,16 @@
6 6
7#include <array> 7#include <array>
8#include <cstddef> 8#include <cstddef>
9#include <cstring>
10#include <memory> 9#include <memory>
11#include <unordered_map>
12#include <vector> 10#include <vector>
13#include <glad/glad.h> 11#include <glad/glad.h>
14#include "common/bit_field.h"
15#include "common/common_types.h" 12#include "common/common_types.h"
16#include "common/hash.h" 13#include "video_core/engines/maxwell_3d.h"
17#include "common/vector_math.h"
18#include "video_core/rasterizer_interface.h" 14#include "video_core/rasterizer_interface.h"
19#include "video_core/renderer_opengl/gl_rasterizer_cache.h" 15#include "video_core/renderer_opengl/gl_rasterizer_cache.h"
20#include "video_core/renderer_opengl/gl_resource_manager.h" 16#include "video_core/renderer_opengl/gl_resource_manager.h"
21#include "video_core/renderer_opengl/gl_shader_gen.h" 17#include "video_core/renderer_opengl/gl_shader_gen.h"
18#include "video_core/renderer_opengl/gl_shader_manager.h"
22#include "video_core/renderer_opengl/gl_state.h" 19#include "video_core/renderer_opengl/gl_state.h"
23#include "video_core/renderer_opengl/gl_stream_buffer.h" 20#include "video_core/renderer_opengl/gl_stream_buffer.h"
24 21
@@ -30,7 +27,7 @@ public:
30 ~RasterizerOpenGL() override; 27 ~RasterizerOpenGL() override;
31 28
32 void DrawArrays() override; 29 void DrawArrays() override;
33 void NotifyMaxwellRegisterChanged(u32 id) override; 30 void NotifyMaxwellRegisterChanged(u32 method) override;
34 void FlushAll() override; 31 void FlushAll() override;
35 void FlushRegion(VAddr addr, u64 size) override; 32 void FlushRegion(VAddr addr, u64 size) override;
36 void InvalidateRegion(VAddr addr, u64 size) override; 33 void InvalidateRegion(VAddr addr, u64 size) override;
@@ -45,7 +42,7 @@ public:
45 /// OpenGL shader generated for a given Maxwell register state 42 /// OpenGL shader generated for a given Maxwell register state
46 struct MaxwellShader { 43 struct MaxwellShader {
47 /// OpenGL shader resource 44 /// OpenGL shader resource
48 OGLShader shader; 45 OGLProgram shader;
49 }; 46 };
50 47
51 struct VertexShader { 48 struct VertexShader {
@@ -56,34 +53,6 @@ public:
56 OGLShader shader; 53 OGLShader shader;
57 }; 54 };
58 55
59 /// Uniform structure for the Uniform Buffer Object, all vectors must be 16-byte aligned
60 // NOTE: Always keep a vec4 at the end. The GL spec is not clear wether the alignment at
61 // the end of a uniform block is included in UNIFORM_BLOCK_DATA_SIZE or not.
62 // Not following that rule will cause problems on some AMD drivers.
63 struct UniformData {};
64
65 // static_assert(
66 // sizeof(UniformData) == 0x460,
67 // "The size of the UniformData structure has changed, update the structure in the shader");
68 static_assert(sizeof(UniformData) < 16384,
69 "UniformData structure must be less than 16kb as per the OpenGL spec");
70
71 struct VSUniformData {};
72 // static_assert(
73 // sizeof(VSUniformData) == 1856,
74 // "The size of the VSUniformData structure has changed, update the structure in the
75 // shader");
76 static_assert(sizeof(VSUniformData) < 16384,
77 "VSUniformData structure must be less than 16kb as per the OpenGL spec");
78
79 struct FSUniformData {};
80 // static_assert(
81 // sizeof(FSUniformData) == 1856,
82 // "The size of the FSUniformData structure has changed, update the structure in the
83 // shader");
84 static_assert(sizeof(FSUniformData) < 16384,
85 "FSUniformData structure must be less than 16kb as per the OpenGL spec");
86
87private: 56private:
88 class SamplerInfo { 57 class SamplerInfo {
89 public: 58 public:
@@ -113,6 +82,18 @@ private:
113 /// Binds the required textures to OpenGL before drawing a batch. 82 /// Binds the required textures to OpenGL before drawing a batch.
114 void BindTextures(); 83 void BindTextures();
115 84
85 /*
86 * Configures the current constbuffers to use for the draw command.
87 * @param stage The shader stage to configure buffers for.
88 * @param program The OpenGL program object that contains the specified stage.
89 * @param current_bindpoint The offset at which to start counting new buffer bindpoints.
90 * @param entries Vector describing the buffers that are actually used in the guest shader.
91 * @returns The next available bindpoint for use in the next shader stage.
92 */
93 u32 SetupConstBuffers(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, GLuint program,
94 u32 current_bindpoint,
95 const std::vector<GLShader::ConstBufferEntry>& entries);
96
116 /// Syncs the viewport to match the guest state 97 /// Syncs the viewport to match the guest state
117 void SyncViewport(const MathUtil::Rectangle<u32>& surfaces_rect, u16 res_scale); 98 void SyncViewport(const MathUtil::Rectangle<u32>& surfaces_rect, u16 res_scale);
118 99
@@ -122,9 +103,6 @@ private:
122 /// Syncs the clip coefficients to match the guest state 103 /// Syncs the clip coefficients to match the guest state
123 void SyncClipCoef(); 104 void SyncClipCoef();
124 105
125 /// Sets the OpenGL shader in accordance with the current guest state
126 void SetShader();
127
128 /// Syncs the cull mode to match the guest state 106 /// Syncs the cull mode to match the guest state
129 void SyncCullMode(); 107 void SyncCullMode();
130 108
@@ -152,23 +130,16 @@ private:
152 130
153 RasterizerCacheOpenGL res_cache; 131 RasterizerCacheOpenGL res_cache;
154 132
155 /// Shader used for test renderering - to be removed once we have emulated shaders 133 std::unique_ptr<GLShader::ProgramManager> shader_program_manager;
156 MaxwellShader test_shader{};
157
158 const MaxwellShader* current_shader{};
159 bool shader_dirty{};
160
161 struct {
162 UniformData data;
163 bool dirty;
164 } uniform_block_data = {};
165
166 OGLPipeline pipeline;
167 OGLVertexArray sw_vao; 134 OGLVertexArray sw_vao;
168 OGLVertexArray hw_vao; 135 OGLVertexArray hw_vao;
169 std::array<bool, 16> hw_vao_enabled_attributes; 136 std::array<bool, 16> hw_vao_enabled_attributes;
170 137
171 std::array<SamplerInfo, 32> texture_samplers; 138 std::array<SamplerInfo, GLShader::NumTextureSamplers> texture_samplers;
139 std::array<std::array<OGLBuffer, Tegra::Engines::Maxwell3D::Regs::MaxConstBuffers>,
140 Tegra::Engines::Maxwell3D::Regs::MaxShaderStage>
141 ssbos;
142
172 static constexpr size_t VERTEX_BUFFER_SIZE = 128 * 1024 * 1024; 143 static constexpr size_t VERTEX_BUFFER_SIZE = 128 * 1024 * 1024;
173 std::unique_ptr<OGLStreamBuffer> vertex_buffer; 144 std::unique_ptr<OGLStreamBuffer> vertex_buffer;
174 OGLBuffer uniform_buffer; 145 OGLBuffer uniform_buffer;
@@ -179,22 +150,11 @@ private:
179 150
180 GLsizeiptr vs_input_size; 151 GLsizeiptr vs_input_size;
181 152
182 void AnalyzeVertexArray(bool is_indexed);
183 void SetupVertexArray(u8* array_ptr, GLintptr buffer_offset); 153 void SetupVertexArray(u8* array_ptr, GLintptr buffer_offset);
184 154
185 OGLBuffer vs_uniform_buffer; 155 std::array<OGLBuffer, Tegra::Engines::Maxwell3D::Regs::MaxShaderStage> uniform_buffers;
186 std::unordered_map<GLShader::MaxwellVSConfig, VertexShader*> vs_shader_map;
187 std::unordered_map<std::string, VertexShader> vs_shader_cache;
188 OGLShader vs_default_shader;
189
190 void SetupVertexShader(VSUniformData* ub_ptr, GLintptr buffer_offset);
191
192 OGLBuffer fs_uniform_buffer;
193 std::unordered_map<GLShader::MaxwellFSConfig, FragmentShader*> fs_shader_map;
194 std::unordered_map<std::string, FragmentShader> fs_shader_cache;
195 OGLShader fs_default_shader;
196 156
197 void SetupFragmentShader(FSUniformData* ub_ptr, GLintptr buffer_offset); 157 void SetupShaders(u8* buffer_ptr, GLintptr buffer_offset, size_t ptr_pos);
198 158
199 enum class AccelDraw { Disabled, Arrays, Indexed }; 159 enum class AccelDraw { Disabled, Arrays, Indexed };
200 AccelDraw accelerate_draw; 160 AccelDraw accelerate_draw;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index 5cbafa2e7..ced2b8247 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -7,7 +7,6 @@
7#include <cstring> 7#include <cstring>
8#include <iterator> 8#include <iterator>
9#include <memory> 9#include <memory>
10#include <unordered_set>
11#include <utility> 10#include <utility>
12#include <vector> 11#include <vector>
13#include <boost/optional.hpp> 12#include <boost/optional.hpp>
@@ -20,7 +19,6 @@
20#include "common/math_util.h" 19#include "common/math_util.h"
21#include "common/microprofile.h" 20#include "common/microprofile.h"
22#include "common/scope_exit.h" 21#include "common/scope_exit.h"
23#include "common/vector_math.h"
24#include "core/core.h" 22#include "core/core.h"
25#include "core/frontend/emu_window.h" 23#include "core/frontend/emu_window.h"
26#include "core/hle/kernel/process.h" 24#include "core/hle/kernel/process.h"
@@ -36,6 +34,7 @@
36 34
37using SurfaceType = SurfaceParams::SurfaceType; 35using SurfaceType = SurfaceParams::SurfaceType;
38using PixelFormat = SurfaceParams::PixelFormat; 36using PixelFormat = SurfaceParams::PixelFormat;
37using ComponentType = SurfaceParams::ComponentType;
39 38
40struct FormatTuple { 39struct FormatTuple {
41 GLint internal_format; 40 GLint internal_format;
@@ -47,26 +46,24 @@ struct FormatTuple {
47 u32 compression_factor; 46 u32 compression_factor;
48}; 47};
49 48
50static constexpr std::array<FormatTuple, 1> fb_format_tuples = {{ 49static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_format_tuples = {{
51 {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, false, 1}, // RGBA8 50 {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, false, 1}, // ABGR8
51 {GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV, false, 1}, // B5G6R5
52 {GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, true, 16}, // DXT1
53 {GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true, 16}, // DXT23
54 {GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true, 16}, // DXT45
52}}; 55}};
53 56
54static constexpr std::array<FormatTuple, 2> tex_format_tuples = {{ 57static const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType component_type) {
55 {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, false, 1}, // RGBA8
56 {GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, true, 16}, // DXT1
57}};
58
59static const FormatTuple& GetFormatTuple(PixelFormat pixel_format) {
60 const SurfaceType type = SurfaceParams::GetFormatType(pixel_format); 58 const SurfaceType type = SurfaceParams::GetFormatType(pixel_format);
61 if (type == SurfaceType::Color) { 59 if (type == SurfaceType::ColorTexture) {
62 ASSERT(static_cast<size_t>(pixel_format) < fb_format_tuples.size()); 60 ASSERT(static_cast<size_t>(pixel_format) < tex_format_tuples.size());
63 return fb_format_tuples[static_cast<unsigned int>(pixel_format)]; 61 // For now only UNORM components are supported
62 ASSERT(component_type == ComponentType::UNorm);
63 return tex_format_tuples[static_cast<unsigned int>(pixel_format)];
64 } else if (type == SurfaceType::Depth || type == SurfaceType::DepthStencil) { 64 } else if (type == SurfaceType::Depth || type == SurfaceType::DepthStencil) {
65 // TODO(Subv): Implement depth formats 65 // TODO(Subv): Implement depth formats
66 ASSERT_MSG(false, "Unimplemented"); 66 ASSERT_MSG(false, "Unimplemented");
67 } else if (type == SurfaceType::Texture) {
68 ASSERT(static_cast<size_t>(pixel_format) < tex_format_tuples.size());
69 return tex_format_tuples[static_cast<unsigned int>(pixel_format)];
70 } 67 }
71 68
72 UNREACHABLE(); 69 UNREACHABLE();
@@ -85,56 +82,42 @@ static u16 GetResolutionScaleFactor() {
85} 82}
86 83
87template <bool morton_to_gl, PixelFormat format> 84template <bool morton_to_gl, PixelFormat format>
88static void MortonCopyTile(u32 stride, u8* tile_buffer, u8* gl_buffer) { 85void MortonCopy(u32 stride, u32 block_height, u32 height, u8* gl_buffer, VAddr base, VAddr start,
89 constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(format) / 8; 86 VAddr end) {
90 constexpr u32 gl_bytes_per_pixel = CachedSurface::GetGLBytesPerPixel(format);
91 for (u32 y = 0; y < 8; ++y) {
92 for (u32 x = 0; x < 8; ++x) {
93 u8* tile_ptr = tile_buffer + VideoCore::MortonInterleave(x, y) * bytes_per_pixel;
94 u8* gl_ptr = gl_buffer + ((7 - y) * stride + x) * gl_bytes_per_pixel;
95 if (morton_to_gl) {
96 std::memcpy(gl_ptr, tile_ptr, bytes_per_pixel);
97 } else {
98 std::memcpy(tile_ptr, gl_ptr, bytes_per_pixel);
99 }
100 }
101 }
102}
103
104template <bool morton_to_gl, PixelFormat format>
105void MortonCopy(u32 stride, u32 height, u8* gl_buffer, VAddr base, VAddr start, VAddr end) {
106 constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(format) / 8; 87 constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(format) / 8;
107 constexpr u32 gl_bytes_per_pixel = CachedSurface::GetGLBytesPerPixel(format); 88 constexpr u32 gl_bytes_per_pixel = CachedSurface::GetGLBytesPerPixel(format);
108 89
109 // TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should check the 90 if (morton_to_gl) {
110 // configuration for this and perform more generic un/swizzle 91 auto data = Tegra::Texture::UnswizzleTexture(
111 LOG_WARNING(Render_OpenGL, "need to use correct swizzle/GOB parameters!"); 92 base, SurfaceParams::TextureFormatFromPixelFormat(format), stride, height,
112 VideoCore::MortonCopyPixels128(stride, height, bytes_per_pixel, gl_bytes_per_pixel, 93 block_height);
113 Memory::GetPointer(base), gl_buffer, morton_to_gl); 94 std::memcpy(gl_buffer, data.data(), data.size());
114} 95 } else {
115 96 // TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should check
116template <> 97 // the configuration for this and perform more generic un/swizzle
117void MortonCopy<true, PixelFormat::DXT1>(u32 stride, u32 height, u8* gl_buffer, VAddr base, 98 LOG_WARNING(Render_OpenGL, "need to use correct swizzle/GOB parameters!");
118 VAddr start, VAddr end) { 99 VideoCore::MortonCopyPixels128(stride, height, bytes_per_pixel, gl_bytes_per_pixel,
119 constexpr u32 bytes_per_pixel = SurfaceParams::GetFormatBpp(PixelFormat::DXT1) / 8; 100 Memory::GetPointer(base), gl_buffer, morton_to_gl);
120 constexpr u32 gl_bytes_per_pixel = CachedSurface::GetGLBytesPerPixel(PixelFormat::DXT1); 101 }
121
122 // TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should check the
123 // configuration for this and perform more generic un/swizzle
124 LOG_WARNING(Render_OpenGL, "need to use correct swizzle/GOB parameters!");
125 auto data =
126 Tegra::Texture::UnswizzleTexture(base, Tegra::Texture::TextureFormat::DXT1, stride, height);
127 std::memcpy(gl_buffer, data.data(), data.size());
128} 102}
129 103
130static constexpr std::array<void (*)(u32, u32, u8*, VAddr, VAddr, VAddr), 2> morton_to_gl_fns = { 104static constexpr std::array<void (*)(u32, u32, u32, u8*, VAddr, VAddr, VAddr),
131 MortonCopy<true, PixelFormat::RGBA8>, 105 SurfaceParams::MaxPixelFormat>
132 MortonCopy<true, PixelFormat::DXT1>, 106 morton_to_gl_fns = {
107 MortonCopy<true, PixelFormat::ABGR8>, MortonCopy<true, PixelFormat::B5G6R5>,
108 MortonCopy<true, PixelFormat::DXT1>, MortonCopy<true, PixelFormat::DXT23>,
109 MortonCopy<true, PixelFormat::DXT45>,
133}; 110};
134 111
135static constexpr std::array<void (*)(u32, u32, u8*, VAddr, VAddr, VAddr), 2> gl_to_morton_fns = { 112static constexpr std::array<void (*)(u32, u32, u32, u8*, VAddr, VAddr, VAddr),
136 MortonCopy<false, PixelFormat::RGBA8>, 113 SurfaceParams::MaxPixelFormat>
137 MortonCopy<false, PixelFormat::DXT1>, 114 gl_to_morton_fns = {
115 MortonCopy<false, PixelFormat::ABGR8>,
116 MortonCopy<false, PixelFormat::B5G6R5>,
117 // TODO(Subv): Swizzling the DXT1/DXT23/DXT45 formats is not yet supported
118 nullptr,
119 nullptr,
120 nullptr,
138}; 121};
139 122
140// Allocate an uninitialized texture of appropriate size and format for the surface 123// Allocate an uninitialized texture of appropriate size and format for the surface
@@ -183,7 +166,7 @@ static bool BlitTextures(GLuint src_tex, const MathUtil::Rectangle<u32>& src_rec
183 166
184 u32 buffers = 0; 167 u32 buffers = 0;
185 168
186 if (type == SurfaceType::Color || type == SurfaceType::Texture) { 169 if (type == SurfaceType::ColorTexture) {
187 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, src_tex, 170 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, src_tex,
188 0); 171 0);
189 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 172 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0,
@@ -311,15 +294,18 @@ MathUtil::Rectangle<u32> SurfaceParams::GetScaledSubRect(const SurfaceParams& su
311 294
312bool SurfaceParams::ExactMatch(const SurfaceParams& other_surface) const { 295bool SurfaceParams::ExactMatch(const SurfaceParams& other_surface) const {
313 return std::tie(other_surface.addr, other_surface.width, other_surface.height, 296 return std::tie(other_surface.addr, other_surface.width, other_surface.height,
314 other_surface.stride, other_surface.pixel_format, other_surface.is_tiled) == 297 other_surface.stride, other_surface.block_height, other_surface.pixel_format,
315 std::tie(addr, width, height, stride, pixel_format, is_tiled) && 298 other_surface.component_type,
299 other_surface.is_tiled) == std::tie(addr, width, height, stride, block_height,
300 pixel_format, component_type, is_tiled) &&
316 pixel_format != PixelFormat::Invalid; 301 pixel_format != PixelFormat::Invalid;
317} 302}
318 303
319bool SurfaceParams::CanSubRect(const SurfaceParams& sub_surface) const { 304bool SurfaceParams::CanSubRect(const SurfaceParams& sub_surface) const {
320 return sub_surface.addr >= addr && sub_surface.end <= end && 305 return sub_surface.addr >= addr && sub_surface.end <= end &&
321 sub_surface.pixel_format == pixel_format && pixel_format != PixelFormat::Invalid && 306 sub_surface.pixel_format == pixel_format && pixel_format != PixelFormat::Invalid &&
322 sub_surface.is_tiled == is_tiled && 307 sub_surface.is_tiled == is_tiled && sub_surface.block_height == block_height &&
308 sub_surface.component_type == component_type &&
323 (sub_surface.addr - addr) % BytesInPixels(is_tiled ? 64 : 1) == 0 && 309 (sub_surface.addr - addr) % BytesInPixels(is_tiled ? 64 : 1) == 0 &&
324 (sub_surface.stride == stride || sub_surface.height <= (is_tiled ? 8u : 1u)) && 310 (sub_surface.stride == stride || sub_surface.height <= (is_tiled ? 8u : 1u)) &&
325 GetSubRect(sub_surface).left + sub_surface.width <= stride; 311 GetSubRect(sub_surface).left + sub_surface.width <= stride;
@@ -328,7 +314,8 @@ bool SurfaceParams::CanSubRect(const SurfaceParams& sub_surface) const {
328bool SurfaceParams::CanExpand(const SurfaceParams& expanded_surface) const { 314bool SurfaceParams::CanExpand(const SurfaceParams& expanded_surface) const {
329 return pixel_format != PixelFormat::Invalid && pixel_format == expanded_surface.pixel_format && 315 return pixel_format != PixelFormat::Invalid && pixel_format == expanded_surface.pixel_format &&
330 addr <= expanded_surface.end && expanded_surface.addr <= end && 316 addr <= expanded_surface.end && expanded_surface.addr <= end &&
331 is_tiled == expanded_surface.is_tiled && stride == expanded_surface.stride && 317 is_tiled == expanded_surface.is_tiled && block_height == expanded_surface.block_height &&
318 component_type == expanded_surface.component_type && stride == expanded_surface.stride &&
332 (std::max(expanded_surface.addr, addr) - std::min(expanded_surface.addr, addr)) % 319 (std::max(expanded_surface.addr, addr) - std::min(expanded_surface.addr, addr)) %
333 BytesInPixels(stride * (is_tiled ? 8 : 1)) == 320 BytesInPixels(stride * (is_tiled ? 8 : 1)) ==
334 0; 321 0;
@@ -339,6 +326,10 @@ bool SurfaceParams::CanTexCopy(const SurfaceParams& texcopy_params) const {
339 end < texcopy_params.end) { 326 end < texcopy_params.end) {
340 return false; 327 return false;
341 } 328 }
329 if (texcopy_params.block_height != block_height ||
330 texcopy_params.component_type != component_type)
331 return false;
332
342 if (texcopy_params.width != texcopy_params.stride) { 333 if (texcopy_params.width != texcopy_params.stride) {
343 const u32 tile_stride = static_cast<u32>(BytesInPixels(stride * (is_tiled ? 8 : 1))); 334 const u32 tile_stride = static_cast<u32>(BytesInPixels(stride * (is_tiled ? 8 : 1)));
344 return (texcopy_params.addr - addr) % BytesInPixels(is_tiled ? 64 : 1) == 0 && 335 return (texcopy_params.addr - addr) % BytesInPixels(is_tiled ? 64 : 1) == 0 &&
@@ -481,18 +472,13 @@ void CachedSurface::LoadGLBuffer(VAddr load_start, VAddr load_end) {
481 const u64 start_offset = load_start - addr; 472 const u64 start_offset = load_start - addr;
482 473
483 if (!is_tiled) { 474 if (!is_tiled) {
484 ASSERT(type == SurfaceType::Color);
485 const u32 bytes_per_pixel{GetFormatBpp() >> 3}; 475 const u32 bytes_per_pixel{GetFormatBpp() >> 3};
486 476
487 // TODO(bunnei): Assumes the default rendering GOB size of 16 (128 lines). We should check 477 std::memcpy(&gl_buffer[start_offset], texture_src_data + start_offset,
488 // the configuration for this and perform more generic un/swizzle 478 bytes_per_pixel * width * height);
489 LOG_WARNING(Render_OpenGL, "need to use correct swizzle/GOB parameters!");
490 VideoCore::MortonCopyPixels128(width, height, bytes_per_pixel, 4,
491 texture_src_data + start_offset, &gl_buffer[start_offset],
492 true);
493 } else { 479 } else {
494 morton_to_gl_fns[static_cast<size_t>(pixel_format)](stride, height, &gl_buffer[0], addr, 480 morton_to_gl_fns[static_cast<size_t>(pixel_format)](
495 load_start, load_end); 481 stride, block_height, height, &gl_buffer[0], addr, load_start, load_end);
496 } 482 }
497} 483}
498 484
@@ -533,11 +519,10 @@ void CachedSurface::FlushGLBuffer(VAddr flush_start, VAddr flush_end) {
533 if (backup_bytes) 519 if (backup_bytes)
534 std::memcpy(&dst_buffer[coarse_start_offset], &backup_data[0], backup_bytes); 520 std::memcpy(&dst_buffer[coarse_start_offset], &backup_data[0], backup_bytes);
535 } else if (!is_tiled) { 521 } else if (!is_tiled) {
536 ASSERT(type == SurfaceType::Color);
537 std::memcpy(dst_buffer + start_offset, &gl_buffer[start_offset], flush_end - flush_start); 522 std::memcpy(dst_buffer + start_offset, &gl_buffer[start_offset], flush_end - flush_start);
538 } else { 523 } else {
539 gl_to_morton_fns[static_cast<size_t>(pixel_format)](stride, height, &gl_buffer[0], addr, 524 gl_to_morton_fns[static_cast<size_t>(pixel_format)](
540 flush_start, flush_end); 525 stride, block_height, height, &gl_buffer[0], addr, flush_start, flush_end);
541 } 526 }
542} 527}
543 528
@@ -556,7 +541,7 @@ void CachedSurface::UploadGLTexture(const MathUtil::Rectangle<u32>& rect, GLuint
556 GLint y0 = static_cast<GLint>(rect.bottom); 541 GLint y0 = static_cast<GLint>(rect.bottom);
557 size_t buffer_offset = (y0 * stride + x0) * GetGLBytesPerPixel(pixel_format); 542 size_t buffer_offset = (y0 * stride + x0) * GetGLBytesPerPixel(pixel_format);
558 543
559 const FormatTuple& tuple = GetFormatTuple(pixel_format); 544 const FormatTuple& tuple = GetFormatTuple(pixel_format, component_type);
560 GLuint target_tex = texture.handle; 545 GLuint target_tex = texture.handle;
561 546
562 // If not 1x scale, create 1x texture that we will blit from to replace texture subrect in 547 // If not 1x scale, create 1x texture that we will blit from to replace texture subrect in
@@ -629,7 +614,7 @@ void CachedSurface::DownloadGLTexture(const MathUtil::Rectangle<u32>& rect, GLui
629 OpenGLState prev_state = state; 614 OpenGLState prev_state = state;
630 SCOPE_EXIT({ prev_state.Apply(); }); 615 SCOPE_EXIT({ prev_state.Apply(); });
631 616
632 const FormatTuple& tuple = GetFormatTuple(pixel_format); 617 const FormatTuple& tuple = GetFormatTuple(pixel_format, component_type);
633 618
634 // Ensure no bad interactions with GL_PACK_ALIGNMENT 619 // Ensure no bad interactions with GL_PACK_ALIGNMENT
635 ASSERT(stride * GetGLBytesPerPixel(pixel_format) % 4 == 0); 620 ASSERT(stride * GetGLBytesPerPixel(pixel_format) % 4 == 0);
@@ -662,7 +647,7 @@ void CachedSurface::DownloadGLTexture(const MathUtil::Rectangle<u32>& rect, GLui
662 state.draw.read_framebuffer = read_fb_handle; 647 state.draw.read_framebuffer = read_fb_handle;
663 state.Apply(); 648 state.Apply();
664 649
665 if (type == SurfaceType::Color || type == SurfaceType::Texture) { 650 if (type == SurfaceType::ColorTexture) {
666 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 651 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
667 texture.handle, 0); 652 texture.handle, 0);
668 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 653 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
@@ -685,7 +670,8 @@ void CachedSurface::DownloadGLTexture(const MathUtil::Rectangle<u32>& rect, GLui
685 glPixelStorei(GL_PACK_ROW_LENGTH, 0); 670 glPixelStorei(GL_PACK_ROW_LENGTH, 0);
686} 671}
687 672
688enum MatchFlags { 673enum class MatchFlags {
674 None = 0,
689 Invalid = 1, // Flag that can be applied to other match types, invalid matches require 675 Invalid = 1, // Flag that can be applied to other match types, invalid matches require
690 // validation before they can be used 676 // validation before they can be used
691 Exact = 1 << 1, // Surfaces perfectly match 677 Exact = 1 << 1, // Surfaces perfectly match
@@ -699,6 +685,10 @@ constexpr MatchFlags operator|(MatchFlags lhs, MatchFlags rhs) {
699 return static_cast<MatchFlags>(static_cast<int>(lhs) | static_cast<int>(rhs)); 685 return static_cast<MatchFlags>(static_cast<int>(lhs) | static_cast<int>(rhs));
700} 686}
701 687
688constexpr MatchFlags operator&(MatchFlags lhs, MatchFlags rhs) {
689 return static_cast<MatchFlags>(static_cast<int>(lhs) & static_cast<int>(rhs));
690}
691
702/// Get the best surface match (and its match type) for the given flags 692/// Get the best surface match (and its match type) for the given flags
703template <MatchFlags find_flags> 693template <MatchFlags find_flags>
704Surface FindMatch(const SurfaceCache& surface_cache, const SurfaceParams& params, 694Surface FindMatch(const SurfaceCache& surface_cache, const SurfaceParams& params,
@@ -716,15 +706,15 @@ Surface FindMatch(const SurfaceCache& surface_cache, const SurfaceParams& params
716 : (params.res_scale <= surface->res_scale); 706 : (params.res_scale <= surface->res_scale);
717 // validity will be checked in GetCopyableInterval 707 // validity will be checked in GetCopyableInterval
718 bool is_valid = 708 bool is_valid =
719 find_flags & MatchFlags::Copy 709 (find_flags & MatchFlags::Copy) != MatchFlags::None
720 ? true 710 ? true
721 : surface->IsRegionValid(validate_interval.value_or(params.GetInterval())); 711 : surface->IsRegionValid(validate_interval.value_or(params.GetInterval()));
722 712
723 if (!(find_flags & MatchFlags::Invalid) && !is_valid) 713 if ((find_flags & MatchFlags::Invalid) == MatchFlags::None && !is_valid)
724 continue; 714 continue;
725 715
726 auto IsMatch_Helper = [&](auto check_type, auto match_fn) { 716 auto IsMatch_Helper = [&](auto check_type, auto match_fn) {
727 if (!(find_flags & check_type)) 717 if ((find_flags & check_type) == MatchFlags::None)
728 return; 718 return;
729 719
730 bool matched; 720 bool matched;
@@ -818,7 +808,7 @@ void main() {
818 color = texelFetch(tbo, tbo_offset).rabg; 808 color = texelFetch(tbo, tbo_offset).rabg;
819} 809}
820)"; 810)";
821 d24s8_abgr_shader.Create(vs_source, nullptr, fs_source); 811 d24s8_abgr_shader.CreateFromSource(vs_source, nullptr, fs_source);
822 812
823 OpenGLState state = OpenGLState::GetCurState(); 813 OpenGLState state = OpenGLState::GetCurState();
824 GLuint old_program = state.draw.shader_program; 814 GLuint old_program = state.draw.shader_program;
@@ -1041,9 +1031,25 @@ Surface RasterizerCacheOpenGL::GetTextureSurface(const Tegra::Texture::FullTextu
1041 params.height = config.tic.Height(); 1031 params.height = config.tic.Height();
1042 params.is_tiled = config.tic.IsTiled(); 1032 params.is_tiled = config.tic.IsTiled();
1043 params.pixel_format = SurfaceParams::PixelFormatFromTextureFormat(config.tic.format); 1033 params.pixel_format = SurfaceParams::PixelFormatFromTextureFormat(config.tic.format);
1034
1035 // TODO(Subv): Different types per component are not supported.
1036 ASSERT(config.tic.r_type.Value() == config.tic.g_type.Value() &&
1037 config.tic.r_type.Value() == config.tic.b_type.Value() &&
1038 config.tic.r_type.Value() == config.tic.a_type.Value());
1039
1040 params.component_type = SurfaceParams::ComponentTypeFromTexture(config.tic.r_type.Value());
1041
1042 if (config.tic.IsTiled()) {
1043 params.block_height = config.tic.BlockHeight();
1044 } else {
1045 // Use the texture-provided stride value if the texture isn't tiled.
1046 params.stride = params.PixelsInBytes(config.tic.Pitch());
1047 }
1048
1044 params.UpdateParams(); 1049 params.UpdateParams();
1045 1050
1046 if (config.tic.Width() % 8 != 0 || config.tic.Height() % 8 != 0) { 1051 if (config.tic.Width() % 8 != 0 || config.tic.Height() % 8 != 0 ||
1052 params.stride != params.width) {
1047 Surface src_surface; 1053 Surface src_surface;
1048 MathUtil::Rectangle<u32> rect; 1054 MathUtil::Rectangle<u32> rect;
1049 std::tie(src_surface, rect) = GetSurfaceSubRect(params, ScaleMatch::Ignore, true); 1055 std::tie(src_surface, rect) = GetSurfaceSubRect(params, ScaleMatch::Ignore, true);
@@ -1083,10 +1089,10 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces(
1083 } 1089 }
1084 1090
1085 MathUtil::Rectangle<u32> viewport_clamped{ 1091 MathUtil::Rectangle<u32> viewport_clamped{
1086 static_cast<u32>(MathUtil::Clamp(viewport.left, 0, static_cast<s32>(config.width))), 1092 static_cast<u32>(std::clamp(viewport.left, 0, static_cast<s32>(config.width))),
1087 static_cast<u32>(MathUtil::Clamp(viewport.top, 0, static_cast<s32>(config.height))), 1093 static_cast<u32>(std::clamp(viewport.top, 0, static_cast<s32>(config.height))),
1088 static_cast<u32>(MathUtil::Clamp(viewport.right, 0, static_cast<s32>(config.width))), 1094 static_cast<u32>(std::clamp(viewport.right, 0, static_cast<s32>(config.width))),
1089 static_cast<u32>(MathUtil::Clamp(viewport.bottom, 0, static_cast<s32>(config.height)))}; 1095 static_cast<u32>(std::clamp(viewport.bottom, 0, static_cast<s32>(config.height)))};
1090 1096
1091 // get color and depth surfaces 1097 // get color and depth surfaces
1092 SurfaceParams color_params; 1098 SurfaceParams color_params;
@@ -1094,10 +1100,13 @@ SurfaceSurfaceRect_Tuple RasterizerCacheOpenGL::GetFramebufferSurfaces(
1094 color_params.res_scale = resolution_scale_factor; 1100 color_params.res_scale = resolution_scale_factor;
1095 color_params.width = config.width; 1101 color_params.width = config.width;
1096 color_params.height = config.height; 1102 color_params.height = config.height;
1103 // TODO(Subv): Can framebuffers use a different block height?
1104 color_params.block_height = Tegra::Texture::TICEntry::DefaultBlockHeight;
1097 SurfaceParams depth_params = color_params; 1105 SurfaceParams depth_params = color_params;
1098 1106
1099 color_params.addr = memory_manager->PhysicalToVirtualAddress(config.Address()); 1107 color_params.addr = memory_manager->PhysicalToVirtualAddress(config.Address());
1100 color_params.pixel_format = SurfaceParams::PixelFormatFromRenderTargetFormat(config.format); 1108 color_params.pixel_format = SurfaceParams::PixelFormatFromRenderTargetFormat(config.format);
1109 color_params.component_type = SurfaceParams::ComponentTypeFromRenderTarget(config.format);
1101 color_params.UpdateParams(); 1110 color_params.UpdateParams();
1102 1111
1103 ASSERT_MSG(!using_depth_fb, "depth buffer is unimplemented"); 1112 ASSERT_MSG(!using_depth_fb, "depth buffer is unimplemented");
@@ -1293,7 +1302,6 @@ void RasterizerCacheOpenGL::InvalidateRegion(VAddr addr, u64 size, const Surface
1293 const SurfaceInterval invalid_interval(addr, addr + size); 1302 const SurfaceInterval invalid_interval(addr, addr + size);
1294 1303
1295 if (region_owner != nullptr) { 1304 if (region_owner != nullptr) {
1296 ASSERT(region_owner->type != SurfaceType::Texture);
1297 ASSERT(addr >= region_owner->addr && addr + size <= region_owner->end); 1305 ASSERT(addr >= region_owner->addr && addr + size <= region_owner->end);
1298 // Surfaces can't have a gap 1306 // Surfaces can't have a gap
1299 ASSERT(region_owner->width == region_owner->stride); 1307 ASSERT(region_owner->width == region_owner->stride);
@@ -1355,7 +1363,8 @@ Surface RasterizerCacheOpenGL::CreateSurface(const SurfaceParams& params) {
1355 1363
1356 surface->gl_buffer_size = 0; 1364 surface->gl_buffer_size = 0;
1357 surface->invalid_regions.insert(surface->GetInterval()); 1365 surface->invalid_regions.insert(surface->GetInterval());
1358 AllocateSurfaceTexture(surface->texture.handle, GetFormatTuple(surface->pixel_format), 1366 AllocateSurfaceTexture(surface->texture.handle,
1367 GetFormatTuple(surface->pixel_format, surface->component_type),
1359 surface->GetScaledWidth(), surface->GetScaledHeight()); 1368 surface->GetScaledWidth(), surface->GetScaledHeight());
1360 1369
1361 return surface; 1370 return surface;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index 06524fc59..6861efe16 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -52,27 +52,45 @@ enum class ScaleMatch {
52 52
53struct SurfaceParams { 53struct SurfaceParams {
54 enum class PixelFormat { 54 enum class PixelFormat {
55 RGBA8 = 0, 55 ABGR8 = 0,
56 DXT1 = 1, 56 B5G6R5 = 1,
57 DXT1 = 2,
58 DXT23 = 3,
59 DXT45 = 4,
60
61 Max,
57 Invalid = 255, 62 Invalid = 255,
58 }; 63 };
59 64
65 static constexpr size_t MaxPixelFormat = static_cast<size_t>(PixelFormat::Max);
66
67 enum class ComponentType {
68 Invalid = 0,
69 SNorm = 1,
70 UNorm = 2,
71 SInt = 3,
72 UInt = 4,
73 Float = 5,
74 };
75
60 enum class SurfaceType { 76 enum class SurfaceType {
61 Color = 0, 77 ColorTexture = 0,
62 Texture = 1, 78 Depth = 1,
63 Depth = 2, 79 DepthStencil = 2,
64 DepthStencil = 3, 80 Fill = 3,
65 Fill = 4, 81 Invalid = 4,
66 Invalid = 5
67 }; 82 };
68 83
69 static constexpr unsigned int GetFormatBpp(PixelFormat format) { 84 static constexpr unsigned int GetFormatBpp(PixelFormat format) {
70 if (format == PixelFormat::Invalid) 85 if (format == PixelFormat::Invalid)
71 return 0; 86 return 0;
72 87
73 constexpr std::array<unsigned int, 2> bpp_table = { 88 constexpr std::array<unsigned int, MaxPixelFormat> bpp_table = {
74 32, // RGBA8 89 32, // ABGR8
75 64, // DXT1 90 16, // B5G6R5
91 64, // DXT1
92 128, // DXT23
93 128, // DXT45
76 }; 94 };
77 95
78 ASSERT(static_cast<size_t>(format) < bpp_table.size()); 96 ASSERT(static_cast<size_t>(format) < bpp_table.size());
@@ -85,8 +103,9 @@ struct SurfaceParams {
85 static PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format) { 103 static PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format) {
86 switch (format) { 104 switch (format) {
87 case Tegra::RenderTargetFormat::RGBA8_UNORM: 105 case Tegra::RenderTargetFormat::RGBA8_UNORM:
88 return PixelFormat::RGBA8; 106 return PixelFormat::ABGR8;
89 default: 107 default:
108 NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
90 UNREACHABLE(); 109 UNREACHABLE();
91 } 110 }
92 } 111 }
@@ -94,8 +113,9 @@ struct SurfaceParams {
94 static PixelFormat PixelFormatFromGPUPixelFormat(Tegra::FramebufferConfig::PixelFormat format) { 113 static PixelFormat PixelFormatFromGPUPixelFormat(Tegra::FramebufferConfig::PixelFormat format) {
95 switch (format) { 114 switch (format) {
96 case Tegra::FramebufferConfig::PixelFormat::ABGR8: 115 case Tegra::FramebufferConfig::PixelFormat::ABGR8:
97 return PixelFormat::RGBA8; 116 return PixelFormat::ABGR8;
98 default: 117 default:
118 NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
99 UNREACHABLE(); 119 UNREACHABLE();
100 } 120 }
101 } 121 }
@@ -104,10 +124,69 @@ struct SurfaceParams {
104 // TODO(Subv): Properly implement this 124 // TODO(Subv): Properly implement this
105 switch (format) { 125 switch (format) {
106 case Tegra::Texture::TextureFormat::A8R8G8B8: 126 case Tegra::Texture::TextureFormat::A8R8G8B8:
107 return PixelFormat::RGBA8; 127 return PixelFormat::ABGR8;
128 case Tegra::Texture::TextureFormat::B5G6R5:
129 return PixelFormat::B5G6R5;
108 case Tegra::Texture::TextureFormat::DXT1: 130 case Tegra::Texture::TextureFormat::DXT1:
109 return PixelFormat::DXT1; 131 return PixelFormat::DXT1;
132 case Tegra::Texture::TextureFormat::DXT23:
133 return PixelFormat::DXT23;
134 case Tegra::Texture::TextureFormat::DXT45:
135 return PixelFormat::DXT45;
136 default:
137 NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
138 UNREACHABLE();
139 }
140 }
141
142 static Tegra::Texture::TextureFormat TextureFormatFromPixelFormat(PixelFormat format) {
143 // TODO(Subv): Properly implement this
144 switch (format) {
145 case PixelFormat::ABGR8:
146 return Tegra::Texture::TextureFormat::A8R8G8B8;
147 case PixelFormat::B5G6R5:
148 return Tegra::Texture::TextureFormat::B5G6R5;
149 case PixelFormat::DXT1:
150 return Tegra::Texture::TextureFormat::DXT1;
151 case PixelFormat::DXT23:
152 return Tegra::Texture::TextureFormat::DXT23;
153 case PixelFormat::DXT45:
154 return Tegra::Texture::TextureFormat::DXT45;
155 default:
156 UNREACHABLE();
157 }
158 }
159
160 static ComponentType ComponentTypeFromTexture(Tegra::Texture::ComponentType type) {
161 // TODO(Subv): Implement more component types
162 switch (type) {
163 case Tegra::Texture::ComponentType::UNORM:
164 return ComponentType::UNorm;
110 default: 165 default:
166 NGLOG_CRITICAL(HW_GPU, "Unimplemented component type={}", static_cast<u32>(type));
167 UNREACHABLE();
168 }
169 }
170
171 static ComponentType ComponentTypeFromRenderTarget(Tegra::RenderTargetFormat format) {
172 // TODO(Subv): Implement more render targets
173 switch (format) {
174 case Tegra::RenderTargetFormat::RGBA8_UNORM:
175 case Tegra::RenderTargetFormat::RGB10_A2_UNORM:
176 return ComponentType::UNorm;
177 default:
178 NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
179 UNREACHABLE();
180 }
181 }
182
183 static ComponentType ComponentTypeFromGPUPixelFormat(
184 Tegra::FramebufferConfig::PixelFormat format) {
185 switch (format) {
186 case Tegra::FramebufferConfig::PixelFormat::ABGR8:
187 return ComponentType::UNorm;
188 default:
189 NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
111 UNREACHABLE(); 190 UNREACHABLE();
112 } 191 }
113 } 192 }
@@ -116,8 +195,7 @@ struct SurfaceParams {
116 SurfaceType a_type = GetFormatType(pixel_format_a); 195 SurfaceType a_type = GetFormatType(pixel_format_a);
117 SurfaceType b_type = GetFormatType(pixel_format_b); 196 SurfaceType b_type = GetFormatType(pixel_format_b);
118 197
119 if ((a_type == SurfaceType::Color || a_type == SurfaceType::Texture) && 198 if (a_type == SurfaceType::ColorTexture && b_type == SurfaceType::ColorTexture) {
120 (b_type == SurfaceType::Color || b_type == SurfaceType::Texture)) {
121 return true; 199 return true;
122 } 200 }
123 201
@@ -133,12 +211,8 @@ struct SurfaceParams {
133 } 211 }
134 212
135 static SurfaceType GetFormatType(PixelFormat pixel_format) { 213 static SurfaceType GetFormatType(PixelFormat pixel_format) {
136 if ((unsigned int)pixel_format <= static_cast<unsigned int>(PixelFormat::RGBA8)) { 214 if (static_cast<size_t>(pixel_format) < MaxPixelFormat) {
137 return SurfaceType::Color; 215 return SurfaceType::ColorTexture;
138 }
139
140 if ((unsigned int)pixel_format <= static_cast<unsigned int>(PixelFormat::DXT1)) {
141 return SurfaceType::Texture;
142 } 216 }
143 217
144 // TODO(Subv): Implement the other formats 218 // TODO(Subv): Implement the other formats
@@ -210,11 +284,13 @@ struct SurfaceParams {
210 u32 width = 0; 284 u32 width = 0;
211 u32 height = 0; 285 u32 height = 0;
212 u32 stride = 0; 286 u32 stride = 0;
287 u32 block_height = 0;
213 u16 res_scale = 1; 288 u16 res_scale = 1;
214 289
215 bool is_tiled = false; 290 bool is_tiled = false;
216 PixelFormat pixel_format = PixelFormat::Invalid; 291 PixelFormat pixel_format = PixelFormat::Invalid;
217 SurfaceType type = SurfaceType::Invalid; 292 SurfaceType type = SurfaceType::Invalid;
293 ComponentType component_type = ComponentType::Invalid;
218}; 294};
219 295
220struct CachedSurface : SurfaceParams { 296struct CachedSurface : SurfaceParams {
@@ -334,7 +410,7 @@ private:
334 OGLVertexArray attributeless_vao; 410 OGLVertexArray attributeless_vao;
335 OGLBuffer d24s8_abgr_buffer; 411 OGLBuffer d24s8_abgr_buffer;
336 GLsizeiptr d24s8_abgr_buffer_size; 412 GLsizeiptr d24s8_abgr_buffer_size;
337 OGLShader d24s8_abgr_shader; 413 OGLProgram d24s8_abgr_shader;
338 GLint d24s8_abgr_tbo_size_u_id; 414 GLint d24s8_abgr_tbo_size_u_id;
339 GLint d24s8_abgr_viewport_u_id; 415 GLint d24s8_abgr_viewport_u_id;
340}; 416};
diff --git a/src/video_core/renderer_opengl/gl_resource_manager.h b/src/video_core/renderer_opengl/gl_resource_manager.h
index 7da5e74d1..93f9172e7 100644
--- a/src/video_core/renderer_opengl/gl_resource_manager.h
+++ b/src/video_core/renderer_opengl/gl_resource_manager.h
@@ -13,14 +13,16 @@
13class OGLTexture : private NonCopyable { 13class OGLTexture : private NonCopyable {
14public: 14public:
15 OGLTexture() = default; 15 OGLTexture() = default;
16 OGLTexture(OGLTexture&& o) { 16
17 std::swap(handle, o.handle); 17 OGLTexture(OGLTexture&& o) noexcept : handle(std::exchange(o.handle, 0)) {}
18 } 18
19 ~OGLTexture() { 19 ~OGLTexture() {
20 Release(); 20 Release();
21 } 21 }
22 OGLTexture& operator=(OGLTexture&& o) { 22
23 std::swap(handle, o.handle); 23 OGLTexture& operator=(OGLTexture&& o) noexcept {
24 Release();
25 handle = std::exchange(o.handle, 0);
24 return *this; 26 return *this;
25 } 27 }
26 28
@@ -46,14 +48,16 @@ public:
46class OGLSampler : private NonCopyable { 48class OGLSampler : private NonCopyable {
47public: 49public:
48 OGLSampler() = default; 50 OGLSampler() = default;
49 OGLSampler(OGLSampler&& o) { 51
50 std::swap(handle, o.handle); 52 OGLSampler(OGLSampler&& o) noexcept : handle(std::exchange(o.handle, 0)) {}
51 } 53
52 ~OGLSampler() { 54 ~OGLSampler() {
53 Release(); 55 Release();
54 } 56 }
55 OGLSampler& operator=(OGLSampler&& o) { 57
56 std::swap(handle, o.handle); 58 OGLSampler& operator=(OGLSampler&& o) noexcept {
59 Release();
60 handle = std::exchange(o.handle, 0);
57 return *this; 61 return *this;
58 } 62 }
59 63
@@ -79,25 +83,71 @@ public:
79class OGLShader : private NonCopyable { 83class OGLShader : private NonCopyable {
80public: 84public:
81 OGLShader() = default; 85 OGLShader() = default;
82 OGLShader(OGLShader&& o) { 86
83 std::swap(handle, o.handle); 87 OGLShader(OGLShader&& o) noexcept : handle(std::exchange(o.handle, 0)) {}
84 } 88
85 ~OGLShader() { 89 ~OGLShader() {
86 Release(); 90 Release();
87 } 91 }
88 OGLShader& operator=(OGLShader&& o) { 92
89 std::swap(handle, o.handle); 93 OGLShader& operator=(OGLShader&& o) noexcept {
94 Release();
95 handle = std::exchange(o.handle, 0);
90 return *this; 96 return *this;
91 } 97 }
92 98
93 /// Creates a new internal OpenGL resource and stores the handle 99 void Create(const char* source, GLenum type) {
94 void Create(const char* vert_shader, const char* geo_shader, const char* frag_shader,
95 const std::vector<const char*>& feedback_vars = {},
96 bool separable_program = false) {
97 if (handle != 0) 100 if (handle != 0)
98 return; 101 return;
99 handle = GLShader::LoadProgram(vert_shader, geo_shader, frag_shader, feedback_vars, 102 if (source == nullptr)
100 separable_program); 103 return;
104 handle = GLShader::LoadShader(source, type);
105 }
106
107 void Release() {
108 if (handle == 0)
109 return;
110 glDeleteShader(handle);
111 handle = 0;
112 }
113
114 GLuint handle = 0;
115};
116
117class OGLProgram : private NonCopyable {
118public:
119 OGLProgram() = default;
120
121 OGLProgram(OGLProgram&& o) noexcept : handle(std::exchange(o.handle, 0)) {}
122
123 ~OGLProgram() {
124 Release();
125 }
126
127 OGLProgram& operator=(OGLProgram&& o) noexcept {
128 Release();
129 handle = std::exchange(o.handle, 0);
130 return *this;
131 }
132
133 template <typename... T>
134 void Create(bool separable_program, T... shaders) {
135 if (handle != 0)
136 return;
137 handle = GLShader::LoadProgram(separable_program, shaders...);
138 }
139
140 /// Creates a new internal OpenGL resource and stores the handle
141 void CreateFromSource(const char* vert_shader, const char* geo_shader, const char* frag_shader,
142 bool separable_program = false) {
143 OGLShader vert, geo, frag;
144 if (vert_shader)
145 vert.Create(vert_shader, GL_VERTEX_SHADER);
146 if (geo_shader)
147 geo.Create(geo_shader, GL_GEOMETRY_SHADER);
148 if (frag_shader)
149 frag.Create(frag_shader, GL_FRAGMENT_SHADER);
150 Create(separable_program, vert.handle, geo.handle, frag.handle);
101 } 151 }
102 152
103 /// Deletes the internal OpenGL resource 153 /// Deletes the internal OpenGL resource
@@ -115,13 +165,12 @@ public:
115class OGLPipeline : private NonCopyable { 165class OGLPipeline : private NonCopyable {
116public: 166public:
117 OGLPipeline() = default; 167 OGLPipeline() = default;
118 OGLPipeline(OGLPipeline&& o) { 168 OGLPipeline(OGLPipeline&& o) noexcept : handle{std::exchange<GLuint>(o.handle, 0)} {}
119 handle = std::exchange<GLuint>(o.handle, 0); 169
120 }
121 ~OGLPipeline() { 170 ~OGLPipeline() {
122 Release(); 171 Release();
123 } 172 }
124 OGLPipeline& operator=(OGLPipeline&& o) { 173 OGLPipeline& operator=(OGLPipeline&& o) noexcept {
125 handle = std::exchange<GLuint>(o.handle, 0); 174 handle = std::exchange<GLuint>(o.handle, 0);
126 return *this; 175 return *this;
127 } 176 }
@@ -148,14 +197,16 @@ public:
148class OGLBuffer : private NonCopyable { 197class OGLBuffer : private NonCopyable {
149public: 198public:
150 OGLBuffer() = default; 199 OGLBuffer() = default;
151 OGLBuffer(OGLBuffer&& o) { 200
152 std::swap(handle, o.handle); 201 OGLBuffer(OGLBuffer&& o) noexcept : handle(std::exchange(o.handle, 0)) {}
153 } 202
154 ~OGLBuffer() { 203 ~OGLBuffer() {
155 Release(); 204 Release();
156 } 205 }
157 OGLBuffer& operator=(OGLBuffer&& o) { 206
158 std::swap(handle, o.handle); 207 OGLBuffer& operator=(OGLBuffer&& o) noexcept {
208 Release();
209 handle = std::exchange(o.handle, 0);
159 return *this; 210 return *this;
160 } 211 }
161 212
@@ -182,12 +233,12 @@ class OGLSync : private NonCopyable {
182public: 233public:
183 OGLSync() = default; 234 OGLSync() = default;
184 235
185 OGLSync(OGLSync&& o) : handle(std::exchange(o.handle, nullptr)) {} 236 OGLSync(OGLSync&& o) noexcept : handle(std::exchange(o.handle, nullptr)) {}
186 237
187 ~OGLSync() { 238 ~OGLSync() {
188 Release(); 239 Release();
189 } 240 }
190 OGLSync& operator=(OGLSync&& o) { 241 OGLSync& operator=(OGLSync&& o) noexcept {
191 Release(); 242 Release();
192 handle = std::exchange(o.handle, nullptr); 243 handle = std::exchange(o.handle, nullptr);
193 return *this; 244 return *this;
@@ -214,14 +265,16 @@ public:
214class OGLVertexArray : private NonCopyable { 265class OGLVertexArray : private NonCopyable {
215public: 266public:
216 OGLVertexArray() = default; 267 OGLVertexArray() = default;
217 OGLVertexArray(OGLVertexArray&& o) { 268
218 std::swap(handle, o.handle); 269 OGLVertexArray(OGLVertexArray&& o) noexcept : handle(std::exchange(o.handle, 0)) {}
219 } 270
220 ~OGLVertexArray() { 271 ~OGLVertexArray() {
221 Release(); 272 Release();
222 } 273 }
223 OGLVertexArray& operator=(OGLVertexArray&& o) { 274
224 std::swap(handle, o.handle); 275 OGLVertexArray& operator=(OGLVertexArray&& o) noexcept {
276 Release();
277 handle = std::exchange(o.handle, 0);
225 return *this; 278 return *this;
226 } 279 }
227 280
@@ -247,14 +300,16 @@ public:
247class OGLFramebuffer : private NonCopyable { 300class OGLFramebuffer : private NonCopyable {
248public: 301public:
249 OGLFramebuffer() = default; 302 OGLFramebuffer() = default;
250 OGLFramebuffer(OGLFramebuffer&& o) { 303
251 std::swap(handle, o.handle); 304 OGLFramebuffer(OGLFramebuffer&& o) noexcept : handle(std::exchange(o.handle, 0)) {}
252 } 305
253 ~OGLFramebuffer() { 306 ~OGLFramebuffer() {
254 Release(); 307 Release();
255 } 308 }
256 OGLFramebuffer& operator=(OGLFramebuffer&& o) { 309
257 std::swap(handle, o.handle); 310 OGLFramebuffer& operator=(OGLFramebuffer&& o) noexcept {
311 Release();
312 handle = std::exchange(o.handle, 0);
258 return *this; 313 return *this;
259 } 314 }
260 315
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 564ea8f9e..086424395 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -2,57 +2,778 @@
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 <map>
6#include <set>
5#include <string> 7#include <string>
6#include <queue> 8#include <string_view>
7#include "common/assert.h" 9#include "common/assert.h"
8#include "common/common_types.h" 10#include "common/common_types.h"
11#include "video_core/engines/shader_bytecode.h"
9#include "video_core/renderer_opengl/gl_shader_decompiler.h" 12#include "video_core/renderer_opengl/gl_shader_decompiler.h"
10 13
11namespace Maxwell3D { 14namespace GLShader {
12namespace Shader {
13namespace Decompiler { 15namespace Decompiler {
14 16
17using Tegra::Shader::Attribute;
18using Tegra::Shader::Instruction;
19using Tegra::Shader::OpCode;
20using Tegra::Shader::Register;
21using Tegra::Shader::Sampler;
22using Tegra::Shader::SubOp;
23using Tegra::Shader::Uniform;
24
15constexpr u32 PROGRAM_END = MAX_PROGRAM_CODE_LENGTH; 25constexpr u32 PROGRAM_END = MAX_PROGRAM_CODE_LENGTH;
16 26
17class Impl { 27class DecompileFail : public std::runtime_error {
28public:
29 using std::runtime_error::runtime_error;
30};
31
32/// Describes the behaviour of code path of a given entry point and a return point.
33enum class ExitMethod {
34 Undetermined, ///< Internal value. Only occur when analyzing JMP loop.
35 AlwaysReturn, ///< All code paths reach the return point.
36 Conditional, ///< Code path reaches the return point or an END instruction conditionally.
37 AlwaysEnd, ///< All code paths reach a END instruction.
38};
39
40/// A subroutine is a range of code refereced by a CALL, IF or LOOP instruction.
41struct Subroutine {
42 /// Generates a name suitable for GLSL source code.
43 std::string GetName() const {
44 return "sub_" + std::to_string(begin) + "_" + std::to_string(end);
45 }
46
47 u32 begin; ///< Entry point of the subroutine.
48 u32 end; ///< Return point of the subroutine.
49 ExitMethod exit_method; ///< Exit method of the subroutine.
50 std::set<u32> labels; ///< Addresses refereced by JMP instructions.
51
52 bool operator<(const Subroutine& rhs) const {
53 return std::tie(begin, end) < std::tie(rhs.begin, rhs.end);
54 }
55};
56
57/// Analyzes shader code and produces a set of subroutines.
58class ControlFlowAnalyzer {
18public: 59public:
19 Impl(const std::array<u32, MAX_PROGRAM_CODE_LENGTH>& program_code, 60 ControlFlowAnalyzer(const ProgramCode& program_code, u32 main_offset)
20 const std::array<u32, MAX_SWIZZLE_DATA_LENGTH>& swizzle_data, u32 main_offset, 61 : program_code(program_code) {
21 const std::function<std::string(u32)>& inputreg_getter, 62
22 const std::function<std::string(u32)>& outputreg_getter, bool sanitize_mul, 63 // Recursively finds all subroutines.
23 const std::string& emit_cb, const std::string& setemit_cb) 64 const Subroutine& program_main = AddSubroutine(main_offset, PROGRAM_END);
24 : program_code(program_code), swizzle_data(swizzle_data), main_offset(main_offset), 65 if (program_main.exit_method != ExitMethod::AlwaysEnd)
25 inputreg_getter(inputreg_getter), outputreg_getter(outputreg_getter), 66 throw DecompileFail("Program does not always end");
26 sanitize_mul(sanitize_mul), emit_cb(emit_cb), setemit_cb(setemit_cb) {} 67 }
27 68
28 std::string Decompile() { 69 std::set<Subroutine> GetSubroutines() {
29 UNREACHABLE(); 70 return std::move(subroutines);
30 return {};
31 } 71 }
32 72
33private: 73private:
34 const std::array<u32, MAX_PROGRAM_CODE_LENGTH>& program_code; 74 const ProgramCode& program_code;
35 const std::array<u32, MAX_SWIZZLE_DATA_LENGTH>& swizzle_data; 75 std::set<Subroutine> subroutines;
36 u32 main_offset; 76 std::map<std::pair<u32, u32>, ExitMethod> exit_method_map;
37 const std::function<std::string(u32)>& inputreg_getter; 77
38 const std::function<std::string(u32)>& outputreg_getter; 78 /// Adds and analyzes a new subroutine if it is not added yet.
39 bool sanitize_mul; 79 const Subroutine& AddSubroutine(u32 begin, u32 end) {
40 const std::string& emit_cb; 80 auto iter = subroutines.find(Subroutine{begin, end});
41 const std::string& setemit_cb; 81 if (iter != subroutines.end())
82 return *iter;
83
84 Subroutine subroutine{begin, end};
85 subroutine.exit_method = Scan(begin, end, subroutine.labels);
86 if (subroutine.exit_method == ExitMethod::Undetermined)
87 throw DecompileFail("Recursive function detected");
88 return *subroutines.insert(std::move(subroutine)).first;
89 }
90
91 /// Scans a range of code for labels and determines the exit method.
92 ExitMethod Scan(u32 begin, u32 end, std::set<u32>& labels) {
93 auto [iter, inserted] =
94 exit_method_map.emplace(std::make_pair(begin, end), ExitMethod::Undetermined);
95 ExitMethod& exit_method = iter->second;
96 if (!inserted)
97 return exit_method;
98
99 for (u32 offset = begin; offset != end && offset != PROGRAM_END; ++offset) {
100 if (const auto opcode = OpCode::Decode({program_code[offset]})) {
101 switch (opcode->GetId()) {
102 case OpCode::Id::EXIT: {
103 return exit_method = ExitMethod::AlwaysEnd;
104 }
105 }
106 }
107 }
108 return exit_method = ExitMethod::AlwaysReturn;
109 }
110};
111
112class ShaderWriter {
113public:
114 void AddLine(std::string_view text) {
115 DEBUG_ASSERT(scope >= 0);
116 if (!text.empty()) {
117 AppendIndentation();
118 }
119 shader_source += text;
120 AddNewLine();
121 }
122
123 void AddLine(char character) {
124 DEBUG_ASSERT(scope >= 0);
125 AppendIndentation();
126 shader_source += character;
127 AddNewLine();
128 }
129
130 void AddNewLine() {
131 DEBUG_ASSERT(scope >= 0);
132 shader_source += '\n';
133 }
134
135 std::string GetResult() {
136 return std::move(shader_source);
137 }
138
139 int scope = 0;
140
141private:
142 void AppendIndentation() {
143 shader_source.append(static_cast<size_t>(scope) * 4, ' ');
144 }
145
146 std::string shader_source;
42}; 147};
43 148
44std::string DecompileProgram(const std::array<u32, MAX_PROGRAM_CODE_LENGTH>& program_code, 149class GLSLGenerator {
45 const std::array<u32, MAX_SWIZZLE_DATA_LENGTH>& swizzle_data, 150public:
46 u32 main_offset, 151 GLSLGenerator(const std::set<Subroutine>& subroutines, const ProgramCode& program_code,
47 const std::function<std::string(u32)>& inputreg_getter, 152 u32 main_offset, Maxwell3D::Regs::ShaderStage stage)
48 const std::function<std::string(u32)>& outputreg_getter, 153 : subroutines(subroutines), program_code(program_code), main_offset(main_offset),
49 bool sanitize_mul, const std::string& emit_cb, 154 stage(stage) {
50 const std::string& setemit_cb) { 155
51 Impl impl(program_code, swizzle_data, main_offset, inputreg_getter, outputreg_getter, 156 Generate();
52 sanitize_mul, emit_cb, setemit_cb); 157 }
53 return impl.Decompile(); 158
159 std::string GetShaderCode() {
160 return declarations.GetResult() + shader.GetResult();
161 }
162
163 /// Returns entries in the shader that are useful for external functions
164 ShaderEntries GetEntries() const {
165 return {GetConstBuffersDeclarations()};
166 }
167
168private:
169 /// Gets the Subroutine object corresponding to the specified address.
170 const Subroutine& GetSubroutine(u32 begin, u32 end) const {
171 auto iter = subroutines.find(Subroutine{begin, end});
172 ASSERT(iter != subroutines.end());
173 return *iter;
174 }
175
176 /// Generates code representing an input attribute register.
177 std::string GetInputAttribute(Attribute::Index attribute) {
178 switch (attribute) {
179 case Attribute::Index::Position:
180 return "position";
181 default:
182 const u32 index{static_cast<u32>(attribute) -
183 static_cast<u32>(Attribute::Index::Attribute_0)};
184 if (attribute >= Attribute::Index::Attribute_0) {
185 declr_input_attribute.insert(attribute);
186 return "input_attribute_" + std::to_string(index);
187 }
188
189 NGLOG_CRITICAL(HW_GPU, "Unhandled input attribute: {}", index);
190 UNREACHABLE();
191 }
192 }
193
194 /// Generates code representing an output attribute register.
195 std::string GetOutputAttribute(Attribute::Index attribute) {
196 switch (attribute) {
197 case Attribute::Index::Position:
198 return "position";
199 default:
200 const u32 index{static_cast<u32>(attribute) -
201 static_cast<u32>(Attribute::Index::Attribute_0)};
202 if (attribute >= Attribute::Index::Attribute_0) {
203 declr_output_attribute.insert(attribute);
204 return "output_attribute_" + std::to_string(index);
205 }
206
207 NGLOG_CRITICAL(HW_GPU, "Unhandled output attribute: {}", index);
208 UNREACHABLE();
209 }
210 }
211
212 /// Generates code representing a 19-bit immediate value
213 static std::string GetImmediate19(const Instruction& instr) {
214 return std::to_string(instr.alu.GetImm20_19());
215 }
216
217 /// Generates code representing a 32-bit immediate value
218 static std::string GetImmediate32(const Instruction& instr) {
219 return std::to_string(instr.alu.GetImm20_32());
220 }
221
222 /// Generates code representing a temporary (GPR) register.
223 std::string GetRegister(const Register& reg, unsigned elem = 0) {
224 if (reg == Register::ZeroIndex)
225 return "0";
226 if (stage == Maxwell3D::Regs::ShaderStage::Fragment && reg < 4) {
227 // GPRs 0-3 are output color for the fragment shader
228 return std::string{"color."} + "rgba"[(reg + elem) & 3];
229 }
230
231 return *declr_register.insert("register_" + std::to_string(reg + elem)).first;
232 }
233
234 /// Generates code representing a uniform (C buffer) register.
235 std::string GetUniform(const Uniform& reg) {
236 declr_const_buffers[reg.index].MarkAsUsed(static_cast<unsigned>(reg.index),
237 static_cast<unsigned>(reg.offset), stage);
238 return 'c' + std::to_string(reg.index) + '[' + std::to_string(reg.offset) + ']';
239 }
240
241 /// Generates code representing a texture sampler.
242 std::string GetSampler(const Sampler& sampler) const {
243 // TODO(Subv): Support more than just texture sampler 0
244 ASSERT_MSG(sampler.index == Sampler::Index::Sampler_0, "unsupported");
245 const unsigned index{static_cast<unsigned>(sampler.index.Value()) -
246 static_cast<unsigned>(Sampler::Index::Sampler_0)};
247 return "tex[" + std::to_string(index) + "]";
248 }
249
250 /**
251 * Adds code that calls a subroutine.
252 * @param subroutine the subroutine to call.
253 */
254 void CallSubroutine(const Subroutine& subroutine) {
255 if (subroutine.exit_method == ExitMethod::AlwaysEnd) {
256 shader.AddLine(subroutine.GetName() + "();");
257 shader.AddLine("return true;");
258 } else if (subroutine.exit_method == ExitMethod::Conditional) {
259 shader.AddLine("if (" + subroutine.GetName() + "()) { return true; }");
260 } else {
261 shader.AddLine(subroutine.GetName() + "();");
262 }
263 }
264
265 /**
266 * Writes code that does an assignment operation.
267 * @param reg the destination register code.
268 * @param value the code representing the value to assign.
269 */
270 void SetDest(u64 elem, const std::string& reg, const std::string& value,
271 u64 dest_num_components, u64 value_num_components, bool is_abs = false) {
272 std::string swizzle = ".";
273 swizzle += "xyzw"[elem];
274
275 std::string dest = reg + (dest_num_components != 1 ? swizzle : "");
276 std::string src = "(" + value + ")" + (value_num_components != 1 ? swizzle : "");
277 src = is_abs ? "abs(" + src + ")" : src;
278
279 shader.AddLine(dest + " = " + src + ";");
280 }
281
282 /*
283 * Writes code that assigns a predicate boolean variable.
284 * @param pred The id of the predicate to write to.
285 * @param value The expression value to assign to the predicate.
286 */
287 void SetPredicate(u64 pred, const std::string& value) {
288 using Tegra::Shader::Pred;
289 // Can't assign to the constant predicate.
290 ASSERT(pred != static_cast<u64>(Pred::UnusedIndex));
291
292 std::string variable = 'p' + std::to_string(pred);
293 shader.AddLine(variable + " = " + value + ';');
294 declr_predicates.insert(std::move(variable));
295 }
296
297 /*
298 * Returns the condition to use in the 'if' for a predicated instruction.
299 * @param instr Instruction to generate the if condition for.
300 * @returns string containing the predicate condition.
301 */
302 std::string GetPredicateCondition(Instruction instr) const {
303 using Tegra::Shader::Pred;
304 ASSERT(instr.pred.pred_index != static_cast<u64>(Pred::UnusedIndex));
305
306 std::string variable =
307 'p' + std::to_string(static_cast<u64>(instr.pred.pred_index.Value()));
308
309 if (instr.negate_pred) {
310 return "!(" + variable + ')';
311 }
312
313 return variable;
314 }
315
316 /*
317 * Returns whether the instruction at the specified offset is a 'sched' instruction.
318 * Sched instructions always appear before a sequence of 3 instructions.
319 */
320 bool IsSchedInstruction(u32 offset) const {
321 // sched instructions appear once every 4 instructions.
322 static constexpr size_t SchedPeriod = 4;
323 u32 absolute_offset = offset - main_offset;
324
325 return (absolute_offset % SchedPeriod) == 0;
326 }
327
328 /**
329 * Compiles a single instruction from Tegra to GLSL.
330 * @param offset the offset of the Tegra shader instruction.
331 * @return the offset of the next instruction to execute. Usually it is the current offset
332 * + 1. If the current instruction always terminates the program, returns PROGRAM_END.
333 */
334 u32 CompileInstr(u32 offset) {
335 // Ignore sched instructions when generating code.
336 if (IsSchedInstruction(offset)) {
337 return offset + 1;
338 }
339
340 const Instruction instr = {program_code[offset]};
341 const auto opcode = OpCode::Decode(instr);
342
343 // Decoding failure
344 if (!opcode) {
345 NGLOG_CRITICAL(HW_GPU, "Unhandled instruction: {0:x}", instr.value);
346 UNREACHABLE();
347 }
348
349 shader.AddLine("// " + std::to_string(offset) + ": " + opcode->GetName());
350
351 using Tegra::Shader::Pred;
352 ASSERT_MSG(instr.pred.full_pred != Pred::NeverExecute,
353 "NeverExecute predicate not implemented");
354
355 if (instr.pred.pred_index != static_cast<u64>(Pred::UnusedIndex)) {
356 shader.AddLine("if (" + GetPredicateCondition(instr) + ')');
357 shader.AddLine('{');
358 ++shader.scope;
359 }
360
361 switch (opcode->GetType()) {
362 case OpCode::Type::Arithmetic: {
363 std::string dest = GetRegister(instr.gpr0);
364 std::string op_a = instr.alu.negate_a ? "-" : "";
365 op_a += GetRegister(instr.gpr8);
366 if (instr.alu.abs_a) {
367 op_a = "abs(" + op_a + ")";
368 }
369
370 std::string op_b = instr.alu.negate_b ? "-" : "";
371
372 if (instr.is_b_imm) {
373 op_b += GetImmediate19(instr);
374 } else {
375 if (instr.is_b_gpr) {
376 op_b += GetRegister(instr.gpr20);
377 } else {
378 op_b += GetUniform(instr.uniform);
379 }
380 }
381
382 if (instr.alu.abs_b) {
383 op_b = "abs(" + op_b + ")";
384 }
385
386 switch (opcode->GetId()) {
387 case OpCode::Id::FMUL_C:
388 case OpCode::Id::FMUL_R:
389 case OpCode::Id::FMUL_IMM: {
390 SetDest(0, dest, op_a + " * " + op_b, 1, 1, instr.alu.abs_d);
391 break;
392 }
393 case OpCode::Id::FMUL32_IMM: {
394 // fmul32i doesn't have abs or neg bits.
395 SetDest(0, dest, GetRegister(instr.gpr8) + " * " + GetImmediate32(instr), 1, 1);
396 break;
397 }
398 case OpCode::Id::FADD_C:
399 case OpCode::Id::FADD_R:
400 case OpCode::Id::FADD_IMM: {
401 SetDest(0, dest, op_a + " + " + op_b, 1, 1, instr.alu.abs_d);
402 break;
403 }
404 case OpCode::Id::MUFU: {
405 switch (instr.sub_op) {
406 case SubOp::Cos:
407 SetDest(0, dest, "cos(" + op_a + ")", 1, 1, instr.alu.abs_d);
408 break;
409 case SubOp::Sin:
410 SetDest(0, dest, "sin(" + op_a + ")", 1, 1, instr.alu.abs_d);
411 break;
412 case SubOp::Ex2:
413 SetDest(0, dest, "exp2(" + op_a + ")", 1, 1, instr.alu.abs_d);
414 break;
415 case SubOp::Lg2:
416 SetDest(0, dest, "log2(" + op_a + ")", 1, 1, instr.alu.abs_d);
417 break;
418 case SubOp::Rcp:
419 SetDest(0, dest, "1.0 / " + op_a, 1, 1, instr.alu.abs_d);
420 break;
421 case SubOp::Rsq:
422 SetDest(0, dest, "inversesqrt(" + op_a + ")", 1, 1, instr.alu.abs_d);
423 break;
424 case SubOp::Min:
425 SetDest(0, dest, "min(" + op_a + "," + op_b + ")", 1, 1, instr.alu.abs_d);
426 break;
427 default:
428 NGLOG_CRITICAL(HW_GPU, "Unhandled MUFU sub op: {0:x}",
429 static_cast<unsigned>(instr.sub_op.Value()));
430 UNREACHABLE();
431 }
432 break;
433 }
434 case OpCode::Id::RRO: {
435 NGLOG_DEBUG(HW_GPU, "Skipping RRO instruction");
436 break;
437 }
438 default: {
439 NGLOG_CRITICAL(HW_GPU, "Unhandled arithmetic instruction: {}", opcode->GetName());
440 UNREACHABLE();
441 }
442 }
443 break;
444 }
445 case OpCode::Type::Ffma: {
446 std::string dest = GetRegister(instr.gpr0);
447 std::string op_a = GetRegister(instr.gpr8);
448 std::string op_b = instr.ffma.negate_b ? "-" : "";
449 std::string op_c = instr.ffma.negate_c ? "-" : "";
450
451 switch (opcode->GetId()) {
452 case OpCode::Id::FFMA_CR: {
453 op_b += GetUniform(instr.uniform);
454 op_c += GetRegister(instr.gpr39);
455 break;
456 }
457 case OpCode::Id::FFMA_RR: {
458 op_b += GetRegister(instr.gpr20);
459 op_c += GetRegister(instr.gpr39);
460 break;
461 }
462 case OpCode::Id::FFMA_RC: {
463 op_b += GetRegister(instr.gpr39);
464 op_c += GetUniform(instr.uniform);
465 break;
466 }
467 case OpCode::Id::FFMA_IMM: {
468 op_b += GetImmediate19(instr);
469 op_c += GetRegister(instr.gpr39);
470 break;
471 }
472 default: {
473 NGLOG_CRITICAL(HW_GPU, "Unhandled FFMA instruction: {}", opcode->GetName());
474 UNREACHABLE();
475 }
476 }
477
478 SetDest(0, dest, op_a + " * " + op_b + " + " + op_c, 1, 1);
479 break;
480 }
481 case OpCode::Type::Memory: {
482 std::string gpr0 = GetRegister(instr.gpr0);
483 const Attribute::Index attribute = instr.attribute.fmt20.index;
484
485 switch (opcode->GetId()) {
486 case OpCode::Id::LD_A: {
487 ASSERT_MSG(instr.attribute.fmt20.size == 0, "untested");
488 SetDest(instr.attribute.fmt20.element, gpr0, GetInputAttribute(attribute), 1, 4);
489 break;
490 }
491 case OpCode::Id::ST_A: {
492 ASSERT_MSG(instr.attribute.fmt20.size == 0, "untested");
493 SetDest(instr.attribute.fmt20.element, GetOutputAttribute(attribute), gpr0, 4, 1);
494 break;
495 }
496 case OpCode::Id::TEXS: {
497 ASSERT_MSG(instr.attribute.fmt20.size == 4, "untested");
498 const std::string op_a = GetRegister(instr.gpr8);
499 const std::string op_b = GetRegister(instr.gpr20);
500 const std::string sampler = GetSampler(instr.sampler);
501 const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");";
502 // Add an extra scope and declare the texture coords inside to prevent overwriting
503 // them in case they are used as outputs of the texs instruction.
504 shader.AddLine("{");
505 ++shader.scope;
506 shader.AddLine(coord);
507 const std::string texture = "texture(" + sampler + ", coords)";
508 for (unsigned elem = 0; elem < instr.attribute.fmt20.size; ++elem) {
509 SetDest(elem, GetRegister(instr.gpr0, elem), texture, 1, 4);
510 }
511 --shader.scope;
512 shader.AddLine("}");
513 break;
514 }
515 default: {
516 NGLOG_CRITICAL(HW_GPU, "Unhandled memory instruction: {}", opcode->GetName());
517 UNREACHABLE();
518 }
519 }
520 break;
521 }
522 case OpCode::Type::FloatPredicate: {
523 std::string op_a = instr.fsetp.neg_a ? "-" : "";
524 op_a += GetRegister(instr.gpr8);
525
526 if (instr.fsetp.abs_a) {
527 op_a = "abs(" + op_a + ')';
528 }
529
530 std::string op_b{};
531
532 if (instr.is_b_imm) {
533 if (instr.fsetp.neg_b) {
534 // Only the immediate version of fsetp has a neg_b bit.
535 op_b += '-';
536 }
537 op_b += '(' + GetImmediate19(instr) + ')';
538 } else {
539 if (instr.is_b_gpr) {
540 op_b += GetRegister(instr.gpr20);
541 } else {
542 op_b += GetUniform(instr.uniform);
543 }
544 }
545
546 if (instr.fsetp.abs_b) {
547 op_b = "abs(" + op_b + ')';
548 }
549
550 using Tegra::Shader::Pred;
551 ASSERT_MSG(instr.fsetp.pred0 == static_cast<u64>(Pred::UnusedIndex) &&
552 instr.fsetp.pred39 == static_cast<u64>(Pred::UnusedIndex),
553 "Compound predicates are not implemented");
554
555 // We can't use the constant predicate as destination.
556 ASSERT(instr.fsetp.pred3 != static_cast<u64>(Pred::UnusedIndex));
557
558 using Tegra::Shader::PredCondition;
559 switch (instr.fsetp.cond) {
560 case PredCondition::LessThan:
561 SetPredicate(instr.fsetp.pred3, '(' + op_a + ") < (" + op_b + ')');
562 break;
563 case PredCondition::Equal:
564 SetPredicate(instr.fsetp.pred3, '(' + op_a + ") == (" + op_b + ')');
565 break;
566 default:
567 NGLOG_CRITICAL(HW_GPU, "Unhandled predicate condition: {} (a: {}, b: {})",
568 static_cast<unsigned>(instr.fsetp.cond.Value()), op_a, op_b);
569 UNREACHABLE();
570 }
571 break;
572 }
573 default: {
574 switch (opcode->GetId()) {
575 case OpCode::Id::EXIT: {
576 ASSERT_MSG(instr.pred.pred_index == static_cast<u64>(Pred::UnusedIndex),
577 "Predicated exits not implemented");
578 shader.AddLine("return true;");
579 offset = PROGRAM_END - 1;
580 break;
581 }
582 case OpCode::Id::KIL: {
583 shader.AddLine("discard;");
584 break;
585 }
586 case OpCode::Id::IPA: {
587 const auto& attribute = instr.attribute.fmt28;
588 std::string dest = GetRegister(instr.gpr0);
589 SetDest(attribute.element, dest, GetInputAttribute(attribute.index), 1, 4);
590 break;
591 }
592 default: {
593 NGLOG_CRITICAL(HW_GPU, "Unhandled instruction: {}", opcode->GetName());
594 UNREACHABLE();
595 }
596 }
597
598 break;
599 }
600 }
601
602 // Close the predicate condition scope.
603 if (instr.pred.pred_index != static_cast<u64>(Pred::UnusedIndex)) {
604 --shader.scope;
605 shader.AddLine('}');
606 }
607
608 return offset + 1;
609 }
610
611 /**
612 * Compiles a range of instructions from Tegra to GLSL.
613 * @param begin the offset of the starting instruction.
614 * @param end the offset where the compilation should stop (exclusive).
615 * @return the offset of the next instruction to compile. PROGRAM_END if the program
616 * terminates.
617 */
618 u32 CompileRange(u32 begin, u32 end) {
619 u32 program_counter;
620 for (program_counter = begin; program_counter < (begin > end ? PROGRAM_END : end);) {
621 program_counter = CompileInstr(program_counter);
622 }
623 return program_counter;
624 }
625
626 void Generate() {
627 // Add declarations for all subroutines
628 for (const auto& subroutine : subroutines) {
629 shader.AddLine("bool " + subroutine.GetName() + "();");
630 }
631 shader.AddNewLine();
632
633 // Add the main entry point
634 shader.AddLine("bool exec_shader() {");
635 ++shader.scope;
636 CallSubroutine(GetSubroutine(main_offset, PROGRAM_END));
637 --shader.scope;
638 shader.AddLine("}\n");
639
640 // Add definitions for all subroutines
641 for (const auto& subroutine : subroutines) {
642 std::set<u32> labels = subroutine.labels;
643
644 shader.AddLine("bool " + subroutine.GetName() + "() {");
645 ++shader.scope;
646
647 if (labels.empty()) {
648 if (CompileRange(subroutine.begin, subroutine.end) != PROGRAM_END) {
649 shader.AddLine("return false;");
650 }
651 } else {
652 labels.insert(subroutine.begin);
653 shader.AddLine("uint jmp_to = " + std::to_string(subroutine.begin) + "u;");
654 shader.AddLine("while (true) {");
655 ++shader.scope;
656
657 shader.AddLine("switch (jmp_to) {");
658
659 for (auto label : labels) {
660 shader.AddLine("case " + std::to_string(label) + "u: {");
661 ++shader.scope;
662
663 auto next_it = labels.lower_bound(label + 1);
664 u32 next_label = next_it == labels.end() ? subroutine.end : *next_it;
665
666 u32 compile_end = CompileRange(label, next_label);
667 if (compile_end > next_label && compile_end != PROGRAM_END) {
668 // This happens only when there is a label inside a IF/LOOP block
669 shader.AddLine("{ jmp_to = " + std::to_string(compile_end) + "u; break; }");
670 labels.emplace(compile_end);
671 }
672
673 --shader.scope;
674 shader.AddLine('}');
675 }
676
677 shader.AddLine("default: return false;");
678 shader.AddLine('}');
679
680 --shader.scope;
681 shader.AddLine('}');
682
683 shader.AddLine("return false;");
684 }
685
686 --shader.scope;
687 shader.AddLine("}\n");
688
689 DEBUG_ASSERT(shader.scope == 0);
690 }
691
692 GenerateDeclarations();
693 }
694
695 /// Returns a list of constant buffer declarations
696 std::vector<ConstBufferEntry> GetConstBuffersDeclarations() const {
697 std::vector<ConstBufferEntry> result;
698 std::copy_if(declr_const_buffers.begin(), declr_const_buffers.end(),
699 std::back_inserter(result), [](const auto& entry) { return entry.IsUsed(); });
700 return result;
701 }
702
703 /// Add declarations for registers
704 void GenerateDeclarations() {
705 for (const auto& reg : declr_register) {
706 declarations.AddLine("float " + reg + " = 0.0;");
707 }
708 declarations.AddNewLine();
709
710 for (const auto& index : declr_input_attribute) {
711 // TODO(bunnei): Use proper number of elements for these
712 declarations.AddLine("layout(location = " +
713 std::to_string(static_cast<u32>(index) -
714 static_cast<u32>(Attribute::Index::Attribute_0)) +
715 ") in vec4 " + GetInputAttribute(index) + ";");
716 }
717 declarations.AddNewLine();
718
719 for (const auto& index : declr_output_attribute) {
720 // TODO(bunnei): Use proper number of elements for these
721 declarations.AddLine("layout(location = " +
722 std::to_string(static_cast<u32>(index) -
723 static_cast<u32>(Attribute::Index::Attribute_0)) +
724 ") out vec4 " + GetOutputAttribute(index) + ";");
725 }
726 declarations.AddNewLine();
727
728 unsigned const_buffer_layout = 0;
729 for (const auto& entry : GetConstBuffersDeclarations()) {
730 declarations.AddLine("layout(std430) buffer " + entry.GetName());
731 declarations.AddLine('{');
732 declarations.AddLine(" float c" + std::to_string(entry.GetIndex()) + "[];");
733 declarations.AddLine("};");
734 declarations.AddNewLine();
735 ++const_buffer_layout;
736 }
737
738 declarations.AddNewLine();
739 for (const auto& pred : declr_predicates) {
740 declarations.AddLine("bool " + pred + " = false;");
741 }
742 declarations.AddNewLine();
743 }
744
745private:
746 const std::set<Subroutine>& subroutines;
747 const ProgramCode& program_code;
748 const u32 main_offset;
749 Maxwell3D::Regs::ShaderStage stage;
750
751 ShaderWriter shader;
752 ShaderWriter declarations;
753
754 // Declarations
755 std::set<std::string> declr_register;
756 std::set<std::string> declr_predicates;
757 std::set<Attribute::Index> declr_input_attribute;
758 std::set<Attribute::Index> declr_output_attribute;
759 std::array<ConstBufferEntry, Maxwell3D::Regs::MaxConstBuffers> declr_const_buffers;
760}; // namespace Decompiler
761
762std::string GetCommonDeclarations() {
763 return "bool exec_shader();";
764}
765
766boost::optional<ProgramResult> DecompileProgram(const ProgramCode& program_code, u32 main_offset,
767 Maxwell3D::Regs::ShaderStage stage) {
768 try {
769 auto subroutines = ControlFlowAnalyzer(program_code, main_offset).GetSubroutines();
770 GLSLGenerator generator(subroutines, program_code, main_offset, stage);
771 return ProgramResult{generator.GetShaderCode(), generator.GetEntries()};
772 } catch (const DecompileFail& exception) {
773 NGLOG_ERROR(HW_GPU, "Shader decompilation failed: {}", exception.what());
774 }
775 return boost::none;
54} 776}
55 777
56} // namespace Decompiler 778} // namespace Decompiler
57} // namespace Shader 779} // namespace GLShader
58} // namespace Maxwell3D
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.h b/src/video_core/renderer_opengl/gl_shader_decompiler.h
index 02ebfcbe8..382c76b7a 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.h
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.h
@@ -2,26 +2,25 @@
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#pragma once
6
5#include <array> 7#include <array>
6#include <functional> 8#include <functional>
7#include <string> 9#include <string>
10#include <boost/optional.hpp>
8#include "common/common_types.h" 11#include "common/common_types.h"
12#include "video_core/engines/maxwell_3d.h"
13#include "video_core/renderer_opengl/gl_shader_gen.h"
9 14
10namespace Maxwell3D { 15namespace GLShader {
11namespace Shader {
12namespace Decompiler { 16namespace Decompiler {
13 17
14constexpr size_t MAX_PROGRAM_CODE_LENGTH{0x100000}; 18using Tegra::Engines::Maxwell3D;
15constexpr size_t MAX_SWIZZLE_DATA_LENGTH{0x100000}; 19
20std::string GetCommonDeclarations();
16 21
17std::string DecompileProgram(const std::array<u32, MAX_PROGRAM_CODE_LENGTH>& program_code, 22boost::optional<ProgramResult> DecompileProgram(const ProgramCode& program_code, u32 main_offset,
18 const std::array<u32, MAX_SWIZZLE_DATA_LENGTH>& swizzle_data, 23 Maxwell3D::Regs::ShaderStage stage);
19 u32 main_offset,
20 const std::function<std::string(u32)>& inputreg_getter,
21 const std::function<std::string(u32)>& outputreg_getter,
22 bool sanitize_mul, const std::string& emit_cb = "",
23 const std::string& setemit_cb = "");
24 24
25} // namespace Decompiler 25} // namespace Decompiler
26} // namespace Shader 26} // namespace GLShader
27} // namespace Maxwell3D
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp
index 8f3c98800..254f6e2c3 100644
--- a/src/video_core/renderer_opengl/gl_shader_gen.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp
@@ -3,18 +3,74 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/assert.h" 5#include "common/assert.h"
6#include "video_core/engines/maxwell_3d.h"
7#include "video_core/renderer_opengl/gl_shader_decompiler.h"
6#include "video_core/renderer_opengl/gl_shader_gen.h" 8#include "video_core/renderer_opengl/gl_shader_gen.h"
7 9
8namespace GLShader { 10namespace GLShader {
9 11
10std::string GenerateVertexShader(const MaxwellVSConfig& config) { 12using Tegra::Engines::Maxwell3D;
11 UNREACHABLE(); 13
12 return {}; 14static constexpr u32 PROGRAM_OFFSET{10};
15
16ProgramResult GenerateVertexShader(const ShaderSetup& setup, const MaxwellVSConfig& config) {
17 std::string out = "#version 430 core\n";
18 out += "#extension GL_ARB_separate_shader_objects : enable\n\n";
19 out += Decompiler::GetCommonDeclarations();
20
21 ProgramResult program = Decompiler::DecompileProgram(setup.program_code, PROGRAM_OFFSET,
22 Maxwell3D::Regs::ShaderStage::Vertex)
23 .get_value_or({});
24 out += R"(
25
26out gl_PerVertex {
27 vec4 gl_Position;
28};
29
30out vec4 position;
31
32layout (std140) uniform vs_config {
33 vec4 viewport_flip;
34};
35
36void main() {
37 exec_shader();
38
39 // Viewport can be flipped, which is unsupported by glViewport
40 position.xy *= viewport_flip.xy;
41 gl_Position = position;
42}
43)";
44 out += program.first;
45 return {out, program.second};
46}
47
48ProgramResult GenerateFragmentShader(const ShaderSetup& setup, const MaxwellFSConfig& config) {
49 std::string out = "#version 430 core\n";
50 out += "#extension GL_ARB_separate_shader_objects : enable\n\n";
51 out += Decompiler::GetCommonDeclarations();
52
53 ProgramResult program = Decompiler::DecompileProgram(setup.program_code, PROGRAM_OFFSET,
54 Maxwell3D::Regs::ShaderStage::Fragment)
55 .get_value_or({});
56 out += R"(
57
58in vec4 position;
59out vec4 color;
60
61layout (std140) uniform fs_config {
62 vec4 viewport_flip;
63};
64
65uniform sampler2D tex[32];
66
67void main() {
68 exec_shader();
13} 69}
14 70
15std::string GenerateFragmentShader(const MaxwellFSConfig& config) { 71)";
16 UNREACHABLE(); 72 out += program.first;
17 return {}; 73 return {out, program.second};
18} 74}
19 75
20} // namespace GLShader 76} // namespace GLShader
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.h b/src/video_core/renderer_opengl/gl_shader_gen.h
index 5101e7d30..458032b5c 100644
--- a/src/video_core/renderer_opengl/gl_shader_gen.h
+++ b/src/video_core/renderer_opengl/gl_shader_gen.h
@@ -4,46 +4,113 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <cstring> 7#include <array>
8#include <string> 8#include <string>
9#include <type_traits> 9#include <type_traits>
10#include <utility>
11#include <vector>
12#include "common/common_types.h"
10#include "common/hash.h" 13#include "common/hash.h"
11 14
12namespace GLShader { 15namespace GLShader {
13 16
14enum Attributes { 17constexpr size_t MAX_PROGRAM_CODE_LENGTH{0x1000};
15 ATTRIBUTE_POSITION, 18
16 ATTRIBUTE_COLOR, 19using ProgramCode = std::array<u64, MAX_PROGRAM_CODE_LENGTH>;
17 ATTRIBUTE_TEXCOORD0, 20
18 ATTRIBUTE_TEXCOORD1, 21class ConstBufferEntry {
19 ATTRIBUTE_TEXCOORD2, 22 using Maxwell = Tegra::Engines::Maxwell3D::Regs;
20 ATTRIBUTE_TEXCOORD0_W, 23
21 ATTRIBUTE_NORMQUAT, 24public:
22 ATTRIBUTE_VIEW, 25 void MarkAsUsed(unsigned index, unsigned offset, Maxwell::ShaderStage stage) {
26 is_used = true;
27 this->index = index;
28 this->stage = stage;
29 max_offset = std::max(max_offset, offset);
30 }
31
32 bool IsUsed() const {
33 return is_used;
34 }
35
36 unsigned GetIndex() const {
37 return index;
38 }
39
40 unsigned GetSize() const {
41 return max_offset + 1;
42 }
43
44 std::string GetName() const {
45 return BufferBaseNames[static_cast<size_t>(stage)] + std::to_string(index);
46 }
47
48private:
49 static constexpr std::array<const char*, Maxwell::MaxShaderStage> BufferBaseNames = {
50 "buffer_vs_c", "buffer_tessc_c", "buffer_tesse_c", "buffer_gs_c", "buffer_fs_c",
51 };
52
53 bool is_used{};
54 unsigned index{};
55 unsigned max_offset{};
56 Maxwell::ShaderStage stage;
23}; 57};
24 58
25struct MaxwellShaderConfigCommon { 59struct ShaderEntries {
26 explicit MaxwellShaderConfigCommon(){}; 60 std::vector<ConstBufferEntry> const_buffer_entries;
27}; 61};
28 62
29struct MaxwellVSConfig : MaxwellShaderConfigCommon { 63using ProgramResult = std::pair<std::string, ShaderEntries>;
30 explicit MaxwellVSConfig() : MaxwellShaderConfigCommon() {}
31 64
32 bool operator==(const MaxwellVSConfig& o) const { 65struct ShaderSetup {
33 return std::memcmp(this, &o, sizeof(MaxwellVSConfig)) == 0; 66 ShaderSetup(ProgramCode&& program_code) : program_code(std::move(program_code)) {}
34 }; 67
68 ProgramCode program_code;
69 bool program_code_hash_dirty = true;
70
71 u64 GetProgramCodeHash() {
72 if (program_code_hash_dirty) {
73 program_code_hash = Common::ComputeHash64(&program_code, sizeof(program_code));
74 program_code_hash_dirty = false;
75 }
76 return program_code_hash;
77 }
78
79private:
80 u64 program_code_hash{};
35}; 81};
36 82
37struct MaxwellFSConfig : MaxwellShaderConfigCommon { 83struct MaxwellShaderConfigCommon {
38 explicit MaxwellFSConfig() : MaxwellShaderConfigCommon() {} 84 void Init(ShaderSetup& setup) {
85 program_hash = setup.GetProgramCodeHash();
86 }
39 87
40 bool operator==(const MaxwellFSConfig& o) const { 88 u64 program_hash;
41 return std::memcmp(this, &o, sizeof(MaxwellFSConfig)) == 0;
42 };
43}; 89};
44 90
45std::string GenerateVertexShader(const MaxwellVSConfig& config); 91struct MaxwellVSConfig : Common::HashableStruct<MaxwellShaderConfigCommon> {
46std::string GenerateFragmentShader(const MaxwellFSConfig& config); 92 explicit MaxwellVSConfig(ShaderSetup& setup) {
93 state.Init(setup);
94 }
95};
96
97struct MaxwellFSConfig : Common::HashableStruct<MaxwellShaderConfigCommon> {
98 explicit MaxwellFSConfig(ShaderSetup& setup) {
99 state.Init(setup);
100 }
101};
102
103/**
104 * Generates the GLSL vertex shader program source code for the given VS program
105 * @returns String of the shader source code
106 */
107ProgramResult GenerateVertexShader(const ShaderSetup& setup, const MaxwellVSConfig& config);
108
109/**
110 * Generates the GLSL fragment shader program source code for the given FS program
111 * @returns String of the shader source code
112 */
113ProgramResult GenerateFragmentShader(const ShaderSetup& setup, const MaxwellFSConfig& config);
47 114
48} // namespace GLShader 115} // namespace GLShader
49 116
@@ -52,14 +119,14 @@ namespace std {
52template <> 119template <>
53struct hash<GLShader::MaxwellVSConfig> { 120struct hash<GLShader::MaxwellVSConfig> {
54 size_t operator()(const GLShader::MaxwellVSConfig& k) const { 121 size_t operator()(const GLShader::MaxwellVSConfig& k) const {
55 return Common::ComputeHash64(&k, sizeof(GLShader::MaxwellVSConfig)); 122 return k.Hash();
56 } 123 }
57}; 124};
58 125
59template <> 126template <>
60struct hash<GLShader::MaxwellFSConfig> { 127struct hash<GLShader::MaxwellFSConfig> {
61 size_t operator()(const GLShader::MaxwellFSConfig& k) const { 128 size_t operator()(const GLShader::MaxwellFSConfig& k) const {
62 return Common::ComputeHash64(&k, sizeof(GLShader::MaxwellFSConfig)); 129 return k.Hash();
63 } 130 }
64}; 131};
65 132
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.cpp b/src/video_core/renderer_opengl/gl_shader_manager.cpp
new file mode 100644
index 000000000..17b3925a0
--- /dev/null
+++ b/src/video_core/renderer_opengl/gl_shader_manager.cpp
@@ -0,0 +1,64 @@
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 "core/core.h"
6#include "core/hle/kernel/process.h"
7#include "video_core/engines/maxwell_3d.h"
8#include "video_core/renderer_opengl/gl_shader_manager.h"
9
10namespace GLShader {
11
12namespace Impl {
13void SetShaderUniformBlockBinding(GLuint shader, const char* name,
14 Maxwell3D::Regs::ShaderStage binding, size_t expected_size) {
15 GLuint ub_index = glGetUniformBlockIndex(shader, name);
16 if (ub_index != GL_INVALID_INDEX) {
17 GLint ub_size = 0;
18 glGetActiveUniformBlockiv(shader, ub_index, GL_UNIFORM_BLOCK_DATA_SIZE, &ub_size);
19 ASSERT_MSG(ub_size == expected_size,
20 "Uniform block size did not match! Got %d, expected %zu",
21 static_cast<int>(ub_size), expected_size);
22 glUniformBlockBinding(shader, ub_index, static_cast<GLuint>(binding));
23 }
24}
25
26void SetShaderUniformBlockBindings(GLuint shader) {
27 SetShaderUniformBlockBinding(shader, "vs_config", Maxwell3D::Regs::ShaderStage::Vertex,
28 sizeof(MaxwellUniformData));
29 SetShaderUniformBlockBinding(shader, "gs_config", Maxwell3D::Regs::ShaderStage::Geometry,
30 sizeof(MaxwellUniformData));
31 SetShaderUniformBlockBinding(shader, "fs_config", Maxwell3D::Regs::ShaderStage::Fragment,
32 sizeof(MaxwellUniformData));
33}
34
35void SetShaderSamplerBindings(GLuint shader) {
36 OpenGLState cur_state = OpenGLState::GetCurState();
37 GLuint old_program = std::exchange(cur_state.draw.shader_program, shader);
38 cur_state.Apply();
39
40 // Set the texture samplers to correspond to different texture units
41 for (u32 texture = 0; texture < NumTextureSamplers; ++texture) {
42 // Set the texture samplers to correspond to different texture units
43 std::string uniform_name = "tex[" + std::to_string(texture) + "]";
44 GLint uniform_tex = glGetUniformLocation(shader, uniform_name.c_str());
45 if (uniform_tex != -1) {
46 glUniform1i(uniform_tex, TextureUnits::MaxwellTexture(texture).id);
47 }
48 }
49
50 cur_state.draw.shader_program = old_program;
51 cur_state.Apply();
52}
53
54} // namespace Impl
55
56void MaxwellUniformData::SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage) {
57 const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
58
59 // TODO(bunnei): Support more than one viewport
60 viewport_flip[0] = regs.viewport_transform[0].scale_x < 0.0 ? -1.0 : 1.0;
61 viewport_flip[1] = regs.viewport_transform[0].scale_y < 0.0 ? -1.0 : 1.0;
62}
63
64} // namespace GLShader
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h
new file mode 100644
index 000000000..e963b4b7e
--- /dev/null
+++ b/src/video_core/renderer_opengl/gl_shader_manager.h
@@ -0,0 +1,175 @@
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 <tuple>
8#include <unordered_map>
9#include <boost/functional/hash.hpp>
10#include <glad/glad.h>
11#include "video_core/renderer_opengl/gl_resource_manager.h"
12#include "video_core/renderer_opengl/gl_shader_gen.h"
13#include "video_core/renderer_opengl/maxwell_to_gl.h"
14
15namespace GLShader {
16
17/// Number of OpenGL texture samplers that can be used in the fragment shader
18static constexpr size_t NumTextureSamplers = 32;
19
20using Tegra::Engines::Maxwell3D;
21
22namespace Impl {
23void SetShaderUniformBlockBindings(GLuint shader);
24void SetShaderSamplerBindings(GLuint shader);
25} // namespace Impl
26
27/// Uniform structure for the Uniform Buffer Object, all vectors must be 16-byte aligned
28// NOTE: Always keep a vec4 at the end. The GL spec is not clear wether the alignment at
29// the end of a uniform block is included in UNIFORM_BLOCK_DATA_SIZE or not.
30// Not following that rule will cause problems on some AMD drivers.
31struct MaxwellUniformData {
32 void SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage);
33 alignas(16) GLvec4 viewport_flip;
34};
35static_assert(sizeof(MaxwellUniformData) == 16, "MaxwellUniformData structure size is incorrect");
36static_assert(sizeof(MaxwellUniformData) < 16384,
37 "MaxwellUniformData structure must be less than 16kb as per the OpenGL spec");
38
39class OGLShaderStage {
40public:
41 OGLShaderStage() = default;
42
43 void Create(const ProgramResult& program_result, GLenum type) {
44 OGLShader shader;
45 shader.Create(program_result.first.c_str(), type);
46 program.Create(true, shader.handle);
47 Impl::SetShaderUniformBlockBindings(program.handle);
48 Impl::SetShaderSamplerBindings(program.handle);
49 entries = program_result.second;
50 }
51 GLuint GetHandle() const {
52 return program.handle;
53 }
54
55 ShaderEntries GetEntries() const {
56 return entries;
57 }
58
59private:
60 OGLProgram program;
61 ShaderEntries entries;
62};
63
64// TODO(wwylele): beautify this doc
65// This is a shader cache designed for translating PICA shader to GLSL shader.
66// The double cache is needed because diffent KeyConfigType, which includes a hash of the code
67// region (including its leftover unused code) can generate the same GLSL code.
68template <typename KeyConfigType,
69 ProgramResult (*CodeGenerator)(const ShaderSetup&, const KeyConfigType&),
70 GLenum ShaderType>
71class ShaderCache {
72public:
73 ShaderCache() = default;
74
75 using Result = std::pair<GLuint, ShaderEntries>;
76
77 Result Get(const KeyConfigType& key, const ShaderSetup& setup) {
78 auto map_it = shader_map.find(key);
79 if (map_it == shader_map.end()) {
80 ProgramResult program = CodeGenerator(setup, key);
81
82 auto [iter, new_shader] = shader_cache.emplace(program.first, OGLShaderStage{});
83 OGLShaderStage& cached_shader = iter->second;
84 if (new_shader) {
85 cached_shader.Create(program, ShaderType);
86 }
87 shader_map[key] = &cached_shader;
88 return {cached_shader.GetHandle(), program.second};
89 } else {
90 return {map_it->second->GetHandle(), map_it->second->GetEntries()};
91 }
92 }
93
94private:
95 std::unordered_map<KeyConfigType, OGLShaderStage*> shader_map;
96 std::unordered_map<std::string, OGLShaderStage> shader_cache;
97};
98
99using VertexShaders = ShaderCache<MaxwellVSConfig, &GenerateVertexShader, GL_VERTEX_SHADER>;
100
101using FragmentShaders = ShaderCache<MaxwellFSConfig, &GenerateFragmentShader, GL_FRAGMENT_SHADER>;
102
103class ProgramManager {
104public:
105 ProgramManager() {
106 pipeline.Create();
107 }
108
109 ShaderEntries UseProgrammableVertexShader(const MaxwellVSConfig& config,
110 const ShaderSetup setup) {
111 ShaderEntries result;
112 std::tie(current.vs, result) = vertex_shaders.Get(config, setup);
113 return result;
114 }
115
116 ShaderEntries UseProgrammableFragmentShader(const MaxwellFSConfig& config,
117 const ShaderSetup setup) {
118 ShaderEntries result;
119 std::tie(current.fs, result) = fragment_shaders.Get(config, setup);
120 return result;
121 }
122
123 GLuint GetCurrentProgramStage(Maxwell3D::Regs::ShaderStage stage) {
124 switch (stage) {
125 case Maxwell3D::Regs::ShaderStage::Vertex:
126 return current.vs;
127 case Maxwell3D::Regs::ShaderStage::Fragment:
128 return current.fs;
129 }
130
131 UNREACHABLE();
132 }
133
134 void UseTrivialGeometryShader() {
135 current.gs = 0;
136 }
137
138 void ApplyTo(OpenGLState& state) {
139 // Workaround for AMD bug
140 glUseProgramStages(pipeline.handle,
141 GL_VERTEX_SHADER_BIT | GL_GEOMETRY_SHADER_BIT | GL_FRAGMENT_SHADER_BIT,
142 0);
143
144 glUseProgramStages(pipeline.handle, GL_VERTEX_SHADER_BIT, current.vs);
145 glUseProgramStages(pipeline.handle, GL_GEOMETRY_SHADER_BIT, current.gs);
146 glUseProgramStages(pipeline.handle, GL_FRAGMENT_SHADER_BIT, current.fs);
147 state.draw.shader_program = 0;
148 state.draw.program_pipeline = pipeline.handle;
149 }
150
151private:
152 struct ShaderTuple {
153 GLuint vs = 0, gs = 0, fs = 0;
154 bool operator==(const ShaderTuple& rhs) const {
155 return std::tie(vs, gs, fs) == std::tie(rhs.vs, rhs.gs, rhs.fs);
156 }
157 struct Hash {
158 std::size_t operator()(const ShaderTuple& tuple) const {
159 std::size_t hash = 0;
160 boost::hash_combine(hash, tuple.vs);
161 boost::hash_combine(hash, tuple.gs);
162 boost::hash_combine(hash, tuple.fs);
163 return hash;
164 }
165 };
166 };
167 ShaderTuple current;
168 VertexShaders vertex_shaders;
169 FragmentShaders fragment_shaders;
170
171 std::unordered_map<ShaderTuple, OGLProgram, ShaderTuple::Hash> program_cache;
172 OGLPipeline pipeline;
173};
174
175} // namespace GLShader
diff --git a/src/video_core/renderer_opengl/gl_shader_util.cpp b/src/video_core/renderer_opengl/gl_shader_util.cpp
index a6c6204d5..8568fface 100644
--- a/src/video_core/renderer_opengl/gl_shader_util.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_util.cpp
@@ -10,156 +10,41 @@
10 10
11namespace GLShader { 11namespace GLShader {
12 12
13GLuint LoadProgram(const char* vertex_shader, const char* geometry_shader, 13GLuint LoadShader(const char* source, GLenum type) {
14 const char* fragment_shader, const std::vector<const char*>& feedback_vars, 14 const char* debug_type;
15 bool separable_program) { 15 switch (type) {
16 // Create the shaders 16 case GL_VERTEX_SHADER:
17 GLuint vertex_shader_id = vertex_shader ? glCreateShader(GL_VERTEX_SHADER) : 0; 17 debug_type = "vertex";
18 GLuint geometry_shader_id = geometry_shader ? glCreateShader(GL_GEOMETRY_SHADER) : 0; 18 break;
19 GLuint fragment_shader_id = fragment_shader ? glCreateShader(GL_FRAGMENT_SHADER) : 0; 19 case GL_GEOMETRY_SHADER:
20 debug_type = "geometry";
21 break;
22 case GL_FRAGMENT_SHADER:
23 debug_type = "fragment";
24 break;
25 default:
26 UNREACHABLE();
27 }
28 GLuint shader_id = glCreateShader(type);
29 glShaderSource(shader_id, 1, &source, nullptr);
30 NGLOG_DEBUG(Render_OpenGL, "Compiling {} shader...", debug_type);
31 glCompileShader(shader_id);
20 32
21 GLint result = GL_FALSE; 33 GLint result = GL_FALSE;
22 int info_log_length; 34 GLint info_log_length;
23 35 glGetShaderiv(shader_id, GL_COMPILE_STATUS, &result);
24 if (vertex_shader) { 36 glGetShaderiv(shader_id, GL_INFO_LOG_LENGTH, &info_log_length);
25 // Compile Vertex Shader
26 LOG_DEBUG(Render_OpenGL, "Compiling vertex shader...");
27
28 glShaderSource(vertex_shader_id, 1, &vertex_shader, nullptr);
29 glCompileShader(vertex_shader_id);
30
31 // Check Vertex Shader
32 glGetShaderiv(vertex_shader_id, GL_COMPILE_STATUS, &result);
33 glGetShaderiv(vertex_shader_id, GL_INFO_LOG_LENGTH, &info_log_length);
34
35 if (info_log_length > 1) {
36 std::vector<char> vertex_shader_error(info_log_length);
37 glGetShaderInfoLog(vertex_shader_id, info_log_length, nullptr, &vertex_shader_error[0]);
38 if (result == GL_TRUE) {
39 LOG_DEBUG(Render_OpenGL, "%s", &vertex_shader_error[0]);
40 } else {
41 LOG_CRITICAL(Render_OpenGL, "Error compiling vertex shader:\n%s",
42 &vertex_shader_error[0]);
43 }
44 }
45 }
46
47 if (geometry_shader) {
48 // Compile Geometry Shader
49 LOG_DEBUG(Render_OpenGL, "Compiling geometry shader...");
50
51 glShaderSource(geometry_shader_id, 1, &geometry_shader, nullptr);
52 glCompileShader(geometry_shader_id);
53
54 // Check Geometry Shader
55 glGetShaderiv(geometry_shader_id, GL_COMPILE_STATUS, &result);
56 glGetShaderiv(geometry_shader_id, GL_INFO_LOG_LENGTH, &info_log_length);
57
58 if (info_log_length > 1) {
59 std::vector<char> geometry_shader_error(info_log_length);
60 glGetShaderInfoLog(geometry_shader_id, info_log_length, nullptr,
61 &geometry_shader_error[0]);
62 if (result == GL_TRUE) {
63 LOG_DEBUG(Render_OpenGL, "%s", &geometry_shader_error[0]);
64 } else {
65 LOG_CRITICAL(Render_OpenGL, "Error compiling geometry shader:\n%s",
66 &geometry_shader_error[0]);
67 }
68 }
69 }
70
71 if (fragment_shader) {
72 // Compile Fragment Shader
73 LOG_DEBUG(Render_OpenGL, "Compiling fragment shader...");
74
75 glShaderSource(fragment_shader_id, 1, &fragment_shader, nullptr);
76 glCompileShader(fragment_shader_id);
77
78 // Check Fragment Shader
79 glGetShaderiv(fragment_shader_id, GL_COMPILE_STATUS, &result);
80 glGetShaderiv(fragment_shader_id, GL_INFO_LOG_LENGTH, &info_log_length);
81
82 if (info_log_length > 1) {
83 std::vector<char> fragment_shader_error(info_log_length);
84 glGetShaderInfoLog(fragment_shader_id, info_log_length, nullptr,
85 &fragment_shader_error[0]);
86 if (result == GL_TRUE) {
87 LOG_DEBUG(Render_OpenGL, "%s", &fragment_shader_error[0]);
88 } else {
89 LOG_CRITICAL(Render_OpenGL, "Error compiling fragment shader:\n%s",
90 &fragment_shader_error[0]);
91 }
92 }
93 }
94
95 // Link the program
96 LOG_DEBUG(Render_OpenGL, "Linking program...");
97
98 GLuint program_id = glCreateProgram();
99 if (vertex_shader) {
100 glAttachShader(program_id, vertex_shader_id);
101 }
102 if (geometry_shader) {
103 glAttachShader(program_id, geometry_shader_id);
104 }
105 if (fragment_shader) {
106 glAttachShader(program_id, fragment_shader_id);
107 }
108
109 if (!feedback_vars.empty()) {
110 auto varyings = feedback_vars;
111 glTransformFeedbackVaryings(program_id, static_cast<GLsizei>(feedback_vars.size()),
112 &varyings[0], GL_INTERLEAVED_ATTRIBS);
113 }
114
115 if (separable_program) {
116 glProgramParameteri(program_id, GL_PROGRAM_SEPARABLE, GL_TRUE);
117 }
118
119 glLinkProgram(program_id);
120
121 // Check the program
122 glGetProgramiv(program_id, GL_LINK_STATUS, &result);
123 glGetProgramiv(program_id, GL_INFO_LOG_LENGTH, &info_log_length);
124 37
125 if (info_log_length > 1) { 38 if (info_log_length > 1) {
126 std::vector<char> program_error(info_log_length); 39 std::string shader_error(info_log_length, ' ');
127 glGetProgramInfoLog(program_id, info_log_length, nullptr, &program_error[0]); 40 glGetShaderInfoLog(shader_id, info_log_length, nullptr, &shader_error[0]);
128 if (result == GL_TRUE) { 41 if (result == GL_TRUE) {
129 LOG_DEBUG(Render_OpenGL, "%s", &program_error[0]); 42 NGLOG_DEBUG(Render_OpenGL, "{}", shader_error);
130 } else { 43 } else {
131 LOG_CRITICAL(Render_OpenGL, "Error linking shader:\n%s", &program_error[0]); 44 NGLOG_ERROR(Render_OpenGL, "Error compiling {} shader:\n{}", debug_type, shader_error);
132 } 45 }
133 } 46 }
134 47 return shader_id;
135 // If the program linking failed at least one of the shaders was probably bad
136 if (result == GL_FALSE) {
137 if (vertex_shader) {
138 LOG_CRITICAL(Render_OpenGL, "Vertex shader:\n%s", vertex_shader);
139 }
140 if (geometry_shader) {
141 LOG_CRITICAL(Render_OpenGL, "Geometry shader:\n%s", geometry_shader);
142 }
143 if (fragment_shader) {
144 LOG_CRITICAL(Render_OpenGL, "Fragment shader:\n%s", fragment_shader);
145 }
146 }
147 ASSERT_MSG(result == GL_TRUE, "Shader not linked");
148
149 if (vertex_shader) {
150 glDetachShader(program_id, vertex_shader_id);
151 glDeleteShader(vertex_shader_id);
152 }
153 if (geometry_shader) {
154 glDetachShader(program_id, geometry_shader_id);
155 glDeleteShader(geometry_shader_id);
156 }
157 if (fragment_shader) {
158 glDetachShader(program_id, fragment_shader_id);
159 glDeleteShader(fragment_shader_id);
160 }
161
162 return program_id;
163} 48}
164 49
165} // namespace GLShader 50} // namespace GLShader
diff --git a/src/video_core/renderer_opengl/gl_shader_util.h b/src/video_core/renderer_opengl/gl_shader_util.h
index fc7b5e080..a1fa9e814 100644
--- a/src/video_core/renderer_opengl/gl_shader_util.h
+++ b/src/video_core/renderer_opengl/gl_shader_util.h
@@ -6,18 +6,60 @@
6 6
7#include <vector> 7#include <vector>
8#include <glad/glad.h> 8#include <glad/glad.h>
9#include "common/assert.h"
10#include "common/logging/log.h"
9 11
10namespace GLShader { 12namespace GLShader {
11 13
12/** 14/**
15 * Utility function to create and compile an OpenGL GLSL shader
16 * @param source String of the GLSL shader program
17 * @param type Type of the shader (GL_VERTEX_SHADER, GL_GEOMETRY_SHADER or GL_FRAGMENT_SHADER)
18 */
19GLuint LoadShader(const char* source, GLenum type);
20
21/**
13 * Utility function to create and compile an OpenGL GLSL shader program (vertex + fragment shader) 22 * Utility function to create and compile an OpenGL GLSL shader program (vertex + fragment shader)
14 * @param vertex_shader String of the GLSL vertex shader program 23 * @param separable_program whether to create a separable program
15 * @param geometry_shader String of the GLSL geometry shader program 24 * @param shaders ID of shaders to attach to the program
16 * @param fragment_shader String of the GLSL fragment shader program 25 * @returns Handle of the newly created OpenGL program object
17 * @returns Handle of the newly created OpenGL shader object
18 */ 26 */
19GLuint LoadProgram(const char* vertex_shader, const char* geometry_shader, 27template <typename... T>
20 const char* fragment_shader, const std::vector<const char*>& feedback_vars = {}, 28GLuint LoadProgram(bool separable_program, T... shaders) {
21 bool separable_program = false); 29 // Link the program
30 NGLOG_DEBUG(Render_OpenGL, "Linking program...");
31
32 GLuint program_id = glCreateProgram();
33
34 ((shaders == 0 ? (void)0 : glAttachShader(program_id, shaders)), ...);
35
36 if (separable_program) {
37 glProgramParameteri(program_id, GL_PROGRAM_SEPARABLE, GL_TRUE);
38 }
39
40 glLinkProgram(program_id);
41
42 // Check the program
43 GLint result = GL_FALSE;
44 GLint info_log_length;
45 glGetProgramiv(program_id, GL_LINK_STATUS, &result);
46 glGetProgramiv(program_id, GL_INFO_LOG_LENGTH, &info_log_length);
47
48 if (info_log_length > 1) {
49 std::string program_error(info_log_length, ' ');
50 glGetProgramInfoLog(program_id, info_log_length, nullptr, &program_error[0]);
51 if (result == GL_TRUE) {
52 NGLOG_DEBUG(Render_OpenGL, "{}", program_error);
53 } else {
54 NGLOG_ERROR(Render_OpenGL, "Error linking shader:\n{}", program_error);
55 }
56 }
57
58 ASSERT_MSG(result == GL_TRUE, "Shader not linked");
59
60 ((shaders == 0 ? (void)0 : glDetachShader(program_id, shaders)), ...);
61
62 return program_id;
63}
22 64
23} // namespace GLShader 65} // namespace GLShader
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index 6da3a7781..f91dfe36a 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -2,8 +2,8 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <iterator>
5#include <glad/glad.h> 6#include <glad/glad.h>
6#include "common/common_funcs.h"
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8#include "video_core/renderer_opengl/gl_state.h" 8#include "video_core/renderer_opengl/gl_state.h"
9 9
@@ -192,7 +192,7 @@ void OpenGLState::Apply() const {
192 } 192 }
193 193
194 // Textures 194 // Textures
195 for (unsigned i = 0; i < ARRAY_SIZE(texture_units); ++i) { 195 for (size_t i = 0; i < std::size(texture_units); ++i) {
196 if (texture_units[i].texture_2d != cur_state.texture_units[i].texture_2d) { 196 if (texture_units[i].texture_2d != cur_state.texture_units[i].texture_2d) {
197 glActiveTexture(TextureUnits::MaxwellTexture(i).Enum()); 197 glActiveTexture(TextureUnits::MaxwellTexture(i).Enum());
198 glBindTexture(GL_TEXTURE_2D, texture_units[i].texture_2d); 198 glBindTexture(GL_TEXTURE_2D, texture_units[i].texture_2d);
@@ -202,6 +202,20 @@ void OpenGLState::Apply() const {
202 } 202 }
203 } 203 }
204 204
205 // Constbuffers
206 for (u32 stage = 0; stage < draw.const_buffers.size(); ++stage) {
207 for (u32 buffer_id = 0; buffer_id < draw.const_buffers[stage].size(); ++buffer_id) {
208 auto& current = cur_state.draw.const_buffers[stage][buffer_id];
209 auto& new_state = draw.const_buffers[stage][buffer_id];
210 if (current.enabled != new_state.enabled || current.bindpoint != new_state.bindpoint ||
211 current.ssbo != new_state.ssbo) {
212 if (new_state.enabled) {
213 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, new_state.bindpoint, new_state.ssbo);
214 }
215 }
216 }
217 }
218
205 // Lighting LUTs 219 // Lighting LUTs
206 if (lighting_lut.texture_buffer != cur_state.lighting_lut.texture_buffer) { 220 if (lighting_lut.texture_buffer != cur_state.lighting_lut.texture_buffer) {
207 glActiveTexture(TextureUnits::LightingLUT.Enum()); 221 glActiveTexture(TextureUnits::LightingLUT.Enum());
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h
index b18af14bb..75c08e645 100644
--- a/src/video_core/renderer_opengl/gl_state.h
+++ b/src/video_core/renderer_opengl/gl_state.h
@@ -123,6 +123,12 @@ public:
123 GLuint uniform_buffer; // GL_UNIFORM_BUFFER_BINDING 123 GLuint uniform_buffer; // GL_UNIFORM_BUFFER_BINDING
124 GLuint shader_program; // GL_CURRENT_PROGRAM 124 GLuint shader_program; // GL_CURRENT_PROGRAM
125 GLuint program_pipeline; // GL_PROGRAM_PIPELINE_BINDING 125 GLuint program_pipeline; // GL_PROGRAM_PIPELINE_BINDING
126 struct ConstBufferConfig {
127 bool enabled = false;
128 GLuint bindpoint;
129 GLuint ssbo;
130 };
131 std::array<std::array<ConstBufferConfig, 16>, 5> const_buffers{};
126 } draw; 132 } draw;
127 133
128 struct { 134 struct {
diff --git a/src/video_core/renderer_opengl/gl_stream_buffer.h b/src/video_core/renderer_opengl/gl_stream_buffer.h
index 4bc2f52e0..e78dc5784 100644
--- a/src/video_core/renderer_opengl/gl_stream_buffer.h
+++ b/src/video_core/renderer_opengl/gl_stream_buffer.h
@@ -2,6 +2,8 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once
6
5#include <memory> 7#include <memory>
6#include <glad/glad.h> 8#include <glad/glad.h>
7#include "common/common_types.h" 9#include "common/common_types.h"
diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h
index 48ee80125..a49265b38 100644
--- a/src/video_core/renderer_opengl/maxwell_to_gl.h
+++ b/src/video_core/renderer_opengl/maxwell_to_gl.h
@@ -10,6 +10,14 @@
10#include "common/logging/log.h" 10#include "common/logging/log.h"
11#include "video_core/engines/maxwell_3d.h" 11#include "video_core/engines/maxwell_3d.h"
12 12
13using GLvec2 = std::array<GLfloat, 2>;
14using GLvec3 = std::array<GLfloat, 3>;
15using GLvec4 = std::array<GLfloat, 4>;
16
17using GLuvec2 = std::array<GLuint, 2>;
18using GLuvec3 = std::array<GLuint, 3>;
19using GLuvec4 = std::array<GLuint, 4>;
20
13namespace MaxwellToGL { 21namespace MaxwellToGL {
14 22
15using Maxwell = Tegra::Engines::Maxwell3D::Regs; 23using Maxwell = Tegra::Engines::Maxwell3D::Regs;
@@ -23,7 +31,7 @@ inline GLenum VertexType(Maxwell::VertexAttribute attrib) {
23 return GL_UNSIGNED_BYTE; 31 return GL_UNSIGNED_BYTE;
24 } 32 }
25 33
26 LOG_CRITICAL(Render_OpenGL, "Unimplemented vertex size=%s", attrib.SizeString().c_str()); 34 NGLOG_CRITICAL(Render_OpenGL, "Unimplemented vertex size={}", attrib.SizeString());
27 UNREACHABLE(); 35 UNREACHABLE();
28 return {}; 36 return {};
29 } 37 }
@@ -32,17 +40,33 @@ inline GLenum VertexType(Maxwell::VertexAttribute attrib) {
32 return GL_FLOAT; 40 return GL_FLOAT;
33 } 41 }
34 42
35 LOG_CRITICAL(Render_OpenGL, "Unimplemented vertex type=%s", attrib.TypeString().c_str()); 43 NGLOG_CRITICAL(Render_OpenGL, "Unimplemented vertex type={}", attrib.TypeString());
44 UNREACHABLE();
45 return {};
46}
47
48inline GLenum IndexFormat(Maxwell::IndexFormat index_format) {
49 switch (index_format) {
50 case Maxwell::IndexFormat::UnsignedByte:
51 return GL_UNSIGNED_BYTE;
52 case Maxwell::IndexFormat::UnsignedShort:
53 return GL_UNSIGNED_SHORT;
54 case Maxwell::IndexFormat::UnsignedInt:
55 return GL_UNSIGNED_INT;
56 }
57 NGLOG_CRITICAL(Render_OpenGL, "Unimplemented index_format={}", static_cast<u32>(index_format));
36 UNREACHABLE(); 58 UNREACHABLE();
37 return {}; 59 return {};
38} 60}
39 61
40inline GLenum PrimitiveTopology(Maxwell::PrimitiveTopology topology) { 62inline GLenum PrimitiveTopology(Maxwell::PrimitiveTopology topology) {
41 switch (topology) { 63 switch (topology) {
64 case Maxwell::PrimitiveTopology::Triangles:
65 return GL_TRIANGLES;
42 case Maxwell::PrimitiveTopology::TriangleStrip: 66 case Maxwell::PrimitiveTopology::TriangleStrip:
43 return GL_TRIANGLE_STRIP; 67 return GL_TRIANGLE_STRIP;
44 } 68 }
45 LOG_CRITICAL(Render_OpenGL, "Unimplemented primitive topology=%d", topology); 69 NGLOG_CRITICAL(Render_OpenGL, "Unimplemented topology={}", static_cast<u32>(topology));
46 UNREACHABLE(); 70 UNREACHABLE();
47 return {}; 71 return {};
48} 72}
@@ -54,18 +78,90 @@ inline GLenum TextureFilterMode(Tegra::Texture::TextureFilter filter_mode) {
54 case Tegra::Texture::TextureFilter::Nearest: 78 case Tegra::Texture::TextureFilter::Nearest:
55 return GL_NEAREST; 79 return GL_NEAREST;
56 } 80 }
57 LOG_CRITICAL(Render_OpenGL, "Unimplemented texture filter mode=%u", 81 NGLOG_CRITICAL(Render_OpenGL, "Unimplemented texture filter mode={}",
58 static_cast<u32>(filter_mode)); 82 static_cast<u32>(filter_mode));
59 UNREACHABLE(); 83 UNREACHABLE();
60 return {}; 84 return {};
61} 85}
62 86
63inline GLenum WrapMode(Tegra::Texture::WrapMode wrap_mode) { 87inline GLenum WrapMode(Tegra::Texture::WrapMode wrap_mode) {
64 switch (wrap_mode) { 88 switch (wrap_mode) {
89 case Tegra::Texture::WrapMode::Wrap:
90 return GL_REPEAT;
65 case Tegra::Texture::WrapMode::ClampToEdge: 91 case Tegra::Texture::WrapMode::ClampToEdge:
66 return GL_CLAMP_TO_EDGE; 92 return GL_CLAMP_TO_EDGE;
93 case Tegra::Texture::WrapMode::ClampOGL:
94 // TODO(Subv): GL_CLAMP was removed as of OpenGL 3.1, to implement GL_CLAMP, we can use
95 // GL_CLAMP_TO_BORDER to get the border color of the texture, and then sample the edge to
96 // manually mix them. However the shader part of this is not yet implemented.
97 return GL_CLAMP_TO_BORDER;
98 }
99 NGLOG_CRITICAL(Render_OpenGL, "Unimplemented texture wrap mode={}",
100 static_cast<u32>(wrap_mode));
101 UNREACHABLE();
102 return {};
103}
104
105inline GLenum BlendEquation(Maxwell::Blend::Equation equation) {
106 switch (equation) {
107 case Maxwell::Blend::Equation::Add:
108 return GL_FUNC_ADD;
109 case Maxwell::Blend::Equation::Subtract:
110 return GL_FUNC_SUBTRACT;
111 case Maxwell::Blend::Equation::ReverseSubtract:
112 return GL_FUNC_REVERSE_SUBTRACT;
113 case Maxwell::Blend::Equation::Min:
114 return GL_MIN;
115 case Maxwell::Blend::Equation::Max:
116 return GL_MAX;
117 }
118 NGLOG_CRITICAL(Render_OpenGL, "Unimplemented blend equation={}", static_cast<u32>(equation));
119 UNREACHABLE();
120 return {};
121}
122
123inline GLenum BlendFunc(Maxwell::Blend::Factor factor) {
124 switch (factor) {
125 case Maxwell::Blend::Factor::Zero:
126 return GL_ZERO;
127 case Maxwell::Blend::Factor::One:
128 return GL_ONE;
129 case Maxwell::Blend::Factor::SourceColor:
130 return GL_SRC_COLOR;
131 case Maxwell::Blend::Factor::OneMinusSourceColor:
132 return GL_ONE_MINUS_SRC_COLOR;
133 case Maxwell::Blend::Factor::SourceAlpha:
134 return GL_SRC_ALPHA;
135 case Maxwell::Blend::Factor::OneMinusSourceAlpha:
136 return GL_ONE_MINUS_SRC_ALPHA;
137 case Maxwell::Blend::Factor::DestAlpha:
138 return GL_DST_ALPHA;
139 case Maxwell::Blend::Factor::OneMinusDestAlpha:
140 return GL_ONE_MINUS_DST_ALPHA;
141 case Maxwell::Blend::Factor::DestColor:
142 return GL_DST_COLOR;
143 case Maxwell::Blend::Factor::OneMinusDestColor:
144 return GL_ONE_MINUS_DST_COLOR;
145 case Maxwell::Blend::Factor::SourceAlphaSaturate:
146 return GL_SRC_ALPHA_SATURATE;
147 case Maxwell::Blend::Factor::Source1Color:
148 return GL_SRC1_COLOR;
149 case Maxwell::Blend::Factor::OneMinusSource1Color:
150 return GL_ONE_MINUS_SRC1_COLOR;
151 case Maxwell::Blend::Factor::Source1Alpha:
152 return GL_SRC1_ALPHA;
153 case Maxwell::Blend::Factor::OneMinusSource1Alpha:
154 return GL_ONE_MINUS_SRC1_ALPHA;
155 case Maxwell::Blend::Factor::ConstantColor:
156 return GL_CONSTANT_COLOR;
157 case Maxwell::Blend::Factor::OneMinusConstantColor:
158 return GL_ONE_MINUS_CONSTANT_COLOR;
159 case Maxwell::Blend::Factor::ConstantAlpha:
160 return GL_CONSTANT_ALPHA;
161 case Maxwell::Blend::Factor::OneMinusConstantAlpha:
162 return GL_ONE_MINUS_CONSTANT_ALPHA;
67 } 163 }
68 LOG_CRITICAL(Render_OpenGL, "Unimplemented texture wrap mode=%u", static_cast<u32>(wrap_mode)); 164 NGLOG_CRITICAL(Render_OpenGL, "Unimplemented blend factor={}", static_cast<u32>(factor));
69 UNREACHABLE(); 165 UNREACHABLE();
70 return {}; 166 return {};
71} 167}
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 78b50b227..ab0acb20a 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -9,13 +9,10 @@
9#include <memory> 9#include <memory>
10#include <glad/glad.h> 10#include <glad/glad.h>
11#include "common/assert.h" 11#include "common/assert.h"
12#include "common/bit_field.h"
13#include "common/logging/log.h" 12#include "common/logging/log.h"
14#include "core/core.h" 13#include "core/core.h"
15#include "core/core_timing.h" 14#include "core/core_timing.h"
16#include "core/frontend/emu_window.h" 15#include "core/frontend/emu_window.h"
17#include "core/hw/hw.h"
18#include "core/hw/lcd.h"
19#include "core/memory.h" 16#include "core/memory.h"
20#include "core/settings.h" 17#include "core/settings.h"
21#include "core/tracer/recorder.h" 18#include "core/tracer/recorder.h"
@@ -57,7 +54,7 @@ uniform sampler2D color_texture;
57void main() { 54void main() {
58 // Swap RGBA -> ABGR so we don't have to do this on the CPU. This needs to change if we have to 55 // Swap RGBA -> ABGR so we don't have to do this on the CPU. This needs to change if we have to
59 // support more framebuffer pixel formats. 56 // support more framebuffer pixel formats.
60 color = texture(color_texture, frag_tex_coord).abgr; 57 color = texture(color_texture, frag_tex_coord);
61} 58}
62)"; 59)";
63 60
@@ -210,7 +207,7 @@ void RendererOpenGL::InitOpenGLObjects() {
210 0.0f); 207 0.0f);
211 208
212 // Link shaders and get variable locations 209 // Link shaders and get variable locations
213 shader.Create(vertex_shader, nullptr, fragment_shader); 210 shader.CreateFromSource(vertex_shader, nullptr, fragment_shader);
214 state.draw.shader_program = shader.handle; 211 state.draw.shader_program = shader.handle;
215 state.Apply(); 212 state.Apply();
216 uniform_modelview_matrix = glGetUniformLocation(shader.handle, "modelview_matrix"); 213 uniform_modelview_matrix = glGetUniformLocation(shader.handle, "modelview_matrix");
@@ -311,10 +308,10 @@ void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x,
311 } 308 }
312 309
313 std::array<ScreenRectVertex, 4> vertices = {{ 310 std::array<ScreenRectVertex, 4> vertices = {{
314 ScreenRectVertex(x, y, texcoords.top, right), 311 ScreenRectVertex(x, y, texcoords.top, left),
315 ScreenRectVertex(x + w, y, texcoords.bottom, right), 312 ScreenRectVertex(x + w, y, texcoords.bottom, left),
316 ScreenRectVertex(x, y + h, texcoords.top, left), 313 ScreenRectVertex(x, y + h, texcoords.top, right),
317 ScreenRectVertex(x + w, y + h, texcoords.bottom, left), 314 ScreenRectVertex(x + w, y + h, texcoords.bottom, right),
318 }}; 315 }};
319 316
320 state.texture_units[0].texture_2d = screen_info.display_texture; 317 state.texture_units[0].texture_2d = screen_info.display_texture;
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h
index c52f40037..2cc6d9a00 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.h
+++ b/src/video_core/renderer_opengl/renderer_opengl.h
@@ -72,7 +72,7 @@ private:
72 // OpenGL object IDs 72 // OpenGL object IDs
73 OGLVertexArray vertex_array; 73 OGLVertexArray vertex_array;
74 OGLBuffer vertex_buffer; 74 OGLBuffer vertex_buffer;
75 OGLShader shader; 75 OGLProgram shader;
76 76
77 /// Display information for Switch screen 77 /// Display information for Switch screen
78 ScreenInfo screen_info; 78 ScreenInfo screen_info;
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp
index 2e87281eb..4df687786 100644
--- a/src/video_core/textures/decoders.cpp
+++ b/src/video_core/textures/decoders.cpp
@@ -48,31 +48,39 @@ u32 BytesPerPixel(TextureFormat format) {
48 case TextureFormat::DXT1: 48 case TextureFormat::DXT1:
49 // In this case a 'pixel' actually refers to a 4x4 tile. 49 // In this case a 'pixel' actually refers to a 4x4 tile.
50 return 8; 50 return 8;
51 case TextureFormat::DXT23:
52 case TextureFormat::DXT45:
53 // In this case a 'pixel' actually refers to a 4x4 tile.
54 return 16;
51 case TextureFormat::A8R8G8B8: 55 case TextureFormat::A8R8G8B8:
52 return 4; 56 return 4;
57 case TextureFormat::B5G6R5:
58 return 2;
53 default: 59 default:
54 UNIMPLEMENTED_MSG("Format not implemented"); 60 UNIMPLEMENTED_MSG("Format not implemented");
55 break; 61 break;
56 } 62 }
57} 63}
58 64
59std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height) { 65std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height,
66 u32 block_height) {
60 u8* data = Memory::GetPointer(address); 67 u8* data = Memory::GetPointer(address);
61 u32 bytes_per_pixel = BytesPerPixel(format); 68 u32 bytes_per_pixel = BytesPerPixel(format);
62 69
63 static constexpr u32 DefaultBlockHeight = 16;
64
65 std::vector<u8> unswizzled_data(width * height * bytes_per_pixel); 70 std::vector<u8> unswizzled_data(width * height * bytes_per_pixel);
66 71
67 switch (format) { 72 switch (format) {
68 case TextureFormat::DXT1: 73 case TextureFormat::DXT1:
69 // In the DXT1 format, each 4x4 tile is swizzled instead of just individual pixel values. 74 case TextureFormat::DXT23:
75 case TextureFormat::DXT45:
76 // In the DXT formats, each 4x4 tile is swizzled instead of just individual pixel values.
70 CopySwizzledData(width / 4, height / 4, bytes_per_pixel, bytes_per_pixel, data, 77 CopySwizzledData(width / 4, height / 4, bytes_per_pixel, bytes_per_pixel, data,
71 unswizzled_data.data(), true, DefaultBlockHeight); 78 unswizzled_data.data(), true, block_height);
72 break; 79 break;
73 case TextureFormat::A8R8G8B8: 80 case TextureFormat::A8R8G8B8:
81 case TextureFormat::B5G6R5:
74 CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data, 82 CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data,
75 unswizzled_data.data(), true, DefaultBlockHeight); 83 unswizzled_data.data(), true, block_height);
76 break; 84 break;
77 default: 85 default:
78 UNIMPLEMENTED_MSG("Format not implemented"); 86 UNIMPLEMENTED_MSG("Format not implemented");
@@ -89,7 +97,10 @@ std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat
89 // TODO(Subv): Implement. 97 // TODO(Subv): Implement.
90 switch (format) { 98 switch (format) {
91 case TextureFormat::DXT1: 99 case TextureFormat::DXT1:
100 case TextureFormat::DXT23:
101 case TextureFormat::DXT45:
92 case TextureFormat::A8R8G8B8: 102 case TextureFormat::A8R8G8B8:
103 case TextureFormat::B5G6R5:
93 // TODO(Subv): For the time being just forward the same data without any decoding. 104 // TODO(Subv): For the time being just forward the same data without any decoding.
94 rgba_data = texture_data; 105 rgba_data = texture_data;
95 break; 106 break;
diff --git a/src/video_core/textures/decoders.h b/src/video_core/textures/decoders.h
index 0c21694ff..a700911cf 100644
--- a/src/video_core/textures/decoders.h
+++ b/src/video_core/textures/decoders.h
@@ -14,7 +14,8 @@ namespace Texture {
14/** 14/**
15 * Unswizzles a swizzled texture without changing its format. 15 * Unswizzles a swizzled texture without changing its format.
16 */ 16 */
17std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height); 17std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height,
18 u32 block_height = TICEntry::DefaultBlockHeight);
18 19
19/** 20/**
20 * Decodes an unswizzled texture into a A8R8G8B8 texture. 21 * Decodes an unswizzled texture into a A8R8G8B8 texture.
diff --git a/src/video_core/textures/texture.h b/src/video_core/textures/texture.h
index c12ed6e1d..86e45aa88 100644
--- a/src/video_core/textures/texture.h
+++ b/src/video_core/textures/texture.h
@@ -4,6 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include "common/assert.h"
7#include "common/bit_field.h" 8#include "common/bit_field.h"
8#include "common/common_funcs.h" 9#include "common/common_funcs.h"
9#include "common/common_types.h" 10#include "common/common_types.h"
@@ -13,8 +14,11 @@ namespace Tegra {
13namespace Texture { 14namespace Texture {
14 15
15enum class TextureFormat : u32 { 16enum class TextureFormat : u32 {
16 A8R8G8B8 = 8, 17 A8R8G8B8 = 0x8,
18 B5G6R5 = 0x15,
17 DXT1 = 0x24, 19 DXT1 = 0x24,
20 DXT23 = 0x25,
21 DXT45 = 0x26,
18}; 22};
19 23
20enum class TextureType : u32 { 24enum class TextureType : u32 {
@@ -55,6 +59,8 @@ union TextureHandle {
55static_assert(sizeof(TextureHandle) == 4, "TextureHandle has wrong size"); 59static_assert(sizeof(TextureHandle) == 4, "TextureHandle has wrong size");
56 60
57struct TICEntry { 61struct TICEntry {
62 static constexpr u32 DefaultBlockHeight = 16;
63
58 union { 64 union {
59 u32 raw; 65 u32 raw;
60 BitField<0, 7, TextureFormat> format; 66 BitField<0, 7, TextureFormat> format;
@@ -68,7 +74,12 @@ struct TICEntry {
68 BitField<0, 16, u32> address_high; 74 BitField<0, 16, u32> address_high;
69 BitField<21, 3, TICHeaderVersion> header_version; 75 BitField<21, 3, TICHeaderVersion> header_version;
70 }; 76 };
71 INSERT_PADDING_BYTES(4); 77 union {
78 BitField<3, 3, u32> block_height;
79
80 // High 16 bits of the pitch value
81 BitField<0, 16, u32> pitch_high;
82 };
72 union { 83 union {
73 BitField<0, 16, u32> width_minus_1; 84 BitField<0, 16, u32> width_minus_1;
74 BitField<23, 4, TextureType> texture_type; 85 BitField<23, 4, TextureType> texture_type;
@@ -80,6 +91,13 @@ struct TICEntry {
80 return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | address_low); 91 return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | address_low);
81 } 92 }
82 93
94 u32 Pitch() const {
95 ASSERT(header_version == TICHeaderVersion::Pitch ||
96 header_version == TICHeaderVersion::PitchColorKey);
97 // The pitch value is 21 bits, and is 32B aligned.
98 return pitch_high << 5;
99 }
100
83 u32 Width() const { 101 u32 Width() const {
84 return width_minus_1 + 1; 102 return width_minus_1 + 1;
85 } 103 }
@@ -88,6 +106,13 @@ struct TICEntry {
88 return height_minus_1 + 1; 106 return height_minus_1 + 1;
89 } 107 }
90 108
109 u32 BlockHeight() const {
110 ASSERT(header_version == TICHeaderVersion::BlockLinear ||
111 header_version == TICHeaderVersion::BlockLinearColorKey);
112 // The block height is stored in log2 format.
113 return 1 << block_height;
114 }
115
91 bool IsTiled() const { 116 bool IsTiled() const {
92 return header_version == TICHeaderVersion::BlockLinear || 117 return header_version == TICHeaderVersion::BlockLinear ||
93 header_version == TICHeaderVersion::BlockLinearColorKey; 118 header_version == TICHeaderVersion::BlockLinearColorKey;
diff --git a/src/video_core/utils.h b/src/video_core/utils.h
index be0f7e22b..e0a14d48f 100644
--- a/src/video_core/utils.h
+++ b/src/video_core/utils.h
@@ -151,7 +151,7 @@ static inline void MortonCopyPixels128(u32 width, u32 height, u32 bytes_per_pixe
151 const u32 coarse_y = y & ~127; 151 const u32 coarse_y = y & ~127;
152 u32 morton_offset = 152 u32 morton_offset =
153 GetMortonOffset128(x, y, bytes_per_pixel) + coarse_y * width * bytes_per_pixel; 153 GetMortonOffset128(x, y, bytes_per_pixel) + coarse_y * width * bytes_per_pixel;
154 u32 gl_pixel_index = (x + (height - 1 - y) * width) * gl_bytes_per_pixel; 154 u32 gl_pixel_index = (x + y * width) * gl_bytes_per_pixel;
155 155
156 data_ptrs[morton_to_gl] = morton_data + morton_offset; 156 data_ptrs[morton_to_gl] = morton_data + morton_offset;
157 data_ptrs[!morton_to_gl] = &gl_data[gl_pixel_index]; 157 data_ptrs[!morton_to_gl] = &gl_data[gl_pixel_index];
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 34e33170e..20796e92c 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -44,6 +44,15 @@
44Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin); 44Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin);
45#endif 45#endif
46 46
47#ifdef _WIN32
48extern "C" {
49// tells Nvidia and AMD drivers to use the dedicated GPU by default on laptops with switchable
50// graphics
51__declspec(dllexport) unsigned long NvOptimusEnablement = 0x00000001;
52__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
53}
54#endif
55
47/** 56/**
48 * "Callouts" are one-time instructional messages shown to the user. In the config settings, there 57 * "Callouts" are one-time instructional messages shown to the user. In the config settings, there
49 * is a bitfield "callout_flags" options, used to track if a message has already been shown to the 58 * is a bitfield "callout_flags" options, used to track if a message has already been shown to the
@@ -776,9 +785,11 @@ void GMainWindow::closeEvent(QCloseEvent* event) {
776 return; 785 return;
777 } 786 }
778 787
779 UISettings::values.geometry = saveGeometry(); 788 if (ui.action_Fullscreen->isChecked()) {
789 UISettings::values.geometry = saveGeometry();
790 UISettings::values.renderwindow_geometry = render_window->saveGeometry();
791 }
780 UISettings::values.state = saveState(); 792 UISettings::values.state = saveState();
781 UISettings::values.renderwindow_geometry = render_window->saveGeometry();
782#if MICROPROFILE_ENABLED 793#if MICROPROFILE_ENABLED
783 UISettings::values.microprofile_geometry = microProfileDialog->saveGeometry(); 794 UISettings::values.microprofile_geometry = microProfileDialog->saveGeometry();
784 UISettings::values.microprofile_visible = microProfileDialog->isVisible(); 795 UISettings::values.microprofile_visible = microProfileDialog->isVisible();
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp
index 0a4644500..39603e881 100644
--- a/src/yuzu_cmd/yuzu.cpp
+++ b/src/yuzu_cmd/yuzu.cpp
@@ -37,6 +37,15 @@
37#include "yuzu_cmd/config.h" 37#include "yuzu_cmd/config.h"
38#include "yuzu_cmd/emu_window/emu_window_sdl2.h" 38#include "yuzu_cmd/emu_window/emu_window_sdl2.h"
39 39
40#ifdef _WIN32
41extern "C" {
42// tells Nvidia and AMD drivers to use the dedicated GPU by default on laptops with switchable
43// graphics
44__declspec(dllexport) unsigned long NvOptimusEnablement = 0x00000001;
45__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
46}
47#endif
48
40static void PrintHelp(const char* argv0) { 49static void PrintHelp(const char* argv0) {
41 std::cout << "Usage: " << argv0 50 std::cout << "Usage: " << argv0
42 << " [options] <filename>\n" 51 << " [options] <filename>\n"