diff options
Diffstat (limited to 'src')
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) | ||
| 200 | static_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 | |||
| 43 | using namespace std; | ||
| 44 | |||
| 45 | typedef uint8_t uint8; | ||
| 46 | typedef uint32_t uint32; | ||
| 47 | typedef uint64_t uint64; | ||
| 48 | |||
| 49 | namespace Common { | ||
| 50 | |||
| 51 | static uint64 UNALIGNED_LOAD64(const char* p) { | ||
| 52 | uint64 result; | ||
| 53 | memcpy(&result, p, sizeof(result)); | ||
| 54 | return result; | ||
| 55 | } | ||
| 56 | |||
| 57 | static 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 | |||
| 79 | static uint64 Fetch64(const char* p) { | ||
| 80 | return uint64_in_expected_order(UNALIGNED_LOAD64(p)); | ||
| 81 | } | ||
| 82 | |||
| 83 | static 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. | ||
| 88 | static const uint64 k0 = 0xc3a5c85c97cb3127ULL; | ||
| 89 | static const uint64 k1 = 0xb492b66fbe98f273ULL; | ||
| 90 | static 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. | ||
| 94 | static 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 | |||
| 99 | static uint64 ShiftMix(uint64 val) { | ||
| 100 | return val ^ (val >> 47); | ||
| 101 | } | ||
| 102 | |||
| 103 | static uint64 HashLen16(uint64 u, uint64 v) { | ||
| 104 | return Hash128to64(uint128(u, v)); | ||
| 105 | } | ||
| 106 | |||
| 107 | static 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 | |||
| 117 | static 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. | ||
| 144 | static 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. | ||
| 155 | static 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. | ||
| 167 | static 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. | ||
| 173 | static 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 | |||
| 194 | uint64 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 | |||
| 232 | uint64 CityHash64WithSeed(const char* s, size_t len, uint64 seed) { | ||
| 233 | return CityHash64WithSeeds(s, len, k2, seed); | ||
| 234 | } | ||
| 235 | |||
| 236 | uint64 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. | ||
| 242 | static 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 | |||
| 272 | uint128 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 | |||
| 334 | uint128 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 | |||
| 68 | namespace Common { | ||
| 69 | |||
| 70 | typedef std::pair<uint64_t, uint64_t> uint128; | ||
| 71 | |||
| 72 | inline uint64_t Uint128Low64(const uint128& x) { | ||
| 73 | return x.first; | ||
| 74 | } | ||
| 75 | inline uint64_t Uint128High64(const uint128& x) { | ||
| 76 | return x.second; | ||
| 77 | } | ||
| 78 | |||
| 79 | // Hash function for a byte array. | ||
| 80 | uint64_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. | ||
| 84 | uint64_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. | ||
| 88 | uint64_t CityHash64WithSeeds(const char* buf, size_t len, uint64_t seed0, uint64_t seed1); | ||
| 89 | |||
| 90 | // Hash function for a byte array. | ||
| 91 | uint128 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. | ||
| 95 | uint128 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. | ||
| 99 | inline 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> {} | ||
| 16 | template <class T> | ||
| 17 | class CodeBlock : public T, NonCopyable { | ||
| 18 | private: | ||
| 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 | |||
| 24 | protected: | ||
| 25 | u8* region; | ||
| 26 | size_t region_size; | ||
| 27 | |||
| 28 | public: | ||
| 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 | 30 | using u8 = std::uint8_t; ///< 8-bit unsigned byte |
| 31 | #ifndef __func__ | 31 | using u16 = std::uint16_t; ///< 16-bit unsigned short |
| 32 | #define __func__ __FUNCTION__ | 32 | using u32 = std::uint32_t; ///< 32-bit unsigned word |
| 33 | #endif | 33 | using u64 = std::uint64_t; ///< 64-bit unsigned int |
| 34 | #endif | ||
| 35 | 34 | ||
| 36 | typedef std::uint8_t u8; ///< 8-bit unsigned byte | 35 | using s8 = std::int8_t; ///< 8-bit signed byte |
| 37 | typedef std::uint16_t u16; ///< 16-bit unsigned short | 36 | using s16 = std::int16_t; ///< 16-bit signed short |
| 38 | typedef std::uint32_t u32; ///< 32-bit unsigned word | 37 | using s32 = std::int32_t; ///< 32-bit signed word |
| 39 | typedef std::uint64_t u64; ///< 64-bit unsigned int | 38 | using s64 = std::int64_t; ///< 64-bit signed int |
| 40 | 39 | ||
| 41 | typedef std::int8_t s8; ///< 8-bit signed byte | 40 | using f32 = float; ///< 32-bit floating point |
| 42 | typedef std::int16_t s16; ///< 16-bit signed short | 41 | using f64 = double; ///< 64-bit floating point |
| 43 | typedef std::int32_t s32; ///< 32-bit signed word | ||
| 44 | typedef std::int64_t s64; ///< 64-bit signed int | ||
| 45 | |||
| 46 | typedef float f32; ///< 32-bit floating point | ||
| 47 | typedef 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. |
| 51 | typedef u64 VAddr; ///< Represents a pointer in the userspace virtual address space. | 45 | using VAddr = u64; ///< Represents a pointer in the userspace virtual address space. |
| 52 | typedef u64 PAddr; ///< Represents a pointer in the ARM11 physical address space. | 46 | using PAddr = u64; ///< Represents a pointer in the ARM11 physical address space. |
| 53 | 47 | ||
| 54 | using u128 = std::array<std::uint64_t, 2>; | 48 | using u128 = std::array<std::uint64_t, 2>; |
| 55 | static_assert(sizeof(u128) == 16, "u128 must be 128 bits wide"); | 49 | static_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 | |||
| 12 | namespace 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 | ||
| 19 | static 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 | ||
| 24 | static 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 | ||
| 37 | void 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 | ||
| 10 | namespace Common { | 12 | namespace Common { |
| 11 | 13 | ||
| 12 | void 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 | */ |
| 20 | static inline u64 ComputeHash64(const void* data, size_t len) { | 20 | static 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 | */ | ||
| 29 | template <typename T> | ||
| 30 | static 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. | ||
| 37 | template <typename T> | ||
| 38 | struct 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 | ||
| 20 | template <typename T> | ||
| 21 | inline T Clamp(const T val, const T& min, const T& max) { | ||
| 22 | return std::max(min, std::min(max, val)); | ||
| 23 | } | ||
| 24 | |||
| 25 | template <class T> | 20 | template <class T> |
| 26 | struct Rectangle { | 21 | struct 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 | |||
| 33 | namespace Common { | 14 | namespace Common { |
| 34 | 15 | ||
| 35 | int CurrentThreadId(); | 16 | int 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 | ||
| 32 | System::~System() = default; | ||
| 33 | |||
| 29 | System::ResultStatus System::RunLoop(bool tight_loop) { | 34 | System::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 | ||
| 224 | Service::SM::ServiceManager& System::ServiceManager() { | ||
| 225 | return *service_manager; | ||
| 226 | } | ||
| 227 | |||
| 228 | const 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 @@ | |||
| 19 | class EmuWindow; | 19 | class EmuWindow; |
| 20 | class ARM_Interface; | 20 | class ARM_Interface; |
| 21 | 21 | ||
| 22 | namespace Service::SM { | ||
| 23 | class ServiceManager; | ||
| 24 | } | ||
| 25 | |||
| 22 | namespace Core { | 26 | namespace Core { |
| 23 | 27 | ||
| 24 | class System { | 28 | class System { |
| 25 | public: | 29 | public: |
| 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 | ||
| 60 | ResultCode Disk_FileSystem::DeleteFile(const Path& path) const { | 60 | ResultCode 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 | ||
| 66 | ResultCode Disk_FileSystem::RenameFile(const Path& src_path, const Path& dest_path) const { | 70 | ResultCode 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 | ||
| 182 | Disk_Directory::Disk_Directory(const std::string& path) : directory() { | 186 | Disk_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 | ||
| 44 | class Disk_Storage : public StorageBackend { | 44 | class Disk_Storage : public StorageBackend { |
| 45 | public: | 45 | public: |
| 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 | ||
| 61 | class Disk_Directory : public DirectoryBackend { | 61 | class Disk_Directory : public DirectoryBackend { |
| 62 | public: | 62 | public: |
| 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 | ||
| 76 | protected: | 76 | protected: |
| 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 | |||
| 12 | namespace FileSys { | ||
| 13 | |||
| 14 | Loader::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 | |||
| 48 | Loader::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 | |||
| 73 | u32 PartitionFilesystem::GetNumEntries() const { | ||
| 74 | return pfs_header.num_entries; | ||
| 75 | } | ||
| 76 | |||
| 77 | u64 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 | |||
| 84 | u64 PartitionFilesystem::GetEntrySize(int index) const { | ||
| 85 | if (index > GetNumEntries()) | ||
| 86 | return 0; | ||
| 87 | |||
| 88 | return pfs_entries[index].fs_entry.size; | ||
| 89 | } | ||
| 90 | |||
| 91 | std::string PartitionFilesystem::GetEntryName(int index) const { | ||
| 92 | if (index > GetNumEntries()) | ||
| 93 | return ""; | ||
| 94 | |||
| 95 | return pfs_entries[index].name; | ||
| 96 | } | ||
| 97 | |||
| 98 | u64 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 | |||
| 107 | u64 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 | |||
| 116 | void 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 | |||
| 14 | namespace Loader { | ||
| 15 | enum class ResultStatus; | ||
| 16 | } | ||
| 17 | |||
| 18 | namespace 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 | */ | ||
| 24 | class PartitionFilesystem { | ||
| 25 | public: | ||
| 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 | |||
| 38 | private: | ||
| 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 | ||
| 23 | ResultCode RomFS_FileSystem::DeleteFile(const Path& path) const { | 23 | ResultCode 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 | ||
| 37 | s32 ResourceLimit::GetCurrentResourceValue(u32 resource) const { | 37 | s32 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 | ||
| 64 | u32 ResourceLimit::GetMaxResourceValue(u32 resource) const { | 64 | u32 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 | ||
| 19 | enum ResourceTypes { | 19 | enum 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 | ||
| 32 | class ResourceLimit final : public Object { | 32 | class 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 | ||
| 948 | static const FunctionDef* GetSVCInfo(u32 func_num) { | 949 | static 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 | ||
| 381 | u64 VMManager::GetTotalMemoryUsage() { | 381 | u64 VMManager::GetTotalMemoryUsage() { |
| 382 | LOG_WARNING(Kernel, "(STUBBED) called"); | 382 | LOG_WARNING(Kernel, "(STUBBED) called"); |
| 383 | return 0xBE000000; | 383 | return 0xF8000000; |
| 384 | } | 384 | } |
| 385 | 385 | ||
| 386 | u64 VMManager::GetTotalHeapUsage() { | 386 | u64 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 | ||
| 13 | namespace Service { | 13 | namespace Service::Account { |
| 14 | namespace Account { | ||
| 15 | 14 | ||
| 16 | // TODO: RE this structure | 15 | // TODO: RE this structure |
| 17 | struct UserData { | 16 | struct UserData { |
| @@ -38,7 +37,10 @@ class IProfile final : public ServiceFramework<IProfile> { | |||
| 38 | public: | 37 | public: |
| 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 | ||
| 9 | namespace Service { | 9 | namespace Service::Account { |
| 10 | namespace Account { | ||
| 11 | 10 | ||
| 12 | class Module final { | 11 | class Module final { |
| 13 | public: | 12 | public: |
| @@ -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. |
| 32 | void InstallInterfaces(SM::ServiceManager& service_manager); | 31 | void 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 | ||
| 7 | namespace Service { | 7 | namespace Service::Account { |
| 8 | namespace Account { | ||
| 9 | 8 | ||
| 10 | ACC_AA::ACC_AA(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:aa") { | 9 | ACC_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 | ||
| 9 | namespace Service { | 9 | namespace Service::Account { |
| 10 | namespace Account { | ||
| 11 | 10 | ||
| 12 | class ACC_AA final : public Module::Interface { | 11 | class ACC_AA final : public Module::Interface { |
| 13 | public: | 12 | public: |
| 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 | ||
| 7 | namespace Service { | 7 | namespace Service::Account { |
| 8 | namespace Account { | ||
| 9 | 8 | ||
| 10 | ACC_SU::ACC_SU(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:su") { | 9 | ACC_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 | ||
| 7 | namespace Service { | 7 | namespace Service::Account { |
| 8 | namespace Account { | ||
| 9 | 8 | ||
| 10 | ACC_U0::ACC_U0(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:u0") { | 9 | ACC_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 | ||
| 9 | namespace Service { | 9 | namespace Service::Account { |
| 10 | namespace Account { | ||
| 11 | 10 | ||
| 12 | class ACC_U0 final : public Module::Interface { | 11 | class ACC_U0 final : public Module::Interface { |
| 13 | public: | 12 | public: |
| 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 | ||
| 7 | namespace Service { | 7 | namespace Service::Account { |
| 8 | namespace Account { | ||
| 9 | 8 | ||
| 10 | ACC_U1::ACC_U1(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:u1") { | 9 | ACC_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 | ||
| 9 | namespace Service { | 9 | namespace Service::Account { |
| 10 | namespace Account { | ||
| 11 | 10 | ||
| 12 | class ACC_U1 final : public Module::Interface { | 11 | class ACC_U1 final : public Module::Interface { |
| 13 | public: | 12 | public: |
| 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 | ||
| 17 | namespace Service { | 17 | namespace Service::AM { |
| 18 | namespace AM { | ||
| 19 | 18 | ||
| 20 | IWindowController::IWindowController() : ServiceFramework("IWindowController") { | 19 | IWindowController::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 | ||
| 11 | namespace Service { | 11 | namespace Service::AM { |
| 12 | namespace AM { | ||
| 13 | 12 | ||
| 14 | class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> { | 13 | class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> { |
| 15 | public: | 14 | public: |
| @@ -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 | ||
| 11 | namespace Service { | 11 | namespace Service::AM { |
| 12 | namespace AM { | ||
| 13 | 12 | ||
| 14 | class IApplicationProxy final : public ServiceFramework<IApplicationProxy> { | 13 | class IApplicationProxy final : public ServiceFramework<IApplicationProxy> { |
| 15 | public: | 14 | public: |
| @@ -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 | ||
| 9 | namespace Service { | 9 | namespace Service::AOC { |
| 10 | namespace AOC { | ||
| 11 | 10 | ||
| 12 | AOC_U::AOC_U() : ServiceFramework("aoc:u") { | 11 | AOC_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 | ||
| 9 | namespace Service { | 9 | namespace Service::AOC { |
| 10 | namespace AOC { | ||
| 11 | 10 | ||
| 12 | class AOC_U final : public ServiceFramework<AOC_U> { | 11 | class AOC_U final : public ServiceFramework<AOC_U> { |
| 13 | public: | 12 | public: |
| @@ -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. |
| 23 | void InstallInterfaces(SM::ServiceManager& service_manager); | 22 | void 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 | ||
| 10 | namespace Service { | 10 | namespace Service::APM { |
| 11 | namespace APM { | ||
| 12 | 11 | ||
| 13 | void InstallInterfaces(SM::ServiceManager& service_manager) { | 12 | void 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 | ||
| 9 | namespace Service { | 9 | namespace Service::APM { |
| 10 | namespace APM { | ||
| 11 | 10 | ||
| 12 | enum class PerformanceMode : u8 { | 11 | enum 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. |
| 24 | void InstallInterfaces(SM::ServiceManager& service_manager); | 23 | void 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 | ||
| 10 | namespace Service { | 10 | namespace Service::APM { |
| 11 | namespace APM { | ||
| 12 | 11 | ||
| 13 | class ISession final : public ServiceFramework<ISession> { | 12 | class ISession final : public ServiceFramework<ISession> { |
| 14 | public: | 13 | public: |
| @@ -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 | ||
| 9 | namespace Service { | 9 | namespace Service::APM { |
| 10 | namespace APM { | ||
| 11 | 10 | ||
| 12 | class APM final : public ServiceFramework<APM> { | 11 | class APM final : public ServiceFramework<APM> { |
| 13 | public: | 12 | public: |
| @@ -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. |
| 24 | void InstallInterfaces(SM::ServiceManager& service_manager); | 23 | void 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 | ||
| 10 | namespace Service { | 10 | namespace Service::Audio { |
| 11 | namespace Audio { | ||
| 12 | 11 | ||
| 13 | class IAudioIn final : public ServiceFramework<IAudioIn> { | 12 | class IAudioIn final : public ServiceFramework<IAudioIn> { |
| 14 | public: | 13 | public: |
| @@ -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 { | |||
| 10 | class HLERequestContext; | 10 | class HLERequestContext; |
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | namespace Service { | 13 | namespace Service::Audio { |
| 14 | namespace Audio { | ||
| 15 | 14 | ||
| 16 | class AudInU final : public ServiceFramework<AudInU> { | 15 | class AudInU final : public ServiceFramework<AudInU> { |
| 17 | public: | 16 | public: |
| @@ -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 | ||
| 12 | namespace Service { | 12 | namespace Service::Audio { |
| 13 | namespace Audio { | ||
| 14 | 13 | ||
| 15 | void InstallInterfaces(SM::ServiceManager& service_manager) { | 14 | void 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 | ||
| 9 | namespace Service { | 9 | namespace Service::Audio { |
| 10 | namespace Audio { | ||
| 11 | 10 | ||
| 12 | /// Registers all Audio services with the specified service manager. | 11 | /// Registers all Audio services with the specified service manager. |
| 13 | void InstallInterfaces(SM::ServiceManager& service_manager); | 12 | void 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 | ||
| 13 | namespace Service { | 13 | namespace Service::Audio { |
| 14 | namespace Audio { | ||
| 15 | 14 | ||
| 16 | /// Switch sample rate frequency | 15 | /// Switch sample rate frequency |
| 17 | constexpr u32 sample_rate{48000}; | 16 | constexpr 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 { | |||
| 10 | class HLERequestContext; | 10 | class HLERequestContext; |
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | namespace Service { | 13 | namespace Service::Audio { |
| 14 | namespace Audio { | ||
| 15 | 14 | ||
| 16 | class IAudioOut; | 15 | class 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 | ||
| 10 | namespace Service { | 10 | namespace Service::Audio { |
| 11 | namespace Audio { | ||
| 12 | 11 | ||
| 13 | class IFinalOutputRecorder final : public ServiceFramework<IFinalOutputRecorder> { | 12 | class IFinalOutputRecorder final : public ServiceFramework<IFinalOutputRecorder> { |
| 14 | public: | 13 | public: |
| @@ -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 { | |||
| 10 | class HLERequestContext; | 10 | class HLERequestContext; |
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | namespace Service { | 13 | namespace Service::Audio { |
| 14 | namespace Audio { | ||
| 15 | 14 | ||
| 16 | class AudRecU final : public ServiceFramework<AudRecU> { | 15 | class AudRecU final : public ServiceFramework<AudRecU> { |
| 17 | public: | 16 | public: |
| @@ -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 | ||
| 12 | namespace Service { | 12 | namespace Service::Audio { |
| 13 | namespace 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 |
| 16 | constexpr u64 audio_ticks{static_cast<u64>(BASE_CLOCK_RATE / 200)}; | 15 | constexpr 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 { | |||
| 10 | class HLERequestContext; | 10 | class HLERequestContext; |
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | namespace Service { | 13 | namespace Service::Audio { |
| 14 | namespace Audio { | ||
| 15 | 14 | ||
| 16 | class AudRenU final : public ServiceFramework<AudRenU> { | 15 | class AudRenU final : public ServiceFramework<AudRenU> { |
| 17 | public: | 16 | public: |
| @@ -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 | ||
| 10 | namespace Service { | 10 | namespace Service::Audio { |
| 11 | namespace Audio { | ||
| 12 | 11 | ||
| 13 | CodecCtl::CodecCtl() : ServiceFramework("codecctl") { | 12 | CodecCtl::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 { | |||
| 10 | class HLERequestContext; | 10 | class HLERequestContext; |
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | namespace Service { | 13 | namespace Service::Audio { |
| 14 | namespace Audio { | ||
| 15 | 14 | ||
| 16 | class CodecCtl final : public ServiceFramework<CodecCtl> { | 15 | class CodecCtl final : public ServiceFramework<CodecCtl> { |
| 17 | public: | 16 | public: |
| @@ -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 | ||
| 11 | namespace Service { | 11 | namespace Service::Fatal { |
| 12 | namespace Fatal { | ||
| 13 | 12 | ||
| 14 | Module::Interface::Interface(std::shared_ptr<Module> module, const char* name) | 13 | Module::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 | ||
| 9 | namespace Service { | 9 | namespace Service::Fatal { |
| 10 | namespace Fatal { | ||
| 11 | 10 | ||
| 12 | class Module final { | 11 | class Module final { |
| 13 | public: | 12 | public: |
| @@ -25,5 +24,4 @@ public: | |||
| 25 | 24 | ||
| 26 | void InstallInterfaces(SM::ServiceManager& service_manager); | 25 | void 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 | ||
| 7 | namespace Service { | 7 | namespace Service::Fatal { |
| 8 | namespace Fatal { | ||
| 9 | 8 | ||
| 10 | Fatal_P::Fatal_P(std::shared_ptr<Module> module) | 9 | Fatal_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 | ||
| 9 | namespace Service { | 9 | namespace Service::Fatal { |
| 10 | namespace Fatal { | ||
| 11 | 10 | ||
| 12 | class Fatal_P final : public Module::Interface { | 11 | class Fatal_P final : public Module::Interface { |
| 13 | public: | 12 | public: |
| 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 | ||
| 7 | namespace Service { | 7 | namespace Service::Fatal { |
| 8 | namespace Fatal { | ||
| 9 | 8 | ||
| 10 | Fatal_U::Fatal_U(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "fatal:u") { | 9 | Fatal_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 | ||
| 9 | namespace Service { | 9 | namespace Service::Fatal { |
| 10 | namespace Fatal { | ||
| 11 | 10 | ||
| 12 | class Fatal_U final : public Module::Interface { | 11 | class Fatal_U final : public Module::Interface { |
| 13 | public: | 12 | public: |
| 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 | ||
| 13 | namespace Service { | 13 | namespace Service::FileSystem { |
| 14 | namespace 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 | ||
| 17 | namespace Service { | 17 | namespace Service::FileSystem { |
| 18 | namespace FileSystem { | ||
| 19 | 18 | ||
| 20 | class IStorage final : public ServiceFramework<IStorage> { | 19 | class IStorage final : public ServiceFramework<IStorage> { |
| 21 | public: | 20 | public: |
| @@ -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 { | |||
| 11 | class FileSystemBackend; | 11 | class FileSystemBackend; |
| 12 | } | 12 | } |
| 13 | 13 | ||
| 14 | namespace Service { | 14 | namespace Service::FileSystem { |
| 15 | namespace FileSystem { | ||
| 16 | 15 | ||
| 17 | class FSP_SRV final : public ServiceFramework<FSP_SRV> { | 16 | class FSP_SRV final : public ServiceFramework<FSP_SRV> { |
| 18 | public: | 17 | public: |
| @@ -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 | ||
| 11 | namespace Service { | 11 | namespace Service::Friend { |
| 12 | namespace Friend { | ||
| 13 | 12 | ||
| 14 | void Module::Interface::CreateFriendService(Kernel::HLERequestContext& ctx) { | 13 | void 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 | ||
| 9 | namespace Service { | 9 | namespace Service::Friend { |
| 10 | namespace Friend { | ||
| 11 | 10 | ||
| 12 | class Module final { | 11 | class Module final { |
| 13 | public: | 12 | public: |
| @@ -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. |
| 26 | void InstallInterfaces(SM::ServiceManager& service_manager); | 25 | void 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 | ||
| 7 | namespace Service { | 7 | namespace Service::Friend { |
| 8 | namespace Friend { | ||
| 9 | 8 | ||
| 10 | Friend_A::Friend_A(std::shared_ptr<Module> module) | 9 | Friend_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 | ||
| 9 | namespace Service { | 9 | namespace Service::Friend { |
| 10 | namespace Friend { | ||
| 11 | 10 | ||
| 12 | class Friend_A final : public Module::Interface { | 11 | class Friend_A final : public Module::Interface { |
| 13 | public: | 12 | public: |
| 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 | ||
| 7 | namespace Service { | 7 | namespace Service::Friend { |
| 8 | namespace Friend { | ||
| 9 | 8 | ||
| 10 | Friend_U::Friend_U(std::shared_ptr<Module> module) | 9 | Friend_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 | ||
| 9 | namespace Service { | 9 | namespace Service::Friend { |
| 10 | namespace Friend { | ||
| 11 | 10 | ||
| 12 | class Friend_U final : public Module::Interface { | 11 | class Friend_U final : public Module::Interface { |
| 13 | public: | 12 | public: |
| 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 | ||
| 17 | namespace Service { | 17 | namespace Service::HID { |
| 18 | namespace 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 | ||
| 10 | namespace Service { | 10 | namespace Service::HID { |
| 11 | namespace 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. |
| 338 | void InstallInterfaces(SM::ServiceManager& service_manager); | 337 | void 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 | ||
| 12 | namespace Service { | 12 | namespace Service::LM { |
| 13 | namespace LM { | ||
| 14 | 13 | ||
| 15 | class Logger final : public ServiceFramework<Logger> { | 14 | class Logger final : public ServiceFramework<Logger> { |
| 16 | public: | 15 | public: |
| @@ -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 | ||
| 11 | namespace Service { | 11 | namespace Service::LM { |
| 12 | namespace LM { | ||
| 13 | 12 | ||
| 14 | class LM final : public ServiceFramework<LM> { | 13 | class LM final : public ServiceFramework<LM> { |
| 15 | public: | 14 | public: |
| @@ -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. |
| 24 | void InstallInterfaces(SM::ServiceManager& service_manager); | 23 | void 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 | ||
| 10 | namespace Service { | 10 | namespace Service::NFP { |
| 11 | namespace NFP { | ||
| 12 | 11 | ||
| 13 | Module::Interface::Interface(std::shared_ptr<Module> module, const char* name) | 12 | Module::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 | ||
| 9 | namespace Service { | 9 | namespace Service::NFP { |
| 10 | namespace NFP { | ||
| 11 | 10 | ||
| 12 | class Module final { | 11 | class Module final { |
| 13 | public: | 12 | public: |
| @@ -24,5 +23,4 @@ public: | |||
| 24 | 23 | ||
| 25 | void InstallInterfaces(SM::ServiceManager& service_manager); | 24 | void 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 | ||
| 7 | namespace Service { | 7 | namespace Service::NFP { |
| 8 | namespace NFP { | ||
| 9 | 8 | ||
| 10 | NFP_User::NFP_User(std::shared_ptr<Module> module) | 9 | NFP_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 | ||
| 9 | namespace Service { | 9 | namespace Service::NFP { |
| 10 | namespace NFP { | ||
| 11 | 10 | ||
| 12 | class NFP_User final : public Module::Interface { | 11 | class NFP_User final : public Module::Interface { |
| 13 | public: | 12 | public: |
| 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 | ||
| 12 | namespace Service { | 12 | namespace Service::NIFM { |
| 13 | namespace NIFM { | ||
| 14 | 13 | ||
| 15 | class IScanRequest final : public ServiceFramework<IScanRequest> { | 14 | class IScanRequest final : public ServiceFramework<IScanRequest> { |
| 16 | public: | 15 | public: |
| @@ -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 | ||
| 9 | namespace Service { | 9 | namespace Service::NIFM { |
| 10 | namespace NIFM { | ||
| 11 | 10 | ||
| 12 | class Module final { | 11 | class Module final { |
| 13 | public: | 12 | public: |
| @@ -25,5 +24,4 @@ public: | |||
| 25 | 24 | ||
| 26 | void InstallInterfaces(SM::ServiceManager& service_manager); | 25 | void 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 | ||
| 7 | namespace Service { | 7 | namespace Service::NIFM { |
| 8 | namespace NIFM { | ||
| 9 | 8 | ||
| 10 | NIFM_A::NIFM_A(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "nifm:a") { | 9 | NIFM_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 | ||
| 9 | namespace Service { | 9 | namespace Service::NIFM { |
| 10 | namespace NIFM { | ||
| 11 | 10 | ||
| 12 | class NIFM_A final : public Module::Interface { | 11 | class NIFM_A final : public Module::Interface { |
| 13 | public: | 12 | public: |
| 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 | ||
| 7 | namespace Service { | 7 | namespace Service::NIFM { |
| 8 | namespace NIFM { | ||
| 9 | 8 | ||
| 10 | NIFM_S::NIFM_S(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "nifm:s") { | 9 | NIFM_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 | ||
| 9 | namespace Service { | 9 | namespace Service::NIFM { |
| 10 | namespace NIFM { | ||
| 11 | 10 | ||
| 12 | class NIFM_S final : public Module::Interface { | 11 | class NIFM_S final : public Module::Interface { |
| 13 | public: | 12 | public: |
| 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 | ||
| 7 | namespace Service { | 7 | namespace Service::NIFM { |
| 8 | namespace NIFM { | ||
| 9 | 8 | ||
| 10 | NIFM_U::NIFM_U(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "nifm:u") { | 9 | NIFM_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 | ||
| 9 | namespace Service { | 9 | namespace Service::NIFM { |
| 10 | namespace NIFM { | ||
| 11 | 10 | ||
| 12 | class NIFM_U final : public Module::Interface { | 11 | class NIFM_U final : public Module::Interface { |
| 13 | public: | 12 | public: |
| 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 | ||
| 8 | namespace Service { | 8 | namespace Service::NS { |
| 9 | namespace NS { | ||
| 10 | 9 | ||
| 11 | void InstallInterfaces(SM::ServiceManager& service_manager) { | 10 | void 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 | ||
| 9 | namespace Service { | 9 | namespace Service::NS { |
| 10 | namespace NS { | ||
| 11 | 10 | ||
| 12 | /// Registers all NS services with the specified service manager. | 11 | /// Registers all NS services with the specified service manager. |
| 13 | void InstallInterfaces(SM::ServiceManager& service_manager); | 12 | void 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 | ||
| 11 | namespace Service { | 11 | namespace Service::NS { |
| 12 | namespace NS { | ||
| 13 | 12 | ||
| 14 | struct FontRegion { | 13 | struct 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 | ||
| 99 | void PL_U::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) { | 98 | void 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 | ||
| 11 | namespace Service { | 11 | namespace Service::NS { |
| 12 | namespace NS { | ||
| 13 | 12 | ||
| 14 | class PL_U final : public ServiceFramework<PL_U> { | 13 | class PL_U final : public ServiceFramework<PL_U> { |
| 15 | public: | 14 | public: |
| @@ -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 | ||
| 12 | namespace Service { | 12 | namespace Service::Nvidia::Devices { |
| 13 | namespace Nvidia { | ||
| 14 | namespace 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 | ||
| 13 | namespace Service { | 13 | namespace Service::Nvidia::Devices { |
| 14 | namespace Nvidia { | ||
| 15 | namespace Devices { | ||
| 16 | 14 | ||
| 17 | u32 nvdisp_disp0::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { | 15 | u32 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 | ||
| 13 | namespace Service { | 13 | namespace Service::Nvidia::Devices { |
| 14 | namespace Nvidia { | ||
| 15 | namespace Devices { | ||
| 16 | 14 | ||
| 17 | class nvmap; | 15 | class 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 | ||
| 12 | namespace Service { | 12 | namespace Service::Nvidia::Devices { |
| 13 | namespace Nvidia { | ||
| 14 | namespace Devices { | ||
| 15 | 13 | ||
| 16 | u32 nvhost_as_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { | 14 | u32 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 | ||
| 14 | namespace Service { | 14 | namespace Service::Nvidia::Devices { |
| 15 | namespace Nvidia { | ||
| 16 | namespace Devices { | ||
| 17 | 15 | ||
| 18 | class nvmap; | 16 | class 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 | ||
| 9 | namespace Service { | 9 | namespace Service::Nvidia::Devices { |
| 10 | namespace Nvidia { | ||
| 11 | namespace Devices { | ||
| 12 | 10 | ||
| 13 | u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { | 11 | u32 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 | ||
| 14 | namespace Service { | 14 | namespace Service::Nvidia::Devices { |
| 15 | namespace Nvidia { | ||
| 16 | namespace Devices { | ||
| 17 | 15 | ||
| 18 | class nvhost_ctrl final : public nvdevice { | 16 | class nvhost_ctrl final : public nvdevice { |
| 19 | public: | 17 | public: |
| @@ -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 | ||
| 10 | namespace Service { | 10 | namespace Service::Nvidia::Devices { |
| 11 | namespace Nvidia { | ||
| 12 | namespace Devices { | ||
| 13 | 11 | ||
| 14 | u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { | 12 | u32 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 | ||
| 12 | namespace Service { | 12 | namespace Service::Nvidia::Devices { |
| 13 | namespace Nvidia { | ||
| 14 | namespace Devices { | ||
| 15 | 13 | ||
| 16 | class nvhost_ctrl_gpu final : public nvdevice { | 14 | class nvhost_ctrl_gpu final : public nvdevice { |
| 17 | public: | 15 | public: |
| @@ -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 | ||
| 12 | namespace Service { | 12 | namespace Service::Nvidia::Devices { |
| 13 | namespace Nvidia { | ||
| 14 | namespace Devices { | ||
| 15 | 13 | ||
| 16 | u32 nvhost_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) { | 14 | u32 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 | ||
| 13 | namespace Service { | 13 | namespace Service::Nvidia::Devices { |
| 14 | namespace Nvidia { | ||
| 15 | namespace Devices { | ||
| 16 | 14 | ||
| 17 | class nvmap; | 15 | class nvmap; |
| 18 | constexpr u32 NVGPU_IOCTL_MAGIC('H'); | 16 | constexpr 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 | ||
| 12 | namespace Service { | 12 | namespace Service::Nvidia::Devices { |
| 13 | namespace Nvidia { | ||
| 14 | namespace Devices { | ||
| 15 | 13 | ||
| 16 | VAddr nvmap::GetObjectAddress(u32 handle) const { | 14 | VAddr 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 | ||
| 15 | namespace Service { | 15 | namespace Service::Nvidia::Devices { |
| 16 | namespace Nvidia { | ||
| 17 | namespace Devices { | ||
| 18 | 16 | ||
| 19 | class nvmap final : public nvdevice { | 17 | class nvmap final : public nvdevice { |
| 20 | public: | 18 | public: |
| @@ -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 | ||
| 12 | namespace Service { | 12 | namespace Service::Nvidia { |
| 13 | namespace Nvidia { | ||
| 14 | 13 | ||
| 15 | void NVDRV::Open(Kernel::HLERequestContext& ctx) { | 14 | void 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 | ||
| 13 | namespace Service { | 13 | namespace Service::Nvidia { |
| 14 | namespace Nvidia { | ||
| 15 | 14 | ||
| 16 | class NVDRV final : public ServiceFramework<NVDRV> { | 15 | class NVDRV final : public ServiceFramework<NVDRV> { |
| 17 | public: | 16 | public: |
| @@ -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 | ||
| 17 | namespace Service { | 17 | namespace Service::Nvidia { |
| 18 | namespace Nvidia { | ||
| 19 | 18 | ||
| 20 | std::weak_ptr<Module> nvdrv; | 19 | std::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 | ||
| 13 | namespace Service { | 13 | namespace Service::Nvidia { |
| 14 | namespace Nvidia { | ||
| 15 | 14 | ||
| 16 | namespace Devices { | 15 | namespace Devices { |
| 17 | class nvdevice; | 16 | class nvdevice; |
| @@ -61,5 +60,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager); | |||
| 61 | 60 | ||
| 62 | extern std::weak_ptr<Module> nvdrv; | 61 | extern 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 | ||
| 11 | namespace Service { | 11 | namespace Service::Nvidia { |
| 12 | namespace Nvidia { | ||
| 13 | 12 | ||
| 14 | NVMEMP::NVMEMP() : ServiceFramework("nvmemp") { | 13 | NVMEMP::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 | ||
| 9 | namespace Service { | 9 | namespace Service::Nvidia { |
| 10 | namespace Nvidia { | ||
| 11 | 10 | ||
| 12 | class NVMEMP final : public ServiceFramework<NVMEMP> { | 11 | class NVMEMP final : public ServiceFramework<NVMEMP> { |
| 13 | public: | 12 | public: |
| @@ -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 | ||
| 12 | namespace Service { | 12 | namespace Service::NVFlinger { |
| 13 | namespace NVFlinger { | ||
| 14 | 13 | ||
| 15 | BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) { | 14 | BufferQueue::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 { | |||
| 13 | struct EventType; | 13 | struct EventType; |
| 14 | } | 14 | } |
| 15 | 15 | ||
| 16 | namespace Service { | 16 | namespace Service::NVFlinger { |
| 17 | namespace NVFlinger { | ||
| 18 | 17 | ||
| 19 | struct IGBPBuffer { | 18 | struct 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 | ||
| 18 | namespace Service { | 19 | namespace Service::NVFlinger { |
| 19 | namespace NVFlinger { | ||
| 20 | 20 | ||
| 21 | constexpr size_t SCREEN_REFRESH_RATE = 60; | 21 | constexpr size_t SCREEN_REFRESH_RATE = 60; |
| 22 | constexpr u64 frame_ticks = static_cast<u64>(BASE_CLOCK_RATE / SCREEN_REFRESH_RATE); | 22 | constexpr 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 { | |||
| 12 | struct EventType; | 12 | struct EventType; |
| 13 | } | 13 | } |
| 14 | 14 | ||
| 15 | namespace Service { | 15 | namespace Service::NVFlinger { |
| 16 | namespace NVFlinger { | ||
| 17 | 16 | ||
| 18 | class BufferQueue; | 17 | class 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 | ||
| 8 | namespace Service { | 8 | namespace Service::PCTL { |
| 9 | namespace PCTL { | ||
| 10 | 9 | ||
| 11 | void InstallInterfaces(SM::ServiceManager& service_manager) { | 10 | void 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 | ||
| 9 | namespace Service { | 9 | namespace Service::PCTL { |
| 10 | namespace PCTL { | ||
| 11 | 10 | ||
| 12 | /// Registers all PCTL services with the specified service manager. | 11 | /// Registers all PCTL services with the specified service manager. |
| 13 | void InstallInterfaces(SM::ServiceManager& service_manager); | 12 | void 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 | ||
| 9 | namespace Service { | 9 | namespace Service::PCTL { |
| 10 | namespace PCTL { | ||
| 11 | 10 | ||
| 12 | class IParentalControlService final : public ServiceFramework<IParentalControlService> { | 11 | class IParentalControlService final : public ServiceFramework<IParentalControlService> { |
| 13 | public: | 12 | public: |
| @@ -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 | ||
| 9 | namespace Service { | 9 | namespace Service::PCTL { |
| 10 | namespace PCTL { | ||
| 11 | 10 | ||
| 12 | class PCTL_A final : public ServiceFramework<PCTL_A> { | 11 | class PCTL_A final : public ServiceFramework<PCTL_A> { |
| 13 | public: | 12 | public: |
| @@ -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 |
| 173 | void Init() { | 173 | void 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 |
| 207 | void Shutdown() { | 206 | void 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 |
| 181 | void Init(); | 181 | void Init(std::shared_ptr<SM::ServiceManager>& sm); |
| 182 | 182 | ||
| 183 | /// Shutdown ServiceManager | 183 | /// Shutdown ServiceManager |
| 184 | void Shutdown(); | 184 | void 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 | ||
| 12 | namespace Service { | 12 | namespace Service::Set { |
| 13 | namespace Set { | ||
| 14 | 13 | ||
| 15 | void SET::GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx) { | 14 | void 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 | ||
| 9 | namespace Service { | 9 | namespace Service::Set { |
| 10 | namespace Set { | ||
| 11 | 10 | ||
| 12 | class SET final : public ServiceFramework<SET> { | 11 | class SET final : public ServiceFramework<SET> { |
| 13 | public: | 12 | public: |
| @@ -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 | ||
| 7 | namespace Service { | 7 | namespace Service::Set { |
| 8 | namespace Set { | ||
| 9 | 8 | ||
| 10 | SET_CAL::SET_CAL() : ServiceFramework("set:cal") { | 9 | SET_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 | ||
| 9 | namespace Service { | 9 | namespace Service::Set { |
| 10 | namespace Set { | ||
| 11 | 10 | ||
| 12 | class SET_CAL final : public ServiceFramework<SET_CAL> { | 11 | class SET_CAL final : public ServiceFramework<SET_CAL> { |
| 13 | public: | 12 | public: |
| @@ -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 | ||
| 7 | namespace Service { | 7 | namespace Service::Set { |
| 8 | namespace Set { | ||
| 9 | 8 | ||
| 10 | SET_FD::SET_FD() : ServiceFramework("set:fd") { | 9 | SET_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 | ||
| 9 | namespace Service { | 9 | namespace Service::Set { |
| 10 | namespace Set { | ||
| 11 | 10 | ||
| 12 | class SET_FD final : public ServiceFramework<SET_FD> { | 11 | class SET_FD final : public ServiceFramework<SET_FD> { |
| 13 | public: | 12 | public: |
| @@ -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 | ||
| 10 | namespace Service { | 10 | namespace Service::Set { |
| 11 | namespace Set { | ||
| 12 | 11 | ||
| 13 | void SET_SYS::GetColorSetId(Kernel::HLERequestContext& ctx) { | 12 | void 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 | ||
| 9 | namespace Service { | 9 | namespace Service::Set { |
| 10 | namespace Set { | ||
| 11 | 10 | ||
| 12 | class SET_SYS final : public ServiceFramework<SET_SYS> { | 11 | class SET_SYS final : public ServiceFramework<SET_SYS> { |
| 13 | public: | 12 | public: |
| @@ -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 | ||
| 11 | namespace Service { | 11 | namespace Service::Set { |
| 12 | namespace Set { | ||
| 13 | 12 | ||
| 14 | void InstallInterfaces(SM::ServiceManager& service_manager) { | 13 | void 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 | ||
| 9 | namespace Service { | 9 | namespace Service::Set { |
| 10 | namespace Set { | ||
| 11 | 10 | ||
| 12 | /// Registers all Settings services with the specified service manager. | 11 | /// Registers all Settings services with the specified service manager. |
| 13 | void InstallInterfaces(SM::ServiceManager& service_manager); | 12 | void 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 | ||
| 10 | namespace Service { | 10 | namespace Service::SM { |
| 11 | namespace SM { | ||
| 12 | 11 | ||
| 13 | void Controller::ConvertSessionToDomain(Kernel::HLERequestContext& ctx) { | 12 | void 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 | ||
| 9 | namespace Service { | 9 | namespace Service::SM { |
| 10 | namespace SM { | ||
| 11 | 10 | ||
| 12 | class Controller final : public ServiceFramework<Controller> { | 11 | class Controller final : public ServiceFramework<Controller> { |
| 13 | public: | 12 | public: |
| @@ -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 | ||
| 15 | namespace Service { | 15 | namespace Service::SM { |
| 16 | namespace SM { | 16 | |
| 17 | ServiceManager::~ServiceManager() = default; | ||
| 17 | 18 | ||
| 18 | void ServiceManager::InvokeControlRequest(Kernel::HLERequestContext& context) { | 19 | void 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 | ||
| 76 | std::shared_ptr<ServiceManager> g_service_manager; | 77 | SM::~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; | |||
| 17 | class SessionRequestHandler; | 17 | class SessionRequestHandler; |
| 18 | } // namespace Kernel | 18 | } // namespace Kernel |
| 19 | 19 | ||
| 20 | namespace Service { | 20 | namespace Service::SM { |
| 21 | namespace SM { | ||
| 22 | 21 | ||
| 23 | /// Interface to "sm:" service | 22 | /// Interface to "sm:" service |
| 24 | class SM final : public ServiceFramework<SM> { | 23 | class SM final : public ServiceFramework<SM> { |
| 25 | public: | 24 | public: |
| 26 | SM(std::shared_ptr<ServiceManager> service_manager); | 25 | SM(std::shared_ptr<ServiceManager> service_manager); |
| 27 | ~SM() = default; | 26 | ~SM() override; |
| 28 | 27 | ||
| 29 | private: | 28 | private: |
| 30 | void Initialize(Kernel::HLERequestContext& ctx); | 29 | void Initialize(Kernel::HLERequestContext& ctx); |
| @@ -45,6 +44,8 @@ class ServiceManager { | |||
| 45 | public: | 44 | public: |
| 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 | ||
| 63 | extern 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 | ||
| 8 | namespace Service { | 8 | namespace Service::Sockets { |
| 9 | namespace Sockets { | ||
| 10 | 9 | ||
| 11 | void BSD::RegisterClient(Kernel::HLERequestContext& ctx) { | 10 | void 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 | ||
| 10 | namespace Service { | 10 | namespace Service::Sockets { |
| 11 | namespace Sockets { | ||
| 12 | 11 | ||
| 13 | class BSD final : public ServiceFramework<BSD> { | 12 | class BSD final : public ServiceFramework<BSD> { |
| 14 | public: | 13 | public: |
| @@ -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 | ||
| 7 | namespace Service { | 7 | namespace Service::Sockets { |
| 8 | namespace Sockets { | ||
| 9 | 8 | ||
| 10 | NSD::NSD(const char* name) : ServiceFramework(name) { | 9 | NSD::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 | ||
| 10 | namespace Service { | 10 | namespace Service::Sockets { |
| 11 | namespace Sockets { | ||
| 12 | 11 | ||
| 13 | class NSD final : public ServiceFramework<NSD> { | 12 | class NSD final : public ServiceFramework<NSD> { |
| 14 | public: | 13 | public: |
| @@ -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 | ||
| 8 | namespace Service { | 8 | namespace Service::Sockets { |
| 9 | namespace Sockets { | ||
| 10 | 9 | ||
| 11 | void SFDNSRES::GetAddrInfo(Kernel::HLERequestContext& ctx) { | 10 | void 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 | ||
| 10 | namespace Service { | 10 | namespace Service::Sockets { |
| 11 | namespace Sockets { | ||
| 12 | 11 | ||
| 13 | class SFDNSRES final : public ServiceFramework<SFDNSRES> { | 12 | class SFDNSRES final : public ServiceFramework<SFDNSRES> { |
| 14 | public: | 13 | public: |
| @@ -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 | ||
| 10 | namespace Service { | 10 | namespace Service::Sockets { |
| 11 | namespace Sockets { | ||
| 12 | 11 | ||
| 13 | void InstallInterfaces(SM::ServiceManager& service_manager) { | 12 | void 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 | ||
| 9 | namespace Service { | 9 | namespace Service::Sockets { |
| 10 | namespace Sockets { | ||
| 11 | 10 | ||
| 12 | /// Registers all Sockets services with the specified service manager. | 11 | /// Registers all Sockets services with the specified service manager. |
| 13 | void InstallInterfaces(SM::ServiceManager& service_manager); | 12 | void 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 | ||
| 7 | namespace Service { | 7 | namespace Service::SPL { |
| 8 | namespace SPL { | ||
| 9 | 8 | ||
| 10 | CSRNG::CSRNG(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "csrng") { | 9 | CSRNG::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 | ||
| 9 | namespace Service { | 9 | namespace Service::SPL { |
| 10 | namespace SPL { | ||
| 11 | 10 | ||
| 12 | class CSRNG final : public Module::Interface { | 11 | class CSRNG final : public Module::Interface { |
| 13 | public: | 12 | public: |
| 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 | ||
| 14 | namespace Service { | 14 | namespace Service::SPL { |
| 15 | namespace SPL { | ||
| 16 | 15 | ||
| 17 | Module::Interface::Interface(std::shared_ptr<Module> module, const char* name) | 16 | Module::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 | ||
| 9 | namespace Service { | 9 | namespace Service::SPL { |
| 10 | namespace SPL { | ||
| 11 | 10 | ||
| 12 | class Module final { | 11 | class Module final { |
| 13 | public: | 12 | public: |
| @@ -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. |
| 26 | void InstallInterfaces(SM::ServiceManager& service_manager); | 25 | void 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 | ||
| 7 | namespace Service { | 7 | namespace Service::SPL { |
| 8 | namespace SPL { | ||
| 9 | 8 | ||
| 10 | SPL::SPL(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "spl:") { | 9 | SPL::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 | ||
| 9 | namespace Service { | 9 | namespace Service::SPL { |
| 10 | namespace SPL { | ||
| 11 | 10 | ||
| 12 | class SPL final : public Module::Interface { | 11 | class SPL final : public Module::Interface { |
| 13 | public: | 12 | public: |
| 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 | ||
| 8 | namespace Service { | 8 | namespace Service::SSL { |
| 9 | namespace SSL { | ||
| 10 | 9 | ||
| 11 | class ISslConnection final : public ServiceFramework<ISslConnection> { | 10 | class ISslConnection final : public ServiceFramework<ISslConnection> { |
| 12 | public: | 11 | public: |
| @@ -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 | ||
| 9 | namespace Service { | 9 | namespace Service::SSL { |
| 10 | namespace SSL { | ||
| 11 | 10 | ||
| 12 | class SSL final : public ServiceFramework<SSL> { | 11 | class SSL final : public ServiceFramework<SSL> { |
| 13 | public: | 12 | public: |
| @@ -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. |
| 22 | void InstallInterfaces(SM::ServiceManager& service_manager); | 21 | void 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 | ||
| 15 | namespace Service { | 15 | namespace Service::Time { |
| 16 | namespace Time { | ||
| 17 | 16 | ||
| 18 | class ISystemClock final : public ServiceFramework<ISystemClock> { | 17 | class ISystemClock final : public ServiceFramework<ISystemClock> { |
| 19 | public: | 18 | public: |
| 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 | ||
| 9 | namespace Service { | 9 | namespace Service::Time { |
| 10 | namespace Time { | ||
| 11 | 10 | ||
| 12 | // TODO(Rozelette) RE this structure | 11 | // TODO(Rozelette) RE this structure |
| 13 | struct LocationName { | 12 | struct 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. |
| 67 | void InstallInterfaces(SM::ServiceManager& service_manager); | 66 | void 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 | ||
| 7 | namespace Service { | 7 | namespace Service::Time { |
| 8 | namespace Time { | ||
| 9 | 8 | ||
| 10 | TIME_S::TIME_S(std::shared_ptr<Module> time) : Module::Interface(std::move(time), "time:s") { | 9 | TIME_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 | ||
| 9 | namespace Service { | 9 | namespace Service::Time { |
| 10 | namespace Time { | ||
| 11 | 10 | ||
| 12 | class TIME_S final : public Module::Interface { | 11 | class TIME_S final : public Module::Interface { |
| 13 | public: | 12 | public: |
| 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 | ||
| 7 | namespace Service { | 7 | namespace Service::Time { |
| 8 | namespace Time { | ||
| 9 | 8 | ||
| 10 | TIME_U::TIME_U(std::shared_ptr<Module> time) : Module::Interface(std::move(time), "time:u") { | 9 | TIME_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 | ||
| 9 | namespace Service { | 9 | namespace Service::Time { |
| 10 | namespace Time { | ||
| 11 | 10 | ||
| 12 | class TIME_U final : public Module::Interface { | 11 | class TIME_U final : public Module::Interface { |
| 13 | public: | 12 | public: |
| 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 | ||
| 24 | namespace Service { | 24 | namespace Service::VI { |
| 25 | namespace VI { | ||
| 26 | 25 | ||
| 27 | struct DisplayInfo { | 26 | struct DisplayInfo { |
| 28 | char display_name[0x40]{"Default"}; | 27 | char display_name[0x40]{"Default"}; |
| @@ -150,7 +149,7 @@ private: | |||
| 150 | 149 | ||
| 151 | class NativeWindow : public Parcel { | 150 | class NativeWindow : public Parcel { |
| 152 | public: | 151 | public: |
| 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 | ||
| 198 | class IGBPConnectResponseParcel : public Parcel { | 197 | class IGBPConnectResponseParcel : public Parcel { |
| 199 | public: | 198 | public: |
| 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 | ||
| 249 | class IGBPSetPreallocatedBufferResponseParcel : public Parcel { | 248 | class IGBPSetPreallocatedBufferResponseParcel : public Parcel { |
| 250 | public: | ||
| 251 | IGBPSetPreallocatedBufferResponseParcel() : Parcel() {} | ||
| 252 | ~IGBPSetPreallocatedBufferResponseParcel() override = default; | ||
| 253 | |||
| 254 | protected: | 249 | protected: |
| 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 | ||
| 290 | class IGBPDequeueBufferResponseParcel : public Parcel { | 285 | class IGBPDequeueBufferResponseParcel : public Parcel { |
| 291 | public: | 286 | public: |
| 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 | ||
| 295 | protected: | 290 | protected: |
| @@ -383,7 +378,7 @@ public: | |||
| 383 | 378 | ||
| 384 | class IGBPQueueBufferResponseParcel : public Parcel { | 379 | class IGBPQueueBufferResponseParcel : public Parcel { |
| 385 | public: | 380 | public: |
| 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 | ||
| 425 | class IGBPQueryResponseParcel : public Parcel { | 420 | class IGBPQueryResponseParcel : public Parcel { |
| 426 | public: | 421 | public: |
| 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 | ||
| 430 | protected: | 425 | protected: |
| @@ -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 | ||
| 601 | class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> { | 647 | class 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 { | |||
| 11 | struct EventType; | 11 | struct EventType; |
| 12 | } | 12 | } |
| 13 | 13 | ||
| 14 | namespace Service { | 14 | namespace Service::VI { |
| 15 | namespace VI { | ||
| 16 | 15 | ||
| 17 | enum class DisplayResolution : u32 { | 16 | enum class DisplayResolution : u32 { |
| 18 | DockedWidth = 1920, | 17 | DockedWidth = 1920, |
| @@ -40,5 +39,4 @@ public: | |||
| 40 | void InstallInterfaces(SM::ServiceManager& service_manager, | 39 | void 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 | ||
| 7 | namespace Service { | 7 | namespace Service::VI { |
| 8 | namespace VI { | ||
| 9 | 8 | ||
| 10 | VI_M::VI_M(std::shared_ptr<Module> module, std::shared_ptr<NVFlinger::NVFlinger> nv_flinger) | 9 | VI_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 | ||
| 9 | namespace Service { | 9 | namespace Service::VI { |
| 10 | namespace VI { | ||
| 11 | 10 | ||
| 12 | class VI_M final : public Module::Interface { | 11 | class VI_M final : public Module::Interface { |
| 13 | public: | 12 | public: |
| 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 | ||
| 7 | namespace Service { | 7 | namespace Service::VI { |
| 8 | namespace VI { | ||
| 9 | 8 | ||
| 10 | VI_S::VI_S(std::shared_ptr<Module> module, std::shared_ptr<NVFlinger::NVFlinger> nv_flinger) | 9 | VI_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 | ||
| 9 | namespace Service { | 9 | namespace Service::VI { |
| 10 | namespace VI { | ||
| 11 | 10 | ||
| 12 | class VI_S final : public Module::Interface { | 11 | class VI_S final : public Module::Interface { |
| 13 | public: | 12 | public: |
| 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 | ||
| 7 | namespace Service { | 7 | namespace Service::VI { |
| 8 | namespace VI { | ||
| 9 | 8 | ||
| 10 | VI_U::VI_U(std::shared_ptr<Module> module, std::shared_ptr<NVFlinger::NVFlinger> nv_flinger) | 9 | VI_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 | ||
| 9 | namespace Service { | 9 | namespace Service::VI { |
| 10 | namespace VI { | ||
| 11 | 10 | ||
| 12 | class VI_U final : public Module::Interface { | 11 | class VI_U final : public Module::Interface { |
| 13 | public: | 12 | public: |
| 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() { | |||
| 165 | void Maxwell3D::DrawArrays() { | 163 | void 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 | ||
| 182 | void Maxwell3D::ProcessCBBind(Regs::ShaderStage stage) { | 182 | void 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 | ||
| 306 | bool 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 @@ | |||
| 20 | namespace Tegra { | 20 | namespace Tegra { |
| 21 | namespace Engines { | 21 | namespace Engines { |
| 22 | 22 | ||
| 23 | #define MAXWELL3D_REG_INDEX(field_name) \ | ||
| 24 | (offsetof(Tegra::Engines::Maxwell3D::Regs, field_name) / sizeof(u32)) | ||
| 25 | |||
| 23 | class Maxwell3D final { | 26 | class Maxwell3D final { |
| 24 | public: | 27 | public: |
| 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 | ||
| 523 | private: | 615 | /// Returns whether the specified shader stage is enabled or not. |
| 524 | MemoryManager& memory_manager; | 616 | bool IsShaderStageEnabled(Regs::ShaderStage stage) const; |
| 525 | 617 | ||
| 618 | private: | ||
| 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 | ||
| 566 | ASSERT_REG_POSITION(rt, 0x200); | 659 | ASSERT_REG_POSITION(rt, 0x200); |
| 660 | ASSERT_REG_POSITION(viewport_transform[0], 0x280); | ||
| 567 | ASSERT_REG_POSITION(viewport, 0x300); | 661 | ASSERT_REG_POSITION(viewport, 0x300); |
| 568 | ASSERT_REG_POSITION(vertex_buffer, 0x35D); | 662 | ASSERT_REG_POSITION(vertex_buffer, 0x35D); |
| 569 | ASSERT_REG_POSITION(zeta, 0x3F8); | 663 | ASSERT_REG_POSITION(zeta, 0x3F8); |
| @@ -573,8 +667,10 @@ ASSERT_REG_POSITION(tsc, 0x557); | |||
| 573 | ASSERT_REG_POSITION(tic, 0x55D); | 667 | ASSERT_REG_POSITION(tic, 0x55D); |
| 574 | ASSERT_REG_POSITION(code_address, 0x582); | 668 | ASSERT_REG_POSITION(code_address, 0x582); |
| 575 | ASSERT_REG_POSITION(draw, 0x585); | 669 | ASSERT_REG_POSITION(draw, 0x585); |
| 670 | ASSERT_REG_POSITION(index_array, 0x5F2); | ||
| 576 | ASSERT_REG_POSITION(query, 0x6C0); | 671 | ASSERT_REG_POSITION(query, 0x6C0); |
| 577 | ASSERT_REG_POSITION(vertex_array[0], 0x700); | 672 | ASSERT_REG_POSITION(vertex_array[0], 0x700); |
| 673 | ASSERT_REG_POSITION(blend, 0x780); | ||
| 578 | ASSERT_REG_POSITION(vertex_array_limit[0], 0x7C0); | 674 | ASSERT_REG_POSITION(vertex_array_limit[0], 0x7C0); |
| 579 | ASSERT_REG_POSITION(shader_config[0], 0x800); | 675 | ASSERT_REG_POSITION(shader_config[0], 0x800); |
| 580 | ASSERT_REG_POSITION(const_buffer, 0x8E0); | 676 | ASSERT_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 | |||
| 18 | namespace Tegra { | ||
| 19 | namespace Shader { | ||
| 20 | |||
| 21 | struct 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 | |||
| 51 | private: | ||
| 52 | u64 value{}; | ||
| 53 | }; | ||
| 54 | |||
| 55 | union 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 | |||
| 80 | union 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 | |||
| 93 | union Uniform { | ||
| 94 | BitField<20, 14, u64> offset; | ||
| 95 | BitField<34, 5, u64> index; | ||
| 96 | }; | ||
| 97 | |||
| 98 | } // namespace Shader | ||
| 99 | } // namespace Tegra | ||
| 100 | |||
| 101 | namespace std { | ||
| 102 | |||
| 103 | // TODO(bunnei): The below is forbidden by the C++ standard, but works fine. See #330. | ||
| 104 | template <> | ||
| 105 | struct make_unsigned<Tegra::Shader::Attribute> { | ||
| 106 | using type = Tegra::Shader::Attribute; | ||
| 107 | }; | ||
| 108 | |||
| 109 | template <> | ||
| 110 | struct make_unsigned<Tegra::Shader::Register> { | ||
| 111 | using type = Tegra::Shader::Register; | ||
| 112 | }; | ||
| 113 | |||
| 114 | } // namespace std | ||
| 115 | |||
| 116 | namespace Tegra { | ||
| 117 | namespace Shader { | ||
| 118 | |||
| 119 | enum class Pred : u64 { | ||
| 120 | UnusedIndex = 0x7, | ||
| 121 | NeverExecute = 0xF, | ||
| 122 | }; | ||
| 123 | |||
| 124 | enum 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 | |||
| 134 | enum class PredOperation : u64 { | ||
| 135 | And = 0, | ||
| 136 | Or = 1, | ||
| 137 | Xor = 2, | ||
| 138 | }; | ||
| 139 | |||
| 140 | enum 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 | |||
| 150 | union 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 | }; | ||
| 227 | static_assert(sizeof(Instruction) == 0x8, "Incorrect structure size"); | ||
| 228 | static_assert(std::is_standard_layout<Instruction>::value, | ||
| 229 | "Structure does not have standard layout"); | ||
| 230 | |||
| 231 | class OpCode { | ||
| 232 | public: | ||
| 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 | |||
| 340 | private: | ||
| 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 | ||
| 16 | enum class RenderTargetFormat : u32 { | 16 | enum 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 | ||
| 21 | class DebugContext; | 24 | class 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)); | |||
| 34 | MICROPROFILE_DEFINE(OpenGL_Blits, "OpenGL", "Blits", MP_RGB(100, 100, 255)); | 34 | MICROPROFILE_DEFINE(OpenGL_Blits, "OpenGL", "Blits", MP_RGB(100, 100, 255)); |
| 35 | MICROPROFILE_DEFINE(OpenGL_CacheManagement, "OpenGL", "Cache Mgmt", MP_RGB(100, 255, 100)); | 35 | MICROPROFILE_DEFINE(OpenGL_CacheManagement, "OpenGL", "Cache Mgmt", MP_RGB(100, 255, 100)); |
| 36 | 36 | ||
| 37 | enum class UniformBindings : GLuint { Common, VS, FS }; | ||
| 38 | |||
| 39 | static 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 | |||
| 52 | static 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 | |||
| 61 | RasterizerOpenGL::RasterizerOpenGL() { | 37 | RasterizerOpenGL::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 | ||
| 152 | void 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 | |||
| 163 | void RasterizerOpenGL::SetupVertexArray(u8* array_ptr, GLintptr buffer_offset) { | 130 | void 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 | ||
| 203 | void RasterizerOpenGL::SetupVertexShader(VSUniformData* ub_ptr, GLintptr buffer_offset) { | 175 | void 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 | ||
| 209 | void 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 | ||
| 214 | bool 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 | |||
| 255 | bool 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 | ||
| 385 | void RasterizerOpenGL::BindTextures() { | 416 | void 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 | ||
| 418 | void RasterizerOpenGL::NotifyMaxwellRegisterChanged(u32 id) {} | 449 | void 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 | ||
| 420 | void RasterizerOpenGL::FlushAll() { | 476 | void 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 | ||
| 534 | void RasterizerOpenGL::SetShader() { | 593 | u32 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 | |||
| 542 | in vec2 vert_position; | ||
| 543 | in vec2 vert_tex_coord; | ||
| 544 | out vec2 frag_tex_coord; | ||
| 545 | |||
| 546 | void 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 | |||
| 558 | in vec2 frag_tex_coord; | ||
| 559 | out vec4 color; | ||
| 560 | |||
| 561 | uniform sampler2D tex[32]; | ||
| 562 | 598 | ||
| 563 | void 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 | ||
| 600 | void RasterizerOpenGL::BindFramebufferSurfaces(const Surface& color_surface, | 642 | void 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 | |||
| 87 | private: | 56 | private: |
| 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 | ||
| 37 | using SurfaceType = SurfaceParams::SurfaceType; | 35 | using SurfaceType = SurfaceParams::SurfaceType; |
| 38 | using PixelFormat = SurfaceParams::PixelFormat; | 36 | using PixelFormat = SurfaceParams::PixelFormat; |
| 37 | using ComponentType = SurfaceParams::ComponentType; | ||
| 39 | 38 | ||
| 40 | struct FormatTuple { | 39 | struct 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 | ||
| 50 | static constexpr std::array<FormatTuple, 1> fb_format_tuples = {{ | 49 | static 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 | ||
| 54 | static constexpr std::array<FormatTuple, 2> tex_format_tuples = {{ | 57 | static 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 | |||
| 59 | static 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 | ||
| 87 | template <bool morton_to_gl, PixelFormat format> | 84 | template <bool morton_to_gl, PixelFormat format> |
| 88 | static void MortonCopyTile(u32 stride, u8* tile_buffer, u8* gl_buffer) { | 85 | void 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 | |||
| 104 | template <bool morton_to_gl, PixelFormat format> | ||
| 105 | void 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 | |
| 116 | template <> | 97 | // the configuration for this and perform more generic un/swizzle |
| 117 | void 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 | ||
| 130 | static constexpr std::array<void (*)(u32, u32, u8*, VAddr, VAddr, VAddr), 2> morton_to_gl_fns = { | 104 | static 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 | ||
| 135 | static constexpr std::array<void (*)(u32, u32, u8*, VAddr, VAddr, VAddr), 2> gl_to_morton_fns = { | 112 | static 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 | ||
| 312 | bool SurfaceParams::ExactMatch(const SurfaceParams& other_surface) const { | 295 | bool 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 | ||
| 319 | bool SurfaceParams::CanSubRect(const SurfaceParams& sub_surface) const { | 304 | bool 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 { | |||
| 328 | bool SurfaceParams::CanExpand(const SurfaceParams& expanded_surface) const { | 314 | bool 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 | ||
| 688 | enum MatchFlags { | 673 | enum 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 | ||
| 688 | constexpr 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 |
| 703 | template <MatchFlags find_flags> | 693 | template <MatchFlags find_flags> |
| 704 | Surface FindMatch(const SurfaceCache& surface_cache, const SurfaceParams& params, | 694 | Surface 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 | ||
| 53 | struct SurfaceParams { | 53 | struct 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 | ||
| 220 | struct CachedSurface : SurfaceParams { | 296 | struct 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 @@ | |||
| 13 | class OGLTexture : private NonCopyable { | 13 | class OGLTexture : private NonCopyable { |
| 14 | public: | 14 | public: |
| 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: | |||
| 46 | class OGLSampler : private NonCopyable { | 48 | class OGLSampler : private NonCopyable { |
| 47 | public: | 49 | public: |
| 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: | |||
| 79 | class OGLShader : private NonCopyable { | 83 | class OGLShader : private NonCopyable { |
| 80 | public: | 84 | public: |
| 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 | |||
| 117 | class OGLProgram : private NonCopyable { | ||
| 118 | public: | ||
| 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: | |||
| 115 | class OGLPipeline : private NonCopyable { | 165 | class OGLPipeline : private NonCopyable { |
| 116 | public: | 166 | public: |
| 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: | |||
| 148 | class OGLBuffer : private NonCopyable { | 197 | class OGLBuffer : private NonCopyable { |
| 149 | public: | 198 | public: |
| 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 { | |||
| 182 | public: | 233 | public: |
| 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: | |||
| 214 | class OGLVertexArray : private NonCopyable { | 265 | class OGLVertexArray : private NonCopyable { |
| 215 | public: | 266 | public: |
| 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: | |||
| 247 | class OGLFramebuffer : private NonCopyable { | 300 | class OGLFramebuffer : private NonCopyable { |
| 248 | public: | 301 | public: |
| 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 | ||
| 11 | namespace Maxwell3D { | 14 | namespace GLShader { |
| 12 | namespace Shader { | ||
| 13 | namespace Decompiler { | 15 | namespace Decompiler { |
| 14 | 16 | ||
| 17 | using Tegra::Shader::Attribute; | ||
| 18 | using Tegra::Shader::Instruction; | ||
| 19 | using Tegra::Shader::OpCode; | ||
| 20 | using Tegra::Shader::Register; | ||
| 21 | using Tegra::Shader::Sampler; | ||
| 22 | using Tegra::Shader::SubOp; | ||
| 23 | using Tegra::Shader::Uniform; | ||
| 24 | |||
| 15 | constexpr u32 PROGRAM_END = MAX_PROGRAM_CODE_LENGTH; | 25 | constexpr u32 PROGRAM_END = MAX_PROGRAM_CODE_LENGTH; |
| 16 | 26 | ||
| 17 | class Impl { | 27 | class DecompileFail : public std::runtime_error { |
| 28 | public: | ||
| 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. | ||
| 33 | enum 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. | ||
| 41 | struct 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. | ||
| 58 | class ControlFlowAnalyzer { | ||
| 18 | public: | 59 | public: |
| 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 | ||
| 33 | private: | 73 | private: |
| 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 | |||
| 112 | class ShaderWriter { | ||
| 113 | public: | ||
| 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 | |||
| 141 | private: | ||
| 142 | void AppendIndentation() { | ||
| 143 | shader_source.append(static_cast<size_t>(scope) * 4, ' '); | ||
| 144 | } | ||
| 145 | |||
| 146 | std::string shader_source; | ||
| 42 | }; | 147 | }; |
| 43 | 148 | ||
| 44 | std::string DecompileProgram(const std::array<u32, MAX_PROGRAM_CODE_LENGTH>& program_code, | 149 | class GLSLGenerator { |
| 45 | const std::array<u32, MAX_SWIZZLE_DATA_LENGTH>& swizzle_data, | 150 | public: |
| 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 | |||
| 168 | private: | ||
| 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 | |||
| 745 | private: | ||
| 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 | |||
| 762 | std::string GetCommonDeclarations() { | ||
| 763 | return "bool exec_shader();"; | ||
| 764 | } | ||
| 765 | |||
| 766 | boost::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 | ||
| 10 | namespace Maxwell3D { | 15 | namespace GLShader { |
| 11 | namespace Shader { | ||
| 12 | namespace Decompiler { | 16 | namespace Decompiler { |
| 13 | 17 | ||
| 14 | constexpr size_t MAX_PROGRAM_CODE_LENGTH{0x100000}; | 18 | using Tegra::Engines::Maxwell3D; |
| 15 | constexpr size_t MAX_SWIZZLE_DATA_LENGTH{0x100000}; | 19 | |
| 20 | std::string GetCommonDeclarations(); | ||
| 16 | 21 | ||
| 17 | std::string DecompileProgram(const std::array<u32, MAX_PROGRAM_CODE_LENGTH>& program_code, | 22 | boost::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 | ||
| 8 | namespace GLShader { | 10 | namespace GLShader { |
| 9 | 11 | ||
| 10 | std::string GenerateVertexShader(const MaxwellVSConfig& config) { | 12 | using Tegra::Engines::Maxwell3D; |
| 11 | UNREACHABLE(); | 13 | |
| 12 | return {}; | 14 | static constexpr u32 PROGRAM_OFFSET{10}; |
| 15 | |||
| 16 | ProgramResult 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 | |||
| 26 | out gl_PerVertex { | ||
| 27 | vec4 gl_Position; | ||
| 28 | }; | ||
| 29 | |||
| 30 | out vec4 position; | ||
| 31 | |||
| 32 | layout (std140) uniform vs_config { | ||
| 33 | vec4 viewport_flip; | ||
| 34 | }; | ||
| 35 | |||
| 36 | void 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 | |||
| 48 | ProgramResult 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 | |||
| 58 | in vec4 position; | ||
| 59 | out vec4 color; | ||
| 60 | |||
| 61 | layout (std140) uniform fs_config { | ||
| 62 | vec4 viewport_flip; | ||
| 63 | }; | ||
| 64 | |||
| 65 | uniform sampler2D tex[32]; | ||
| 66 | |||
| 67 | void main() { | ||
| 68 | exec_shader(); | ||
| 13 | } | 69 | } |
| 14 | 70 | ||
| 15 | std::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 | ||
| 12 | namespace GLShader { | 15 | namespace GLShader { |
| 13 | 16 | ||
| 14 | enum Attributes { | 17 | constexpr size_t MAX_PROGRAM_CODE_LENGTH{0x1000}; |
| 15 | ATTRIBUTE_POSITION, | 18 | |
| 16 | ATTRIBUTE_COLOR, | 19 | using ProgramCode = std::array<u64, MAX_PROGRAM_CODE_LENGTH>; |
| 17 | ATTRIBUTE_TEXCOORD0, | 20 | |
| 18 | ATTRIBUTE_TEXCOORD1, | 21 | class ConstBufferEntry { |
| 19 | ATTRIBUTE_TEXCOORD2, | 22 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; |
| 20 | ATTRIBUTE_TEXCOORD0_W, | 23 | |
| 21 | ATTRIBUTE_NORMQUAT, | 24 | public: |
| 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 | |||
| 48 | private: | ||
| 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 | ||
| 25 | struct MaxwellShaderConfigCommon { | 59 | struct ShaderEntries { |
| 26 | explicit MaxwellShaderConfigCommon(){}; | 60 | std::vector<ConstBufferEntry> const_buffer_entries; |
| 27 | }; | 61 | }; |
| 28 | 62 | ||
| 29 | struct MaxwellVSConfig : MaxwellShaderConfigCommon { | 63 | using ProgramResult = std::pair<std::string, ShaderEntries>; |
| 30 | explicit MaxwellVSConfig() : MaxwellShaderConfigCommon() {} | ||
| 31 | 64 | ||
| 32 | bool operator==(const MaxwellVSConfig& o) const { | 65 | struct 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 | |||
| 79 | private: | ||
| 80 | u64 program_code_hash{}; | ||
| 35 | }; | 81 | }; |
| 36 | 82 | ||
| 37 | struct MaxwellFSConfig : MaxwellShaderConfigCommon { | 83 | struct 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 | ||
| 45 | std::string GenerateVertexShader(const MaxwellVSConfig& config); | 91 | struct MaxwellVSConfig : Common::HashableStruct<MaxwellShaderConfigCommon> { |
| 46 | std::string GenerateFragmentShader(const MaxwellFSConfig& config); | 92 | explicit MaxwellVSConfig(ShaderSetup& setup) { |
| 93 | state.Init(setup); | ||
| 94 | } | ||
| 95 | }; | ||
| 96 | |||
| 97 | struct 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 | */ | ||
| 107 | ProgramResult 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 | */ | ||
| 113 | ProgramResult GenerateFragmentShader(const ShaderSetup& setup, const MaxwellFSConfig& config); | ||
| 47 | 114 | ||
| 48 | } // namespace GLShader | 115 | } // namespace GLShader |
| 49 | 116 | ||
| @@ -52,14 +119,14 @@ namespace std { | |||
| 52 | template <> | 119 | template <> |
| 53 | struct hash<GLShader::MaxwellVSConfig> { | 120 | struct 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 | ||
| 59 | template <> | 126 | template <> |
| 60 | struct hash<GLShader::MaxwellFSConfig> { | 127 | struct 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 | |||
| 10 | namespace GLShader { | ||
| 11 | |||
| 12 | namespace Impl { | ||
| 13 | void 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 | |||
| 26 | void 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 | |||
| 35 | void 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 | |||
| 56 | void 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 | |||
| 15 | namespace GLShader { | ||
| 16 | |||
| 17 | /// Number of OpenGL texture samplers that can be used in the fragment shader | ||
| 18 | static constexpr size_t NumTextureSamplers = 32; | ||
| 19 | |||
| 20 | using Tegra::Engines::Maxwell3D; | ||
| 21 | |||
| 22 | namespace Impl { | ||
| 23 | void SetShaderUniformBlockBindings(GLuint shader); | ||
| 24 | void 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. | ||
| 31 | struct MaxwellUniformData { | ||
| 32 | void SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage); | ||
| 33 | alignas(16) GLvec4 viewport_flip; | ||
| 34 | }; | ||
| 35 | static_assert(sizeof(MaxwellUniformData) == 16, "MaxwellUniformData structure size is incorrect"); | ||
| 36 | static_assert(sizeof(MaxwellUniformData) < 16384, | ||
| 37 | "MaxwellUniformData structure must be less than 16kb as per the OpenGL spec"); | ||
| 38 | |||
| 39 | class OGLShaderStage { | ||
| 40 | public: | ||
| 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 | |||
| 59 | private: | ||
| 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. | ||
| 68 | template <typename KeyConfigType, | ||
| 69 | ProgramResult (*CodeGenerator)(const ShaderSetup&, const KeyConfigType&), | ||
| 70 | GLenum ShaderType> | ||
| 71 | class ShaderCache { | ||
| 72 | public: | ||
| 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 | |||
| 94 | private: | ||
| 95 | std::unordered_map<KeyConfigType, OGLShaderStage*> shader_map; | ||
| 96 | std::unordered_map<std::string, OGLShaderStage> shader_cache; | ||
| 97 | }; | ||
| 98 | |||
| 99 | using VertexShaders = ShaderCache<MaxwellVSConfig, &GenerateVertexShader, GL_VERTEX_SHADER>; | ||
| 100 | |||
| 101 | using FragmentShaders = ShaderCache<MaxwellFSConfig, &GenerateFragmentShader, GL_FRAGMENT_SHADER>; | ||
| 102 | |||
| 103 | class ProgramManager { | ||
| 104 | public: | ||
| 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 | |||
| 151 | private: | ||
| 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 | ||
| 11 | namespace GLShader { | 11 | namespace GLShader { |
| 12 | 12 | ||
| 13 | GLuint LoadProgram(const char* vertex_shader, const char* geometry_shader, | 13 | GLuint 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 | ||
| 10 | namespace GLShader { | 12 | namespace 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 | */ | ||
| 19 | GLuint 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 | */ |
| 19 | GLuint LoadProgram(const char* vertex_shader, const char* geometry_shader, | 27 | template <typename... T> |
| 20 | const char* fragment_shader, const std::vector<const char*>& feedback_vars = {}, | 28 | GLuint 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 | ||
| 13 | using GLvec2 = std::array<GLfloat, 2>; | ||
| 14 | using GLvec3 = std::array<GLfloat, 3>; | ||
| 15 | using GLvec4 = std::array<GLfloat, 4>; | ||
| 16 | |||
| 17 | using GLuvec2 = std::array<GLuint, 2>; | ||
| 18 | using GLuvec3 = std::array<GLuint, 3>; | ||
| 19 | using GLuvec4 = std::array<GLuint, 4>; | ||
| 20 | |||
| 13 | namespace MaxwellToGL { | 21 | namespace MaxwellToGL { |
| 14 | 22 | ||
| 15 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; | 23 | using 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 | |||
| 48 | inline 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 | ||
| 40 | inline GLenum PrimitiveTopology(Maxwell::PrimitiveTopology topology) { | 62 | inline 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 | ||
| 63 | inline GLenum WrapMode(Tegra::Texture::WrapMode wrap_mode) { | 87 | inline 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 | |||
| 105 | inline 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 | |||
| 123 | inline 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; | |||
| 57 | void main() { | 54 | void 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 | ||
| 59 | std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height) { | 65 | std::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 | */ |
| 17 | std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width, u32 height); | 17 | std::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 { | |||
| 13 | namespace Texture { | 14 | namespace Texture { |
| 14 | 15 | ||
| 15 | enum class TextureFormat : u32 { | 16 | enum 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 | ||
| 20 | enum class TextureType : u32 { | 24 | enum class TextureType : u32 { |
| @@ -55,6 +59,8 @@ union TextureHandle { | |||
| 55 | static_assert(sizeof(TextureHandle) == 4, "TextureHandle has wrong size"); | 59 | static_assert(sizeof(TextureHandle) == 4, "TextureHandle has wrong size"); |
| 56 | 60 | ||
| 57 | struct TICEntry { | 61 | struct 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 @@ | |||
| 44 | Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin); | 44 | Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin); |
| 45 | #endif | 45 | #endif |
| 46 | 46 | ||
| 47 | #ifdef _WIN32 | ||
| 48 | extern "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 | ||
| 41 | extern "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 | |||
| 40 | static void PrintHelp(const char* argv0) { | 49 | static void PrintHelp(const char* argv0) { |
| 41 | std::cout << "Usage: " << argv0 | 50 | std::cout << "Usage: " << argv0 |
| 42 | << " [options] <filename>\n" | 51 | << " [options] <filename>\n" |