summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt3
-rw-r--r--src/core/core.cpp4
-rw-r--r--src/core/network/network.cpp654
-rw-r--r--src/core/network/network.h87
-rw-r--r--src/core/network/sockets.h94
-rw-r--r--src/input_common/gcadapter/gc_adapter.cpp185
-rw-r--r--src/input_common/gcadapter/gc_adapter.h44
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h9
-rw-r--r--src/video_core/compatible_formats.cpp87
-rw-r--r--src/video_core/gpu.h82
-rw-r--r--src/video_core/gpu_thread.cpp4
-rw-r--r--src/video_core/macro/macro_jit_x64.cpp1
-rw-r--r--src/video_core/morton.cpp276
-rw-r--r--src/video_core/renderer_opengl/gl_arb_decompiler.cpp117
-rw-r--r--src/video_core/renderer_opengl/gl_buffer_cache.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_device.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_device.h5
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp103
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h4
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp5
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp26
-rw-r--r--src/video_core/renderer_opengl/gl_shader_manager.cpp71
-rw-r--r--src/video_core/renderer_opengl/gl_shader_manager.h17
-rw-r--r--src/video_core/renderer_opengl/gl_stream_buffer.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.cpp162
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp4
-rw-r--r--src/video_core/renderer_vulkan/fixed_pipeline_state.cpp1
-rw-r--r--src/video_core/renderer_vulkan/maxwell_to_vk.cpp173
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.cpp4
-rw-r--r--src/video_core/renderer_vulkan/vk_device.cpp9
-rw-r--r--src/video_core/renderer_vulkan/vk_device.h5
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp4
-rw-r--r--src/video_core/renderer_vulkan/vk_shader_decompiler.cpp17
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp10
-rw-r--r--src/video_core/shader/decode/arithmetic_integer.cpp6
-rw-r--r--src/video_core/shader/decode/image.cpp54
-rw-r--r--src/video_core/shader/decode/other.cpp3
-rw-r--r--src/video_core/shader/decode/video.cpp19
-rw-r--r--src/video_core/shader/decode/xmad.cpp15
-rw-r--r--src/video_core/shader/shader_ir.cpp4
-rw-r--r--src/video_core/surface.cpp257
-rw-r--r--src/video_core/surface.h770
-rw-r--r--src/video_core/texture_cache/format_lookup_table.cpp149
-rw-r--r--src/video_core/texture_cache/surface_base.cpp2
-rw-r--r--src/video_core/texture_cache/surface_params.cpp18
-rw-r--r--src/video_core/texture_cache/texture_cache.h8
-rw-r--r--src/video_core/textures/convert.cpp6
-rw-r--r--src/video_core/textures/decoders.cpp89
-rw-r--r--src/video_core/textures/decoders.h4
-rw-r--r--src/video_core/textures/texture.h49
-rw-r--r--src/yuzu/configuration/configuration_shared.cpp74
-rw-r--r--src/yuzu/configuration/configuration_shared.h20
-rw-r--r--src/yuzu/configuration/configure_audio.cpp23
-rw-r--r--src/yuzu/configuration/configure_audio.h6
-rw-r--r--src/yuzu/configuration/configure_audio.ui151
-rw-r--r--src/yuzu/configuration/configure_general.cpp37
-rw-r--r--src/yuzu/configuration/configure_general.h7
-rw-r--r--src/yuzu/configuration/configure_graphics.cpp54
-rw-r--r--src/yuzu/configuration/configure_graphics.h7
-rw-r--r--src/yuzu/configuration/configure_graphics.ui282
-rw-r--r--src/yuzu/configuration/configure_graphics_advanced.cpp66
-rw-r--r--src/yuzu/configuration/configure_graphics_advanced.h10
-rw-r--r--src/yuzu/configuration/configure_graphics_advanced.ui154
-rw-r--r--src/yuzu/configuration/configure_system.cpp115
-rw-r--r--src/yuzu/configuration/configure_system.h7
-rw-r--r--src/yuzu/configuration/configure_system.ui972
-rw-r--r--src/yuzu/debugger/wait_tree.cpp5
-rw-r--r--src/yuzu/uisettings.cpp2
-rw-r--r--src/yuzu/uisettings.h2
69 files changed, 3372 insertions, 2348 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index c42f95705..c85c9485f 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -586,6 +586,9 @@ add_library(core STATIC
586 memory/dmnt_cheat_vm.h 586 memory/dmnt_cheat_vm.h
587 memory.cpp 587 memory.cpp
588 memory.h 588 memory.h
589 network/network.cpp
590 network/network.h
591 network/sockets.h
589 perf_stats.cpp 592 perf_stats.cpp
590 perf_stats.h 593 perf_stats.h
591 reporter.cpp 594 reporter.cpp
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 69a1aa0a5..e598c0e2b 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -43,6 +43,7 @@
43#include "core/loader/loader.h" 43#include "core/loader/loader.h"
44#include "core/memory.h" 44#include "core/memory.h"
45#include "core/memory/cheat_engine.h" 45#include "core/memory/cheat_engine.h"
46#include "core/network/network.h"
46#include "core/perf_stats.h" 47#include "core/perf_stats.h"
47#include "core/reporter.h" 48#include "core/reporter.h"
48#include "core/settings.h" 49#include "core/settings.h"
@@ -394,6 +395,9 @@ struct System::Impl {
394 /// Telemetry session for this emulation session 395 /// Telemetry session for this emulation session
395 std::unique_ptr<Core::TelemetrySession> telemetry_session; 396 std::unique_ptr<Core::TelemetrySession> telemetry_session;
396 397
398 /// Network instance
399 Network::NetworkInstance network_instance;
400
397 ResultStatus status = ResultStatus::Success; 401 ResultStatus status = ResultStatus::Success;
398 std::string status_details = ""; 402 std::string status_details = "";
399 403
diff --git a/src/core/network/network.cpp b/src/core/network/network.cpp
new file mode 100644
index 000000000..56d173b5e
--- /dev/null
+++ b/src/core/network/network.cpp
@@ -0,0 +1,654 @@
1// Copyright 2020 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <algorithm>
6#include <cstring>
7#include <limits>
8#include <utility>
9#include <vector>
10
11#ifdef _WIN32
12#define _WINSOCK_DEPRECATED_NO_WARNINGS // gethostname
13#include <winsock2.h>
14#elif __unix__
15#include <errno.h>
16#include <fcntl.h>
17#include <netdb.h>
18#include <netinet/in.h>
19#include <poll.h>
20#include <sys/socket.h>
21#include <unistd.h>
22#else
23#error "Unimplemented platform"
24#endif
25
26#include "common/assert.h"
27#include "common/common_types.h"
28#include "common/logging/log.h"
29#include "core/network/network.h"
30#include "core/network/sockets.h"
31
32namespace Network {
33
34namespace {
35
36#ifdef _WIN32
37
38using socklen_t = int;
39
40void Initialize() {
41 WSADATA wsa_data;
42 (void)WSAStartup(MAKEWORD(2, 2), &wsa_data);
43}
44
45void Finalize() {
46 WSACleanup();
47}
48
49constexpr IPv4Address TranslateIPv4(in_addr addr) {
50 auto& bytes = addr.S_un.S_un_b;
51 return IPv4Address{bytes.s_b1, bytes.s_b2, bytes.s_b3, bytes.s_b4};
52}
53
54sockaddr TranslateFromSockAddrIn(SockAddrIn input) {
55 sockaddr_in result;
56
57#ifdef __unix__
58 result.sin_len = sizeof(result);
59#endif
60
61 switch (static_cast<Domain>(input.family)) {
62 case Domain::INET:
63 result.sin_family = AF_INET;
64 break;
65 default:
66 UNIMPLEMENTED_MSG("Unhandled sockaddr family={}", static_cast<int>(input.family));
67 result.sin_family = AF_INET;
68 break;
69 }
70
71 result.sin_port = htons(input.portno);
72
73 auto& ip = result.sin_addr.S_un.S_un_b;
74 ip.s_b1 = input.ip[0];
75 ip.s_b2 = input.ip[1];
76 ip.s_b3 = input.ip[2];
77 ip.s_b4 = input.ip[3];
78
79 sockaddr addr;
80 std::memcpy(&addr, &result, sizeof(addr));
81 return addr;
82}
83
84LINGER MakeLinger(bool enable, u32 linger_value) {
85 ASSERT(linger_value <= std::numeric_limits<u_short>::max());
86
87 LINGER value;
88 value.l_onoff = enable ? 1 : 0;
89 value.l_linger = static_cast<u_short>(linger_value);
90 return value;
91}
92
93int LastError() {
94 return WSAGetLastError();
95}
96
97bool EnableNonBlock(SOCKET fd, bool enable) {
98 u_long value = enable ? 1 : 0;
99 return ioctlsocket(fd, FIONBIO, &value) != SOCKET_ERROR;
100}
101
102#elif __unix__ // ^ _WIN32 v __unix__
103
104using SOCKET = int;
105using WSAPOLLFD = pollfd;
106using ULONG = u64;
107
108constexpr SOCKET INVALID_SOCKET = -1;
109constexpr SOCKET SOCKET_ERROR = -1;
110
111constexpr int WSAEWOULDBLOCK = EAGAIN;
112constexpr int WSAENOTCONN = ENOTCONN;
113
114constexpr int SD_RECEIVE = SHUT_RD;
115constexpr int SD_SEND = SHUT_WR;
116constexpr int SD_BOTH = SHUT_RDWR;
117
118void Initialize() {}
119
120void Finalize() {}
121
122constexpr IPv4Address TranslateIPv4(in_addr addr) {
123 const u32 bytes = addr.s_addr;
124 return IPv4Address{static_cast<u8>(bytes), static_cast<u8>(bytes >> 8),
125 static_cast<u8>(bytes >> 16), static_cast<u8>(bytes >> 24)};
126}
127
128sockaddr TranslateFromSockAddrIn(SockAddrIn input) {
129 sockaddr_in result;
130
131 switch (static_cast<Domain>(input.family)) {
132 case Domain::INET:
133 result.sin_family = AF_INET;
134 break;
135 default:
136 UNIMPLEMENTED_MSG("Unhandled sockaddr family={}", static_cast<int>(input.family));
137 result.sin_family = AF_INET;
138 break;
139 }
140
141 result.sin_port = htons(input.portno);
142
143 result.sin_addr.s_addr = input.ip[0] | input.ip[1] << 8 | input.ip[2] << 16 | input.ip[3] << 24;
144
145 sockaddr addr;
146 std::memcpy(&addr, &result, sizeof(addr));
147 return addr;
148}
149
150int WSAPoll(WSAPOLLFD* fds, ULONG nfds, int timeout) {
151 return poll(fds, nfds, timeout);
152}
153
154int closesocket(SOCKET fd) {
155 return close(fd);
156}
157
158linger MakeLinger(bool enable, u32 linger_value) {
159 linger value;
160 value.l_onoff = enable ? 1 : 0;
161 value.l_linger = linger_value;
162 return value;
163}
164
165int LastError() {
166 return errno;
167}
168
169bool EnableNonBlock(int fd, bool enable) {
170 int flags = fcntl(fd, F_GETFD);
171 if (flags == -1) {
172 return false;
173 }
174 if (enable) {
175 flags |= O_NONBLOCK;
176 } else {
177 flags &= ~O_NONBLOCK;
178 }
179 return fcntl(fd, F_SETFD, flags) == 0;
180}
181
182#endif
183
184int TranslateDomain(Domain domain) {
185 switch (domain) {
186 case Domain::INET:
187 return AF_INET;
188 default:
189 UNIMPLEMENTED_MSG("Unimplemented domain={}", static_cast<int>(domain));
190 return 0;
191 }
192}
193
194int TranslateType(Type type) {
195 switch (type) {
196 case Type::STREAM:
197 return SOCK_STREAM;
198 case Type::DGRAM:
199 return SOCK_DGRAM;
200 default:
201 UNIMPLEMENTED_MSG("Unimplemented type={}", static_cast<int>(type));
202 return 0;
203 }
204}
205
206int TranslateProtocol(Protocol protocol) {
207 switch (protocol) {
208 case Protocol::TCP:
209 return IPPROTO_TCP;
210 case Protocol::UDP:
211 return IPPROTO_UDP;
212 default:
213 UNIMPLEMENTED_MSG("Unimplemented protocol={}", static_cast<int>(protocol));
214 return 0;
215 }
216}
217
218SockAddrIn TranslateToSockAddrIn(sockaddr input_) {
219 sockaddr_in input;
220 std::memcpy(&input, &input_, sizeof(input));
221
222 SockAddrIn result;
223
224 switch (input.sin_family) {
225 case AF_INET:
226 result.family = Domain::INET;
227 break;
228 default:
229 UNIMPLEMENTED_MSG("Unhandled sockaddr family={}", input.sin_family);
230 result.family = Domain::INET;
231 break;
232 }
233
234 result.portno = ntohs(input.sin_port);
235
236 result.ip = TranslateIPv4(input.sin_addr);
237
238 return result;
239}
240
241u16 TranslatePollEvents(u16 events) {
242 u16 result = 0;
243
244 if (events & POLL_IN) {
245 events &= ~POLL_IN;
246 result |= POLLIN;
247 }
248 if (events & POLL_PRI) {
249 events &= ~POLL_PRI;
250#ifdef _WIN32
251 LOG_WARNING(Service, "Winsock doesn't support POLLPRI");
252#else
253 result |= POLL_PRI;
254#endif
255 }
256 if (events & POLL_OUT) {
257 events &= ~POLL_OUT;
258 result |= POLLOUT;
259 }
260
261 UNIMPLEMENTED_IF_MSG(events != 0, "Unhandled guest events=0x{:x}", events);
262
263 return result;
264}
265
266u16 TranslatePollRevents(u16 revents) {
267 u16 result = 0;
268 const auto translate = [&result, &revents](int host, unsigned guest) {
269 if (revents & host) {
270 revents &= ~host;
271 result |= guest;
272 }
273 };
274
275 translate(POLLIN, POLL_IN);
276 translate(POLLPRI, POLL_PRI);
277 translate(POLLOUT, POLL_OUT);
278 translate(POLLERR, POLL_ERR);
279 translate(POLLHUP, POLL_HUP);
280
281 UNIMPLEMENTED_IF_MSG(revents != 0, "Unhandled host revents=0x{:x}", revents);
282
283 return result;
284}
285
286template <typename T>
287Errno SetSockOpt(SOCKET fd, int option, T value) {
288 const int result =
289 setsockopt(fd, SOL_SOCKET, option, reinterpret_cast<const char*>(&value), sizeof(value));
290 if (result != SOCKET_ERROR) {
291 return Errno::SUCCESS;
292 }
293 const int ec = LastError();
294 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
295 return Errno::SUCCESS;
296}
297
298} // Anonymous namespace
299
300NetworkInstance::NetworkInstance() {
301 Initialize();
302}
303
304NetworkInstance::~NetworkInstance() {
305 Finalize();
306}
307
308std::pair<IPv4Address, Errno> GetHostIPv4Address() {
309 std::array<char, 256> name{};
310 if (gethostname(name.data(), static_cast<int>(name.size()) - 1) == SOCKET_ERROR) {
311 UNIMPLEMENTED_MSG("Unhandled gethostname error");
312 return {IPv4Address{}, Errno::SUCCESS};
313 }
314
315 hostent* const ent = gethostbyname(name.data());
316 if (!ent) {
317 UNIMPLEMENTED_MSG("Unhandled gethostbyname error");
318 return {IPv4Address{}, Errno::SUCCESS};
319 }
320 if (ent->h_addr_list == nullptr) {
321 UNIMPLEMENTED_MSG("No addr provided in hostent->h_addr_list");
322 return {IPv4Address{}, Errno::SUCCESS};
323 }
324 if (ent->h_length != sizeof(in_addr)) {
325 UNIMPLEMENTED_MSG("Unexpected size={} in hostent->h_length", ent->h_length);
326 }
327
328 in_addr addr;
329 std::memcpy(&addr, ent->h_addr_list[0], sizeof(addr));
330 return {TranslateIPv4(addr), Errno::SUCCESS};
331}
332
333std::pair<s32, Errno> Poll(std::vector<PollFD>& pollfds, s32 timeout) {
334 const size_t num = pollfds.size();
335
336 std::vector<WSAPOLLFD> host_pollfds(pollfds.size());
337 std::transform(pollfds.begin(), pollfds.end(), host_pollfds.begin(), [](PollFD fd) {
338 WSAPOLLFD result;
339 result.fd = fd.socket->fd;
340 result.events = TranslatePollEvents(fd.events);
341 result.revents = 0;
342 return result;
343 });
344
345 const int result = WSAPoll(host_pollfds.data(), static_cast<ULONG>(num), timeout);
346 if (result == 0) {
347 ASSERT(std::all_of(host_pollfds.begin(), host_pollfds.end(),
348 [](WSAPOLLFD fd) { return fd.revents == 0; }));
349 return {0, Errno::SUCCESS};
350 }
351
352 for (size_t i = 0; i < num; ++i) {
353 pollfds[i].revents = TranslatePollRevents(host_pollfds[i].revents);
354 }
355
356 if (result > 0) {
357 return {result, Errno::SUCCESS};
358 }
359
360 ASSERT(result == SOCKET_ERROR);
361
362 const int ec = LastError();
363 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
364 return {-1, Errno::SUCCESS};
365}
366
367Socket::~Socket() {
368 if (fd == INVALID_SOCKET) {
369 return;
370 }
371 (void)closesocket(fd);
372 fd = INVALID_SOCKET;
373}
374
375Socket::Socket(Socket&& rhs) noexcept : fd{std::exchange(rhs.fd, INVALID_SOCKET)} {}
376
377Errno Socket::Initialize(Domain domain, Type type, Protocol protocol) {
378 fd = socket(TranslateDomain(domain), TranslateType(type), TranslateProtocol(protocol));
379 if (fd != INVALID_SOCKET) {
380 return Errno::SUCCESS;
381 }
382
383 const int ec = LastError();
384 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
385 return Errno::SUCCESS;
386}
387
388std::pair<Socket::AcceptResult, Errno> Socket::Accept() {
389 sockaddr addr;
390 socklen_t addrlen = sizeof(addr);
391 const SOCKET new_socket = accept(fd, &addr, &addrlen);
392
393 if (new_socket == INVALID_SOCKET) {
394 const int ec = LastError();
395 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
396 return {AcceptResult{}, Errno::SUCCESS};
397 }
398
399 AcceptResult result;
400 result.socket = std::make_unique<Socket>();
401 result.socket->fd = new_socket;
402
403 ASSERT(addrlen == sizeof(sockaddr_in));
404 result.sockaddr_in = TranslateToSockAddrIn(addr);
405
406 return {std::move(result), Errno::SUCCESS};
407}
408
409Errno Socket::Connect(SockAddrIn addr_in) {
410 const sockaddr host_addr_in = TranslateFromSockAddrIn(addr_in);
411 if (connect(fd, &host_addr_in, sizeof(host_addr_in)) != INVALID_SOCKET) {
412 return Errno::SUCCESS;
413 }
414
415 switch (const int ec = LastError()) {
416 case WSAEWOULDBLOCK:
417 LOG_DEBUG(Service, "EAGAIN generated");
418 return Errno::AGAIN;
419 default:
420 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
421 return Errno::SUCCESS;
422 }
423}
424
425std::pair<SockAddrIn, Errno> Socket::GetPeerName() {
426 sockaddr addr;
427 socklen_t addrlen = sizeof(addr);
428 if (getpeername(fd, &addr, &addrlen) == SOCKET_ERROR) {
429 const int ec = LastError();
430 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
431 return {SockAddrIn{}, Errno::SUCCESS};
432 }
433
434 ASSERT(addrlen == sizeof(sockaddr_in));
435 return {TranslateToSockAddrIn(addr), Errno::SUCCESS};
436}
437
438std::pair<SockAddrIn, Errno> Socket::GetSockName() {
439 sockaddr addr;
440 socklen_t addrlen = sizeof(addr);
441 if (getsockname(fd, &addr, &addrlen) == SOCKET_ERROR) {
442 const int ec = LastError();
443 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
444 return {SockAddrIn{}, Errno::SUCCESS};
445 }
446
447 ASSERT(addrlen == sizeof(sockaddr_in));
448 return {TranslateToSockAddrIn(addr), Errno::SUCCESS};
449}
450
451Errno Socket::Bind(SockAddrIn addr) {
452 const sockaddr addr_in = TranslateFromSockAddrIn(addr);
453 if (bind(fd, &addr_in, sizeof(addr_in)) != SOCKET_ERROR) {
454 return Errno::SUCCESS;
455 }
456
457 const int ec = LastError();
458 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
459 return Errno::SUCCESS;
460}
461
462Errno Socket::Listen(s32 backlog) {
463 if (listen(fd, backlog) != SOCKET_ERROR) {
464 return Errno::SUCCESS;
465 }
466
467 const int ec = LastError();
468 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
469 return Errno::SUCCESS;
470}
471
472Errno Socket::Shutdown(ShutdownHow how) {
473 int host_how = 0;
474 switch (how) {
475 case ShutdownHow::RD:
476 host_how = SD_RECEIVE;
477 break;
478 case ShutdownHow::WR:
479 host_how = SD_SEND;
480 break;
481 case ShutdownHow::RDWR:
482 host_how = SD_BOTH;
483 break;
484 default:
485 UNIMPLEMENTED_MSG("Unimplemented flag how={}", static_cast<int>(how));
486 return Errno::SUCCESS;
487 }
488 if (shutdown(fd, host_how) != SOCKET_ERROR) {
489 return Errno::SUCCESS;
490 }
491
492 switch (const int ec = LastError()) {
493 case WSAENOTCONN:
494 LOG_ERROR(Service, "ENOTCONN generated");
495 return Errno::NOTCONN;
496 default:
497 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
498 return Errno::SUCCESS;
499 }
500}
501
502std::pair<s32, Errno> Socket::Recv(int flags, std::vector<u8>& message) {
503 ASSERT(flags == 0);
504 ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max()));
505
506 const int result =
507 recv(fd, reinterpret_cast<char*>(message.data()), static_cast<int>(message.size()), 0);
508 if (result != SOCKET_ERROR) {
509 return {result, Errno::SUCCESS};
510 }
511
512 switch (const int ec = LastError()) {
513 case WSAEWOULDBLOCK:
514 LOG_DEBUG(Service, "EAGAIN generated");
515 return {-1, Errno::AGAIN};
516 case WSAENOTCONN:
517 LOG_ERROR(Service, "ENOTCONN generated");
518 return {-1, Errno::NOTCONN};
519 default:
520 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
521 return {0, Errno::SUCCESS};
522 }
523}
524
525std::pair<s32, Errno> Socket::RecvFrom(int flags, std::vector<u8>& message, SockAddrIn* addr) {
526 ASSERT(flags == 0);
527 ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max()));
528
529 sockaddr addr_in{};
530 socklen_t addrlen = sizeof(addr_in);
531 socklen_t* const p_addrlen = addr ? &addrlen : nullptr;
532 sockaddr* const p_addr_in = addr ? &addr_in : nullptr;
533
534 const int result = recvfrom(fd, reinterpret_cast<char*>(message.data()),
535 static_cast<int>(message.size()), 0, p_addr_in, p_addrlen);
536 if (result != SOCKET_ERROR) {
537 if (addr) {
538 ASSERT(addrlen == sizeof(addr_in));
539 *addr = TranslateToSockAddrIn(addr_in);
540 }
541 return {result, Errno::SUCCESS};
542 }
543
544 switch (const int ec = LastError()) {
545 case WSAEWOULDBLOCK:
546 LOG_DEBUG(Service, "EAGAIN generated");
547 return {-1, Errno::AGAIN};
548 case WSAENOTCONN:
549 LOG_ERROR(Service, "ENOTCONN generated");
550 return {-1, Errno::NOTCONN};
551 default:
552 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
553 return {-1, Errno::SUCCESS};
554 }
555}
556
557std::pair<s32, Errno> Socket::Send(const std::vector<u8>& message, int flags) {
558 ASSERT(message.size() < static_cast<size_t>(std::numeric_limits<int>::max()));
559 ASSERT(flags == 0);
560
561 const int result = send(fd, reinterpret_cast<const char*>(message.data()),
562 static_cast<int>(message.size()), 0);
563 if (result != SOCKET_ERROR) {
564 return {result, Errno::SUCCESS};
565 }
566
567 const int ec = LastError();
568 switch (ec) {
569 case WSAEWOULDBLOCK:
570 LOG_DEBUG(Service, "EAGAIN generated");
571 return {-1, Errno::AGAIN};
572 case WSAENOTCONN:
573 LOG_ERROR(Service, "ENOTCONN generated");
574 return {-1, Errno::NOTCONN};
575 default:
576 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
577 return {-1, Errno::SUCCESS};
578 }
579}
580
581std::pair<s32, Errno> Socket::SendTo(u32 flags, const std::vector<u8>& message,
582 const SockAddrIn* addr) {
583 ASSERT(flags == 0);
584
585 const sockaddr* to = nullptr;
586 const int tolen = addr ? 0 : sizeof(sockaddr);
587 sockaddr host_addr_in;
588
589 if (addr) {
590 host_addr_in = TranslateFromSockAddrIn(*addr);
591 to = &host_addr_in;
592 }
593
594 const int result = sendto(fd, reinterpret_cast<const char*>(message.data()),
595 static_cast<int>(message.size()), 0, to, tolen);
596 if (result != SOCKET_ERROR) {
597 return {result, Errno::SUCCESS};
598 }
599
600 const int ec = LastError();
601 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
602 return {-1, Errno::SUCCESS};
603}
604
605Errno Socket::Close() {
606 [[maybe_unused]] const int result = closesocket(fd);
607 ASSERT(result == 0);
608 fd = INVALID_SOCKET;
609
610 return Errno::SUCCESS;
611}
612
613Errno Socket::SetLinger(bool enable, u32 linger) {
614 return SetSockOpt(fd, SO_LINGER, MakeLinger(enable, linger));
615}
616
617Errno Socket::SetReuseAddr(bool enable) {
618 return SetSockOpt<u32>(fd, SO_REUSEADDR, enable ? 1 : 0);
619}
620
621Errno Socket::SetBroadcast(bool enable) {
622 return SetSockOpt<u32>(fd, SO_BROADCAST, enable ? 1 : 0);
623}
624
625Errno Socket::SetSndBuf(u32 value) {
626 return SetSockOpt(fd, SO_SNDBUF, value);
627}
628
629Errno Socket::SetRcvBuf(u32 value) {
630 return SetSockOpt(fd, SO_RCVBUF, value);
631}
632
633Errno Socket::SetSndTimeo(u32 value) {
634 return SetSockOpt(fd, SO_SNDTIMEO, value);
635}
636
637Errno Socket::SetRcvTimeo(u32 value) {
638 return SetSockOpt(fd, SO_RCVTIMEO, value);
639}
640
641Errno Socket::SetNonBlock(bool enable) {
642 if (EnableNonBlock(fd, enable)) {
643 return Errno::SUCCESS;
644 }
645 const int ec = LastError();
646 UNREACHABLE_MSG("Unhandled host socket error={}", ec);
647 return Errno::SUCCESS;
648}
649
650bool Socket::IsOpened() const {
651 return fd != INVALID_SOCKET;
652}
653
654} // namespace Network
diff --git a/src/core/network/network.h b/src/core/network/network.h
new file mode 100644
index 000000000..0622e4593
--- /dev/null
+++ b/src/core/network/network.h
@@ -0,0 +1,87 @@
1// Copyright 2020 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 <utility>
9
10#include "common/common_types.h"
11
12namespace Network {
13
14class Socket;
15
16/// Error code for network functions
17enum class Errno {
18 SUCCESS,
19 BADF,
20 INVAL,
21 MFILE,
22 NOTCONN,
23 AGAIN,
24};
25
26/// Address families
27enum class Domain {
28 INET, ///< Address family for IPv4
29};
30
31/// Socket types
32enum class Type {
33 STREAM,
34 DGRAM,
35 RAW,
36 SEQPACKET,
37};
38
39/// Protocol values for sockets
40enum class Protocol {
41 ICMP,
42 TCP,
43 UDP,
44};
45
46/// Shutdown mode
47enum class ShutdownHow {
48 RD,
49 WR,
50 RDWR,
51};
52
53/// Array of IPv4 address
54using IPv4Address = std::array<u8, 4>;
55
56/// Cross-platform sockaddr structure
57struct SockAddrIn {
58 Domain family;
59 IPv4Address ip;
60 u16 portno;
61};
62
63/// Cross-platform poll fd structure
64struct PollFD {
65 Socket* socket;
66 u16 events;
67 u16 revents;
68};
69
70constexpr u16 POLL_IN = 1 << 0;
71constexpr u16 POLL_PRI = 1 << 1;
72constexpr u16 POLL_OUT = 1 << 2;
73constexpr u16 POLL_ERR = 1 << 3;
74constexpr u16 POLL_HUP = 1 << 4;
75constexpr u16 POLL_NVAL = 1 << 5;
76
77class NetworkInstance {
78public:
79 explicit NetworkInstance();
80 ~NetworkInstance();
81};
82
83/// @brief Returns host's IPv4 address
84/// @return Pair of an array of human ordered IPv4 address (e.g. 192.168.0.1) and an error code
85std::pair<IPv4Address, Errno> GetHostIPv4Address();
86
87} // namespace Network
diff --git a/src/core/network/sockets.h b/src/core/network/sockets.h
new file mode 100644
index 000000000..7bdff0fe4
--- /dev/null
+++ b/src/core/network/sockets.h
@@ -0,0 +1,94 @@
1// Copyright 2020 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 <memory>
8#include <utility>
9
10#if defined(_WIN32)
11#include <winsock.h>
12#elif !defined(__unix__)
13#error "Platform not implemented"
14#endif
15
16#include "common/common_types.h"
17#include "core/network/network.h"
18
19// TODO: C++20 Replace std::vector usages with std::span
20
21namespace Network {
22
23class Socket {
24public:
25 struct AcceptResult {
26 std::unique_ptr<Socket> socket;
27 SockAddrIn sockaddr_in;
28 };
29
30 explicit Socket() = default;
31 ~Socket();
32
33 Socket(const Socket&) = delete;
34 Socket& operator=(const Socket&) = delete;
35
36 Socket(Socket&& rhs) noexcept;
37
38 // Avoid closing sockets implicitly
39 Socket& operator=(Socket&&) noexcept = delete;
40
41 Errno Initialize(Domain domain, Type type, Protocol protocol);
42
43 Errno Close();
44
45 std::pair<AcceptResult, Errno> Accept();
46
47 Errno Connect(SockAddrIn addr_in);
48
49 std::pair<SockAddrIn, Errno> GetPeerName();
50
51 std::pair<SockAddrIn, Errno> GetSockName();
52
53 Errno Bind(SockAddrIn addr);
54
55 Errno Listen(s32 backlog);
56
57 Errno Shutdown(ShutdownHow how);
58
59 std::pair<s32, Errno> Recv(int flags, std::vector<u8>& message);
60
61 std::pair<s32, Errno> RecvFrom(int flags, std::vector<u8>& message, SockAddrIn* addr);
62
63 std::pair<s32, Errno> Send(const std::vector<u8>& message, int flags);
64
65 std::pair<s32, Errno> SendTo(u32 flags, const std::vector<u8>& message, const SockAddrIn* addr);
66
67 Errno SetLinger(bool enable, u32 linger);
68
69 Errno SetReuseAddr(bool enable);
70
71 Errno SetBroadcast(bool enable);
72
73 Errno SetSndBuf(u32 value);
74
75 Errno SetRcvBuf(u32 value);
76
77 Errno SetSndTimeo(u32 value);
78
79 Errno SetRcvTimeo(u32 value);
80
81 Errno SetNonBlock(bool enable);
82
83 bool IsOpened() const;
84
85#if defined(_WIN32)
86 SOCKET fd = INVALID_SOCKET;
87#elif defined(__unix__)
88 int fd = -1;
89#endif
90};
91
92std::pair<s32, Errno> Poll(std::vector<PollFD>& poll_fds, s32 timeout);
93
94} // namespace Network
diff --git a/src/input_common/gcadapter/gc_adapter.cpp b/src/input_common/gcadapter/gc_adapter.cpp
index 898a278a9..02d06876f 100644
--- a/src/input_common/gcadapter/gc_adapter.cpp
+++ b/src/input_common/gcadapter/gc_adapter.cpp
@@ -24,12 +24,9 @@ Adapter::Adapter() {
24 } 24 }
25 LOG_INFO(Input, "GC Adapter Initialization started"); 25 LOG_INFO(Input, "GC Adapter Initialization started");
26 26
27 current_status = NO_ADAPTER_DETECTED;
28 get_origin.fill(true);
29
30 const int init_res = libusb_init(&libusb_ctx); 27 const int init_res = libusb_init(&libusb_ctx);
31 if (init_res == LIBUSB_SUCCESS) { 28 if (init_res == LIBUSB_SUCCESS) {
32 StartScanThread(); 29 Setup();
33 } else { 30 } else {
34 LOG_ERROR(Input, "libusb could not be initialized. failed with error = {}", init_res); 31 LOG_ERROR(Input, "libusb could not be initialized. failed with error = {}", init_res);
35 } 32 }
@@ -37,9 +34,9 @@ Adapter::Adapter() {
37 34
38GCPadStatus Adapter::GetPadStatus(std::size_t port, const std::array<u8, 37>& adapter_payload) { 35GCPadStatus Adapter::GetPadStatus(std::size_t port, const std::array<u8, 37>& adapter_payload) {
39 GCPadStatus pad = {}; 36 GCPadStatus pad = {};
37 const std::size_t offset = 1 + (9 * port);
40 38
41 ControllerTypes type = ControllerTypes(adapter_payload[1 + (9 * port)] >> 4); 39 adapter_controllers_status[port] = static_cast<ControllerTypes>(adapter_payload[offset] >> 4);
42 adapter_controllers_status[port] = type;
43 40
44 static constexpr std::array<PadButton, 8> b1_buttons{ 41 static constexpr std::array<PadButton, 8> b1_buttons{
45 PadButton::PAD_BUTTON_A, PadButton::PAD_BUTTON_B, PadButton::PAD_BUTTON_X, 42 PadButton::PAD_BUTTON_A, PadButton::PAD_BUTTON_B, PadButton::PAD_BUTTON_X,
@@ -54,14 +51,19 @@ GCPadStatus Adapter::GetPadStatus(std::size_t port, const std::array<u8, 37>& ad
54 PadButton::PAD_TRIGGER_L, 51 PadButton::PAD_TRIGGER_L,
55 }; 52 };
56 53
54 static constexpr std::array<PadAxes, 6> axes{
55 PadAxes::StickX, PadAxes::StickY, PadAxes::SubstickX,
56 PadAxes::SubstickY, PadAxes::TriggerLeft, PadAxes::TriggerRight,
57 };
58
57 if (adapter_controllers_status[port] == ControllerTypes::None && !get_origin[port]) { 59 if (adapter_controllers_status[port] == ControllerTypes::None && !get_origin[port]) {
58 // Controller may have been disconnected, recalibrate if reconnected. 60 // Controller may have been disconnected, recalibrate if reconnected.
59 get_origin[port] = true; 61 get_origin[port] = true;
60 } 62 }
61 63
62 if (adapter_controllers_status[port] != ControllerTypes::None) { 64 if (adapter_controllers_status[port] != ControllerTypes::None) {
63 const u8 b1 = adapter_payload[1 + (9 * port) + 1]; 65 const u8 b1 = adapter_payload[offset + 1];
64 const u8 b2 = adapter_payload[1 + (9 * port) + 2]; 66 const u8 b2 = adapter_payload[offset + 2];
65 67
66 for (std::size_t i = 0; i < b1_buttons.size(); ++i) { 68 for (std::size_t i = 0; i < b1_buttons.size(); ++i) {
67 if ((b1 & (1U << i)) != 0) { 69 if ((b1 & (1U << i)) != 0) {
@@ -74,21 +76,13 @@ GCPadStatus Adapter::GetPadStatus(std::size_t port, const std::array<u8, 37>& ad
74 pad.button |= static_cast<u16>(b2_buttons[j]); 76 pad.button |= static_cast<u16>(b2_buttons[j]);
75 } 77 }
76 } 78 }
77 79 for (PadAxes axis : axes) {
78 pad.stick_x = adapter_payload[1 + (9 * port) + 3]; 80 const std::size_t index = static_cast<std::size_t>(axis);
79 pad.stick_y = adapter_payload[1 + (9 * port) + 4]; 81 pad.axis_values[index] = adapter_payload[offset + 3 + index];
80 pad.substick_x = adapter_payload[1 + (9 * port) + 5]; 82 }
81 pad.substick_y = adapter_payload[1 + (9 * port) + 6];
82 pad.trigger_left = adapter_payload[1 + (9 * port) + 7];
83 pad.trigger_right = adapter_payload[1 + (9 * port) + 8];
84 83
85 if (get_origin[port]) { 84 if (get_origin[port]) {
86 origin_status[port].stick_x = pad.stick_x; 85 origin_status[port].axis_values = pad.axis_values;
87 origin_status[port].stick_y = pad.stick_y;
88 origin_status[port].substick_x = pad.substick_x;
89 origin_status[port].substick_y = pad.substick_y;
90 origin_status[port].trigger_left = pad.trigger_left;
91 origin_status[port].trigger_right = pad.trigger_right;
92 get_origin[port] = false; 86 get_origin[port] = false;
93 } 87 }
94 } 88 }
@@ -101,82 +95,47 @@ void Adapter::PadToState(const GCPadStatus& pad, GCState& state) {
101 state.buttons.insert_or_assign(button_value, pad.button & button_value); 95 state.buttons.insert_or_assign(button_value, pad.button & button_value);
102 } 96 }
103 97
104 state.axes.insert_or_assign(static_cast<u8>(PadAxes::StickX), pad.stick_x); 98 for (size_t i = 0; i < pad.axis_values.size(); ++i) {
105 state.axes.insert_or_assign(static_cast<u8>(PadAxes::StickY), pad.stick_y); 99 state.axes.insert_or_assign(static_cast<u8>(i), pad.axis_values[i]);
106 state.axes.insert_or_assign(static_cast<u8>(PadAxes::SubstickX), pad.substick_x); 100 }
107 state.axes.insert_or_assign(static_cast<u8>(PadAxes::SubstickY), pad.substick_y);
108 state.axes.insert_or_assign(static_cast<u8>(PadAxes::TriggerLeft), pad.trigger_left);
109 state.axes.insert_or_assign(static_cast<u8>(PadAxes::TriggerRight), pad.trigger_right);
110} 101}
111 102
112void Adapter::Read() { 103void Adapter::Read() {
113 LOG_DEBUG(Input, "GC Adapter Read() thread started"); 104 LOG_DEBUG(Input, "GC Adapter Read() thread started");
114 105
115 int payload_size_in, payload_size_copy; 106 int payload_size;
116 std::array<u8, 37> adapter_payload; 107 std::array<u8, 37> adapter_payload;
117 std::array<u8, 37> adapter_payload_copy;
118 std::array<GCPadStatus, 4> pads; 108 std::array<GCPadStatus, 4> pads;
119 109
120 while (adapter_thread_running) { 110 while (adapter_thread_running) {
121 libusb_interrupt_transfer(usb_adapter_handle, input_endpoint, adapter_payload.data(), 111 libusb_interrupt_transfer(usb_adapter_handle, input_endpoint, adapter_payload.data(),
122 sizeof(adapter_payload), &payload_size_in, 16); 112 sizeof(adapter_payload), &payload_size, 16);
123 payload_size_copy = 0;
124 // this mutex might be redundant?
125 {
126 std::lock_guard<std::mutex> lk(s_mutex);
127 std::copy(std::begin(adapter_payload), std::end(adapter_payload),
128 std::begin(adapter_payload_copy));
129 payload_size_copy = payload_size_in;
130 }
131 113
132 if (payload_size_copy != sizeof(adapter_payload_copy) || 114 if (payload_size != sizeof(adapter_payload) || adapter_payload[0] != LIBUSB_DT_HID) {
133 adapter_payload_copy[0] != LIBUSB_DT_HID) { 115 LOG_ERROR(Input,
134 LOG_ERROR(Input, "error reading payload (size: {}, type: {:02x})", payload_size_copy, 116 "Error reading payload (size: {}, type: {:02x}) Is the adapter connected?",
135 adapter_payload_copy[0]); 117 payload_size, adapter_payload[0]);
136 adapter_thread_running = false; // error reading from adapter, stop reading. 118 adapter_thread_running = false; // error reading from adapter, stop reading.
137 break; 119 break;
138 } 120 }
139 for (std::size_t port = 0; port < pads.size(); ++port) { 121 for (std::size_t port = 0; port < pads.size(); ++port) {
140 pads[port] = GetPadStatus(port, adapter_payload_copy); 122 pads[port] = GetPadStatus(port, adapter_payload);
141 if (DeviceConnected(port) && configuring) { 123 if (DeviceConnected(port) && configuring) {
142 if (pads[port].button != 0) { 124 if (pads[port].button != 0) {
143 pad_queue[port].Push(pads[port]); 125 pad_queue[port].Push(pads[port]);
144 } 126 }
145 127
146 // Accounting for a threshold here because of some controller variance 128 // Accounting for a threshold here to ensure an intentional press
147 if (pads[port].stick_x > origin_status[port].stick_x + pads[port].THRESHOLD || 129 for (size_t i = 0; i < pads[port].axis_values.size(); ++i) {
148 pads[port].stick_x < origin_status[port].stick_x - pads[port].THRESHOLD) { 130 const u8 value = pads[port].axis_values[i];
149 pads[port].axis = GCAdapter::PadAxes::StickX; 131 const u8 origin = origin_status[port].axis_values[i];
150 pads[port].axis_value = pads[port].stick_x; 132
151 pad_queue[port].Push(pads[port]); 133 if (value > origin + pads[port].THRESHOLD ||
152 } 134 value < origin - pads[port].THRESHOLD) {
153 if (pads[port].stick_y > origin_status[port].stick_y + pads[port].THRESHOLD || 135 pads[port].axis = static_cast<PadAxes>(i);
154 pads[port].stick_y < origin_status[port].stick_y - pads[port].THRESHOLD) { 136 pads[port].axis_value = pads[port].axis_values[i];
155 pads[port].axis = GCAdapter::PadAxes::StickY; 137 pad_queue[port].Push(pads[port]);
156 pads[port].axis_value = pads[port].stick_y; 138 }
157 pad_queue[port].Push(pads[port]);
158 }
159 if (pads[port].substick_x > origin_status[port].substick_x + pads[port].THRESHOLD ||
160 pads[port].substick_x < origin_status[port].substick_x - pads[port].THRESHOLD) {
161 pads[port].axis = GCAdapter::PadAxes::SubstickX;
162 pads[port].axis_value = pads[port].substick_x;
163 pad_queue[port].Push(pads[port]);
164 }
165 if (pads[port].substick_y > origin_status[port].substick_y + pads[port].THRESHOLD ||
166 pads[port].substick_y < origin_status[port].substick_y - pads[port].THRESHOLD) {
167 pads[port].axis = GCAdapter::PadAxes::SubstickY;
168 pads[port].axis_value = pads[port].substick_y;
169 pad_queue[port].Push(pads[port]);
170 }
171 if (pads[port].trigger_left > pads[port].TRIGGER_THRESHOLD) {
172 pads[port].axis = GCAdapter::PadAxes::TriggerLeft;
173 pads[port].axis_value = pads[port].trigger_left;
174 pad_queue[port].Push(pads[port]);
175 }
176 if (pads[port].trigger_right > pads[port].TRIGGER_THRESHOLD) {
177 pads[port].axis = GCAdapter::PadAxes::TriggerRight;
178 pads[port].axis_value = pads[port].trigger_right;
179 pad_queue[port].Push(pads[port]);
180 } 139 }
181 } 140 }
182 PadToState(pads[port], state[port]); 141 PadToState(pads[port], state[port]);
@@ -185,42 +144,11 @@ void Adapter::Read() {
185 } 144 }
186} 145}
187 146
188void Adapter::ScanThreadFunc() {
189 LOG_INFO(Input, "GC Adapter scanning thread started");
190
191 while (detect_thread_running) {
192 if (usb_adapter_handle == nullptr) {
193 std::lock_guard<std::mutex> lk(initialization_mutex);
194 Setup();
195 }
196 std::this_thread::sleep_for(std::chrono::milliseconds(500));
197 }
198}
199
200void Adapter::StartScanThread() {
201 if (detect_thread_running) {
202 return;
203 }
204 if (!libusb_ctx) {
205 return;
206 }
207
208 detect_thread_running = true;
209 detect_thread = std::thread(&Adapter::ScanThreadFunc, this);
210}
211
212void Adapter::StopScanThread() {
213 detect_thread_running = false;
214 detect_thread.join();
215}
216
217void Adapter::Setup() { 147void Adapter::Setup() {
218 // Reset the error status in case the adapter gets unplugged 148 // Initialize all controllers as unplugged
219 if (current_status < 0) {
220 current_status = NO_ADAPTER_DETECTED;
221 }
222
223 adapter_controllers_status.fill(ControllerTypes::None); 149 adapter_controllers_status.fill(ControllerTypes::None);
150 // Initialize all ports to store axis origin values
151 get_origin.fill(true);
224 152
225 // pointer to list of connected usb devices 153 // pointer to list of connected usb devices
226 libusb_device** devices{}; 154 libusb_device** devices{};
@@ -229,8 +157,6 @@ void Adapter::Setup() {
229 const ssize_t device_count = libusb_get_device_list(libusb_ctx, &devices); 157 const ssize_t device_count = libusb_get_device_list(libusb_ctx, &devices);
230 if (device_count < 0) { 158 if (device_count < 0) {
231 LOG_ERROR(Input, "libusb_get_device_list failed with error: {}", device_count); 159 LOG_ERROR(Input, "libusb_get_device_list failed with error: {}", device_count);
232 detect_thread_running = false; // Stop the loop constantly checking for gc adapter
233 // TODO: For hotplug+gc adapter checkbox implementation, revert this.
234 return; 160 return;
235 } 161 }
236 162
@@ -244,9 +170,6 @@ void Adapter::Setup() {
244 } 170 }
245 libusb_free_device_list(devices, 1); 171 libusb_free_device_list(devices, 1);
246 } 172 }
247 // Break out of the ScanThreadFunc() loop that is constantly looking for the device
248 // Assumes user has GC adapter plugged in before launch to use the adapter
249 detect_thread_running = false;
250} 173}
251 174
252bool Adapter::CheckDeviceAccess(libusb_device* device) { 175bool Adapter::CheckDeviceAccess(libusb_device* device) {
@@ -331,24 +254,14 @@ void Adapter::GetGCEndpoint(libusb_device* device) {
331 sizeof(clear_payload), nullptr, 16); 254 sizeof(clear_payload), nullptr, 16);
332 255
333 adapter_thread_running = true; 256 adapter_thread_running = true;
334 current_status = ADAPTER_DETECTED;
335 adapter_input_thread = std::thread([=] { Read(); }); // Read input 257 adapter_input_thread = std::thread([=] { Read(); }); // Read input
336} 258}
337 259
338Adapter::~Adapter() { 260Adapter::~Adapter() {
339 StopScanThread();
340 Reset(); 261 Reset();
341} 262}
342 263
343void Adapter::Reset() { 264void Adapter::Reset() {
344 std::unique_lock<std::mutex> lock(initialization_mutex, std::defer_lock);
345 if (!lock.try_lock()) {
346 return;
347 }
348 if (current_status != ADAPTER_DETECTED) {
349 return;
350 }
351
352 if (adapter_thread_running) { 265 if (adapter_thread_running) {
353 adapter_thread_running = false; 266 adapter_thread_running = false;
354 } 267 }
@@ -356,7 +269,6 @@ void Adapter::Reset() {
356 269
357 adapter_controllers_status.fill(ControllerTypes::None); 270 adapter_controllers_status.fill(ControllerTypes::None);
358 get_origin.fill(true); 271 get_origin.fill(true);
359 current_status = NO_ADAPTER_DETECTED;
360 272
361 if (usb_adapter_handle) { 273 if (usb_adapter_handle) {
362 libusb_release_interface(usb_adapter_handle, 1); 274 libusb_release_interface(usb_adapter_handle, 1);
@@ -409,24 +321,7 @@ const std::array<GCState, 4>& Adapter::GetPadState() const {
409} 321}
410 322
411int Adapter::GetOriginValue(int port, int axis) const { 323int Adapter::GetOriginValue(int port, int axis) const {
412 const auto& status = origin_status[port]; 324 return origin_status[port].axis_values[axis];
413
414 switch (static_cast<PadAxes>(axis)) {
415 case PadAxes::StickX:
416 return status.stick_x;
417 case PadAxes::StickY:
418 return status.stick_y;
419 case PadAxes::SubstickX:
420 return status.substick_x;
421 case PadAxes::SubstickY:
422 return status.substick_y;
423 case PadAxes::TriggerLeft:
424 return status.trigger_left;
425 case PadAxes::TriggerRight:
426 return status.trigger_right;
427 default:
428 return 0;
429 }
430} 325}
431 326
432} // namespace GCAdapter 327} // namespace GCAdapter
diff --git a/src/input_common/gcadapter/gc_adapter.h b/src/input_common/gcadapter/gc_adapter.h
index 3586c8bda..bed81915c 100644
--- a/src/input_common/gcadapter/gc_adapter.h
+++ b/src/input_common/gcadapter/gc_adapter.h
@@ -47,24 +47,10 @@ enum class PadAxes : u8 {
47}; 47};
48 48
49struct GCPadStatus { 49struct GCPadStatus {
50 u16 button{}; // Or-ed PAD_BUTTON_* and PAD_TRIGGER_* bits 50 u16 button{}; // Or-ed PAD_BUTTON_* and PAD_TRIGGER_* bits
51 u8 stick_x{}; // 0 <= stick_x <= 255 51
52 u8 stick_y{}; // 0 <= stick_y <= 255 52 std::array<u8, 6> axis_values{}; // Triggers and sticks, following indices defined in PadAxes
53 u8 substick_x{}; // 0 <= substick_x <= 255 53 static constexpr u8 THRESHOLD = 50; // Threshold for axis press for polling
54 u8 substick_y{}; // 0 <= substick_y <= 255
55 u8 trigger_left{}; // 0 <= trigger_left <= 255
56 u8 trigger_right{}; // 0 <= trigger_right <= 255
57
58 static constexpr u8 MAIN_STICK_CENTER_X = 0x80;
59 static constexpr u8 MAIN_STICK_CENTER_Y = 0x80;
60 static constexpr u8 MAIN_STICK_RADIUS = 0x7f;
61 static constexpr u8 C_STICK_CENTER_X = 0x80;
62 static constexpr u8 C_STICK_CENTER_Y = 0x80;
63 static constexpr u8 C_STICK_RADIUS = 0x7f;
64 static constexpr u8 THRESHOLD = 10;
65
66 // 256/4, at least a quarter press to count as a press. For polling mostly
67 static constexpr u8 TRIGGER_THRESHOLD = 64;
68 54
69 u8 port{}; 55 u8 port{};
70 PadAxes axis{PadAxes::Undefined}; 56 PadAxes axis{PadAxes::Undefined};
@@ -78,11 +64,6 @@ struct GCState {
78 64
79enum class ControllerTypes { None, Wired, Wireless }; 65enum class ControllerTypes { None, Wired, Wireless };
80 66
81enum {
82 NO_ADAPTER_DETECTED = 0,
83 ADAPTER_DETECTED = 1,
84};
85
86class Adapter { 67class Adapter {
87public: 68public:
88 /// Initialize the GC Adapter capture and read sequence 69 /// Initialize the GC Adapter capture and read sequence
@@ -111,12 +92,6 @@ private:
111 void PadToState(const GCPadStatus& pad, GCState& state); 92 void PadToState(const GCPadStatus& pad, GCState& state);
112 93
113 void Read(); 94 void Read();
114 void ScanThreadFunc();
115 /// Begin scanning for the GC Adapter.
116 void StartScanThread();
117
118 /// Stop scanning for the adapter
119 void StopScanThread();
120 95
121 /// Resets status of device connected to port 96 /// Resets status of device connected to port
122 void ResetDeviceType(std::size_t port); 97 void ResetDeviceType(std::size_t port);
@@ -133,19 +108,11 @@ private:
133 /// For use in initialization, querying devices to find the adapter 108 /// For use in initialization, querying devices to find the adapter
134 void Setup(); 109 void Setup();
135 110
136 int current_status = NO_ADAPTER_DETECTED;
137 libusb_device_handle* usb_adapter_handle = nullptr; 111 libusb_device_handle* usb_adapter_handle = nullptr;
138 std::array<ControllerTypes, 4> adapter_controllers_status{};
139
140 std::mutex s_mutex;
141 112
142 std::thread adapter_input_thread; 113 std::thread adapter_input_thread;
143 bool adapter_thread_running; 114 bool adapter_thread_running;
144 115
145 std::mutex initialization_mutex;
146 std::thread detect_thread;
147 bool detect_thread_running = false;
148
149 libusb_context* libusb_ctx; 116 libusb_context* libusb_ctx;
150 117
151 u8 input_endpoint = 0; 118 u8 input_endpoint = 0;
@@ -153,10 +120,11 @@ private:
153 120
154 bool configuring = false; 121 bool configuring = false;
155 122
156 std::array<Common::SPSCQueue<GCPadStatus>, 4> pad_queue;
157 std::array<GCState, 4> state; 123 std::array<GCState, 4> state;
158 std::array<bool, 4> get_origin; 124 std::array<bool, 4> get_origin;
159 std::array<GCPadStatus, 4> origin_status; 125 std::array<GCPadStatus, 4> origin_status;
126 std::array<Common::SPSCQueue<GCPadStatus>, 4> pad_queue;
127 std::array<ControllerTypes, 4> adapter_controllers_status{};
160}; 128};
161 129
162} // namespace GCAdapter 130} // namespace GCAdapter
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index dd7ce8c99..b5dc68902 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -524,11 +524,8 @@ private:
524 void MarkRegionAsWritten(VAddr start, VAddr end) { 524 void MarkRegionAsWritten(VAddr start, VAddr end) {
525 const u64 page_end = end >> WRITE_PAGE_BIT; 525 const u64 page_end = end >> WRITE_PAGE_BIT;
526 for (u64 page_start = start >> WRITE_PAGE_BIT; page_start <= page_end; ++page_start) { 526 for (u64 page_start = start >> WRITE_PAGE_BIT; page_start <= page_end; ++page_start) {
527 auto it = written_pages.find(page_start); 527 if (const auto [it, inserted] = written_pages.emplace(page_start, 1); !inserted) {
528 if (it != written_pages.end()) { 528 ++it->second;
529 it->second = it->second + 1;
530 } else {
531 written_pages.insert_or_assign(page_start, 1);
532 } 529 }
533 } 530 }
534 } 531 }
@@ -539,7 +536,7 @@ private:
539 auto it = written_pages.find(page_start); 536 auto it = written_pages.find(page_start);
540 if (it != written_pages.end()) { 537 if (it != written_pages.end()) {
541 if (it->second > 1) { 538 if (it->second > 1) {
542 it->second = it->second - 1; 539 --it->second;
543 } else { 540 } else {
544 written_pages.erase(it); 541 written_pages.erase(it);
545 } 542 }
diff --git a/src/video_core/compatible_formats.cpp b/src/video_core/compatible_formats.cpp
index 6c426b035..b06c32c84 100644
--- a/src/video_core/compatible_formats.cpp
+++ b/src/video_core/compatible_formats.cpp
@@ -17,101 +17,94 @@ namespace {
17// https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_view.txt 17// https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_view.txt
18 18
19constexpr std::array VIEW_CLASS_128_BITS = { 19constexpr std::array VIEW_CLASS_128_BITS = {
20 PixelFormat::RGBA32F, 20 PixelFormat::R32G32B32A32_FLOAT,
21 PixelFormat::RGBA32UI, 21 PixelFormat::R32G32B32A32_UINT,
22 PixelFormat::R32G32B32A32_SINT,
22}; 23};
23// Missing formats:
24// PixelFormat::RGBA32I
25 24
26constexpr std::array VIEW_CLASS_96_BITS = { 25constexpr std::array VIEW_CLASS_96_BITS = {
27 PixelFormat::RGB32F, 26 PixelFormat::R32G32B32_FLOAT,
28}; 27};
29// Missing formats: 28// Missing formats:
30// PixelFormat::RGB32UI, 29// PixelFormat::RGB32UI,
31// PixelFormat::RGB32I, 30// PixelFormat::RGB32I,
32 31
33constexpr std::array VIEW_CLASS_64_BITS = { 32constexpr std::array VIEW_CLASS_64_BITS = {
34 PixelFormat::RGBA16F, PixelFormat::RG32F, PixelFormat::RGBA16UI, PixelFormat::RG32UI, 33 PixelFormat::R32G32_FLOAT, PixelFormat::R32G32_UINT,
35 PixelFormat::RGBA16U, PixelFormat::RGBA16F, PixelFormat::RGBA16S, 34 PixelFormat::R32G32_SINT, PixelFormat::R16G16B16A16_FLOAT,
35 PixelFormat::R16G16B16A16_UNORM, PixelFormat::R16G16B16A16_SNORM,
36 PixelFormat::R16G16B16A16_UINT, PixelFormat::R16G16B16A16_SINT,
36}; 37};
37// Missing formats:
38// PixelFormat::RGBA16I
39// PixelFormat::RG32I
40 38
41// TODO: How should we handle 48 bits? 39// TODO: How should we handle 48 bits?
42 40
43constexpr std::array VIEW_CLASS_32_BITS = { 41constexpr std::array VIEW_CLASS_32_BITS = {
44 PixelFormat::RG16F, PixelFormat::R11FG11FB10F, PixelFormat::R32F, 42 PixelFormat::R16G16_FLOAT, PixelFormat::B10G11R11_FLOAT, PixelFormat::R32_FLOAT,
45 PixelFormat::A2B10G10R10U, PixelFormat::RG16UI, PixelFormat::R32UI, 43 PixelFormat::A2B10G10R10_UNORM, PixelFormat::R16G16_UINT, PixelFormat::R32_UINT,
46 PixelFormat::RG16I, PixelFormat::R32I, PixelFormat::ABGR8U, 44 PixelFormat::R16G16_SINT, PixelFormat::R32_SINT, PixelFormat::A8B8G8R8_UNORM,
47 PixelFormat::RG16, PixelFormat::ABGR8S, PixelFormat::RG16S, 45 PixelFormat::R16G16_UNORM, PixelFormat::A8B8G8R8_SNORM, PixelFormat::R16G16_SNORM,
48 PixelFormat::RGBA8_SRGB, PixelFormat::E5B9G9R9F, PixelFormat::BGRA8, 46 PixelFormat::A8B8G8R8_SRGB, PixelFormat::E5B9G9R9_FLOAT, PixelFormat::B8G8R8A8_UNORM,
49 PixelFormat::BGRA8_SRGB, 47 PixelFormat::B8G8R8A8_SRGB, PixelFormat::A8B8G8R8_UINT, PixelFormat::A8B8G8R8_SINT,
48 PixelFormat::A2B10G10R10_UINT,
50}; 49};
51// Missing formats:
52// PixelFormat::RGBA8UI
53// PixelFormat::RGBA8I
54// PixelFormat::RGB10_A2_UI
55 50
56// TODO: How should we handle 24 bits? 51// TODO: How should we handle 24 bits?
57 52
58constexpr std::array VIEW_CLASS_16_BITS = { 53constexpr std::array VIEW_CLASS_16_BITS = {
59 PixelFormat::R16F, PixelFormat::RG8UI, PixelFormat::R16UI, PixelFormat::R16I, 54 PixelFormat::R16_FLOAT, PixelFormat::R8G8_UINT, PixelFormat::R16_UINT,
60 PixelFormat::RG8U, PixelFormat::R16U, PixelFormat::RG8S, PixelFormat::R16S, 55 PixelFormat::R16_SINT, PixelFormat::R8G8_UNORM, PixelFormat::R16_UNORM,
56 PixelFormat::R8G8_SNORM, PixelFormat::R16_SNORM, PixelFormat::R8G8_SINT,
61}; 57};
62// Missing formats:
63// PixelFormat::RG8I
64 58
65constexpr std::array VIEW_CLASS_8_BITS = { 59constexpr std::array VIEW_CLASS_8_BITS = {
66 PixelFormat::R8UI, 60 PixelFormat::R8_UINT,
67 PixelFormat::R8U, 61 PixelFormat::R8_UNORM,
62 PixelFormat::R8_SINT,
63 PixelFormat::R8_SNORM,
68}; 64};
69// Missing formats:
70// PixelFormat::R8I
71// PixelFormat::R8S
72 65
73constexpr std::array VIEW_CLASS_RGTC1_RED = { 66constexpr std::array VIEW_CLASS_RGTC1_RED = {
74 PixelFormat::DXN1, 67 PixelFormat::BC4_UNORM,
68 PixelFormat::BC4_SNORM,
75}; 69};
76// Missing formats:
77// COMPRESSED_SIGNED_RED_RGTC1
78 70
79constexpr std::array VIEW_CLASS_RGTC2_RG = { 71constexpr std::array VIEW_CLASS_RGTC2_RG = {
80 PixelFormat::DXN2UNORM, 72 PixelFormat::BC5_UNORM,
81 PixelFormat::DXN2SNORM, 73 PixelFormat::BC5_SNORM,
82}; 74};
83 75
84constexpr std::array VIEW_CLASS_BPTC_UNORM = { 76constexpr std::array VIEW_CLASS_BPTC_UNORM = {
85 PixelFormat::BC7U, 77 PixelFormat::BC7_UNORM,
86 PixelFormat::BC7U_SRGB, 78 PixelFormat::BC7_SRGB,
87}; 79};
88 80
89constexpr std::array VIEW_CLASS_BPTC_FLOAT = { 81constexpr std::array VIEW_CLASS_BPTC_FLOAT = {
90 PixelFormat::BC6H_SF16, 82 PixelFormat::BC6H_SFLOAT,
91 PixelFormat::BC6H_UF16, 83 PixelFormat::BC6H_UFLOAT,
92}; 84};
93 85
94// Compatibility table taken from Table 4.X.1 in: 86// Compatibility table taken from Table 4.X.1 in:
95// https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_copy_image.txt 87// https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_copy_image.txt
96 88
97constexpr std::array COPY_CLASS_128_BITS = { 89constexpr std::array COPY_CLASS_128_BITS = {
98 PixelFormat::RGBA32UI, PixelFormat::RGBA32F, PixelFormat::DXT23, 90 PixelFormat::R32G32B32A32_UINT, PixelFormat::R32G32B32A32_FLOAT, PixelFormat::R32G32B32A32_SINT,
99 PixelFormat::DXT23_SRGB, PixelFormat::DXT45, PixelFormat::DXT45_SRGB, 91 PixelFormat::BC2_UNORM, PixelFormat::BC2_SRGB, PixelFormat::BC3_UNORM,
100 PixelFormat::DXN2SNORM, PixelFormat::BC7U, PixelFormat::BC7U_SRGB, 92 PixelFormat::BC3_SRGB, PixelFormat::BC5_UNORM, PixelFormat::BC5_SNORM,
101 PixelFormat::BC6H_SF16, PixelFormat::BC6H_UF16, 93 PixelFormat::BC7_UNORM, PixelFormat::BC7_SRGB, PixelFormat::BC6H_SFLOAT,
94 PixelFormat::BC6H_UFLOAT,
102}; 95};
103// Missing formats: 96// Missing formats:
104// PixelFormat::RGBA32I 97// PixelFormat::RGBA32I
105// COMPRESSED_RG_RGTC2 98// COMPRESSED_RG_RGTC2
106 99
107constexpr std::array COPY_CLASS_64_BITS = { 100constexpr std::array COPY_CLASS_64_BITS = {
108 PixelFormat::RGBA16F, PixelFormat::RG32F, PixelFormat::RGBA16UI, PixelFormat::RG32UI, 101 PixelFormat::R16G16B16A16_FLOAT, PixelFormat::R16G16B16A16_UINT,
109 PixelFormat::RGBA16U, PixelFormat::RGBA16S, PixelFormat::DXT1_SRGB, PixelFormat::DXT1, 102 PixelFormat::R16G16B16A16_UNORM, PixelFormat::R16G16B16A16_SNORM,
110 103 PixelFormat::R16G16B16A16_SINT, PixelFormat::R32G32_UINT,
104 PixelFormat::R32G32_FLOAT, PixelFormat::R32G32_SINT,
105 PixelFormat::BC1_RGBA_UNORM, PixelFormat::BC1_RGBA_SRGB,
111}; 106};
112// Missing formats: 107// Missing formats:
113// PixelFormat::RGBA16I
114// PixelFormat::RG32I,
115// COMPRESSED_RGB_S3TC_DXT1_EXT 108// COMPRESSED_RGB_S3TC_DXT1_EXT
116// COMPRESSED_SRGB_S3TC_DXT1_EXT 109// COMPRESSED_SRGB_S3TC_DXT1_EXT
117// COMPRESSED_RGBA_S3TC_DXT1_EXT 110// COMPRESSED_RGBA_S3TC_DXT1_EXT
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h
index 8d04d9fd9..19a34c402 100644
--- a/src/video_core/gpu.h
+++ b/src/video_core/gpu.h
@@ -40,53 +40,61 @@ namespace Tegra {
40 40
41enum class RenderTargetFormat : u32 { 41enum class RenderTargetFormat : u32 {
42 NONE = 0x0, 42 NONE = 0x0,
43 RGBA32_FLOAT = 0xC0, 43 R32B32G32A32_FLOAT = 0xC0,
44 RGBA32_UINT = 0xC2, 44 R32G32B32A32_SINT = 0xC1,
45 RGBA16_UNORM = 0xC6, 45 R32G32B32A32_UINT = 0xC2,
46 RGBA16_SNORM = 0xC7, 46 R16G16B16A16_UNORM = 0xC6,
47 RGBA16_UINT = 0xC9, 47 R16G16B16A16_SNORM = 0xC7,
48 RGBA16_FLOAT = 0xCA, 48 R16G16B16A16_SINT = 0xC8,
49 RG32_FLOAT = 0xCB, 49 R16G16B16A16_UINT = 0xC9,
50 RG32_UINT = 0xCD, 50 R16G16B16A16_FLOAT = 0xCA,
51 RGBX16_FLOAT = 0xCE, 51 R32G32_FLOAT = 0xCB,
52 BGRA8_UNORM = 0xCF, 52 R32G32_SINT = 0xCC,
53 BGRA8_SRGB = 0xD0, 53 R32G32_UINT = 0xCD,
54 RGB10_A2_UNORM = 0xD1, 54 R16G16B16X16_FLOAT = 0xCE,
55 RGBA8_UNORM = 0xD5, 55 B8G8R8A8_UNORM = 0xCF,
56 RGBA8_SRGB = 0xD6, 56 B8G8R8A8_SRGB = 0xD0,
57 RGBA8_SNORM = 0xD7, 57 A2B10G10R10_UNORM = 0xD1,
58 RGBA8_UINT = 0xD9, 58 A2B10G10R10_UINT = 0xD2,
59 RG16_UNORM = 0xDA, 59 A8B8G8R8_UNORM = 0xD5,
60 RG16_SNORM = 0xDB, 60 A8B8G8R8_SRGB = 0xD6,
61 RG16_SINT = 0xDC, 61 A8B8G8R8_SNORM = 0xD7,
62 RG16_UINT = 0xDD, 62 A8B8G8R8_SINT = 0xD8,
63 RG16_FLOAT = 0xDE, 63 A8B8G8R8_UINT = 0xD9,
64 R11G11B10_FLOAT = 0xE0, 64 R16G16_UNORM = 0xDA,
65 R16G16_SNORM = 0xDB,
66 R16G16_SINT = 0xDC,
67 R16G16_UINT = 0xDD,
68 R16G16_FLOAT = 0xDE,
69 B10G11R11_FLOAT = 0xE0,
65 R32_SINT = 0xE3, 70 R32_SINT = 0xE3,
66 R32_UINT = 0xE4, 71 R32_UINT = 0xE4,
67 R32_FLOAT = 0xE5, 72 R32_FLOAT = 0xE5,
68 B5G6R5_UNORM = 0xE8, 73 R5G6B5_UNORM = 0xE8,
69 BGR5A1_UNORM = 0xE9, 74 A1R5G5B5_UNORM = 0xE9,
70 RG8_UNORM = 0xEA, 75 R8G8_UNORM = 0xEA,
71 RG8_SNORM = 0xEB, 76 R8G8_SNORM = 0xEB,
72 RG8_UINT = 0xED, 77 R8G8_SINT = 0xEC,
78 R8G8_UINT = 0xED,
73 R16_UNORM = 0xEE, 79 R16_UNORM = 0xEE,
74 R16_SNORM = 0xEF, 80 R16_SNORM = 0xEF,
75 R16_SINT = 0xF0, 81 R16_SINT = 0xF0,
76 R16_UINT = 0xF1, 82 R16_UINT = 0xF1,
77 R16_FLOAT = 0xF2, 83 R16_FLOAT = 0xF2,
78 R8_UNORM = 0xF3, 84 R8_UNORM = 0xF3,
85 R8_SNORM = 0xF4,
86 R8_SINT = 0xF5,
79 R8_UINT = 0xF6, 87 R8_UINT = 0xF6,
80}; 88};
81 89
82enum class DepthFormat : u32 { 90enum class DepthFormat : u32 {
83 Z32_FLOAT = 0xA, 91 D32_FLOAT = 0xA,
84 Z16_UNORM = 0x13, 92 D16_UNORM = 0x13,
85 S8_Z24_UNORM = 0x14, 93 S8_UINT_Z24_UNORM = 0x14,
86 Z24_X8_UNORM = 0x15, 94 D24X8_UNORM = 0x15,
87 Z24_S8_UNORM = 0x16, 95 D24S8_UNORM = 0x16,
88 Z24_C8_UNORM = 0x18, 96 D24C8_UNORM = 0x18,
89 Z32_S8_X24_FLOAT = 0x19, 97 D32_FLOAT_S8X24_UINT = 0x19,
90}; 98};
91 99
92struct CommandListHeader; 100struct CommandListHeader;
@@ -97,9 +105,9 @@ class DebugContext;
97 */ 105 */
98struct FramebufferConfig { 106struct FramebufferConfig {
99 enum class PixelFormat : u32 { 107 enum class PixelFormat : u32 {
100 ABGR8 = 1, 108 A8B8G8R8_UNORM = 1,
101 RGB565 = 4, 109 RGB565_UNORM = 4,
102 BGRA8 = 5, 110 B8G8R8A8_UNORM = 5,
103 }; 111 };
104 112
105 VAddr address; 113 VAddr address;
diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp
index 738c6f0c1..bf761abf2 100644
--- a/src/video_core/gpu_thread.cpp
+++ b/src/video_core/gpu_thread.cpp
@@ -44,9 +44,9 @@ static void RunThread(Core::System& system, VideoCore::RendererBase& renderer,
44 dma_pusher.DispatchCalls(); 44 dma_pusher.DispatchCalls();
45 } else if (const auto data = std::get_if<SwapBuffersCommand>(&next.data)) { 45 } else if (const auto data = std::get_if<SwapBuffersCommand>(&next.data)) {
46 renderer.SwapBuffers(data->framebuffer ? &*data->framebuffer : nullptr); 46 renderer.SwapBuffers(data->framebuffer ? &*data->framebuffer : nullptr);
47 } else if (const auto data = std::get_if<OnCommandListEndCommand>(&next.data)) { 47 } else if (std::holds_alternative<OnCommandListEndCommand>(next.data)) {
48 renderer.Rasterizer().ReleaseFences(); 48 renderer.Rasterizer().ReleaseFences();
49 } else if (const auto data = std::get_if<GPUTickCommand>(&next.data)) { 49 } else if (std::holds_alternative<GPUTickCommand>(next.data)) {
50 system.GPU().TickWork(); 50 system.GPU().TickWork();
51 } else if (const auto data = std::get_if<FlushRegionCommand>(&next.data)) { 51 } else if (const auto data = std::get_if<FlushRegionCommand>(&next.data)) {
52 renderer.Rasterizer().FlushRegion(data->addr, data->size); 52 renderer.Rasterizer().FlushRegion(data->addr, data->size);
diff --git a/src/video_core/macro/macro_jit_x64.cpp b/src/video_core/macro/macro_jit_x64.cpp
index 07292702f..c1b9e4ad9 100644
--- a/src/video_core/macro/macro_jit_x64.cpp
+++ b/src/video_core/macro/macro_jit_x64.cpp
@@ -419,7 +419,6 @@ void Tegra::MacroJITx64Impl::Optimizer_ScanFlags() {
419 419
420void MacroJITx64Impl::Compile() { 420void MacroJITx64Impl::Compile() {
421 MICROPROFILE_SCOPE(MacroJitCompile); 421 MICROPROFILE_SCOPE(MacroJitCompile);
422 bool keep_executing = true;
423 labels.fill(Xbyak::Label()); 422 labels.fill(Xbyak::Label());
424 423
425 Common::X64::ABI_PushRegistersAndAdjustStack(*this, Common::X64::ABI_ALL_CALLEE_SAVED, 8); 424 Common::X64::ABI_PushRegistersAndAdjustStack(*this, Common::X64::ABI_ALL_CALLEE_SAVED, 8);
diff --git a/src/video_core/morton.cpp b/src/video_core/morton.cpp
index 836b25c1d..9da9fb4ff 100644
--- a/src/video_core/morton.cpp
+++ b/src/video_core/morton.cpp
@@ -41,146 +41,168 @@ static void MortonCopy(u32 stride, u32 block_height, u32 height, u32 block_depth
41} 41}
42 42
43static constexpr ConversionArray morton_to_linear_fns = { 43static constexpr ConversionArray morton_to_linear_fns = {
44 MortonCopy<true, PixelFormat::ABGR8U>, 44 MortonCopy<true, PixelFormat::A8B8G8R8_UNORM>,
45 MortonCopy<true, PixelFormat::ABGR8S>, 45 MortonCopy<true, PixelFormat::A8B8G8R8_SNORM>,
46 MortonCopy<true, PixelFormat::ABGR8UI>, 46 MortonCopy<true, PixelFormat::A8B8G8R8_SINT>,
47 MortonCopy<true, PixelFormat::B5G6R5U>, 47 MortonCopy<true, PixelFormat::A8B8G8R8_UINT>,
48 MortonCopy<true, PixelFormat::A2B10G10R10U>, 48 MortonCopy<true, PixelFormat::R5G6B5_UNORM>,
49 MortonCopy<true, PixelFormat::A1B5G5R5U>, 49 MortonCopy<true, PixelFormat::B5G6R5_UNORM>,
50 MortonCopy<true, PixelFormat::R8U>, 50 MortonCopy<true, PixelFormat::A1R5G5B5_UNORM>,
51 MortonCopy<true, PixelFormat::R8UI>, 51 MortonCopy<true, PixelFormat::A2B10G10R10_UNORM>,
52 MortonCopy<true, PixelFormat::RGBA16F>, 52 MortonCopy<true, PixelFormat::A2B10G10R10_UINT>,
53 MortonCopy<true, PixelFormat::RGBA16U>, 53 MortonCopy<true, PixelFormat::A1B5G5R5_UNORM>,
54 MortonCopy<true, PixelFormat::RGBA16S>, 54 MortonCopy<true, PixelFormat::R8_UNORM>,
55 MortonCopy<true, PixelFormat::RGBA16UI>, 55 MortonCopy<true, PixelFormat::R8_SNORM>,
56 MortonCopy<true, PixelFormat::R11FG11FB10F>, 56 MortonCopy<true, PixelFormat::R8_SINT>,
57 MortonCopy<true, PixelFormat::RGBA32UI>, 57 MortonCopy<true, PixelFormat::R8_UINT>,
58 MortonCopy<true, PixelFormat::DXT1>, 58 MortonCopy<true, PixelFormat::R16G16B16A16_FLOAT>,
59 MortonCopy<true, PixelFormat::DXT23>, 59 MortonCopy<true, PixelFormat::R16G16B16A16_UNORM>,
60 MortonCopy<true, PixelFormat::DXT45>, 60 MortonCopy<true, PixelFormat::R16G16B16A16_SNORM>,
61 MortonCopy<true, PixelFormat::DXN1>, 61 MortonCopy<true, PixelFormat::R16G16B16A16_SINT>,
62 MortonCopy<true, PixelFormat::DXN2UNORM>, 62 MortonCopy<true, PixelFormat::R16G16B16A16_UINT>,
63 MortonCopy<true, PixelFormat::DXN2SNORM>, 63 MortonCopy<true, PixelFormat::B10G11R11_FLOAT>,
64 MortonCopy<true, PixelFormat::BC7U>, 64 MortonCopy<true, PixelFormat::R32G32B32A32_UINT>,
65 MortonCopy<true, PixelFormat::BC6H_UF16>, 65 MortonCopy<true, PixelFormat::BC1_RGBA_UNORM>,
66 MortonCopy<true, PixelFormat::BC6H_SF16>, 66 MortonCopy<true, PixelFormat::BC2_UNORM>,
67 MortonCopy<true, PixelFormat::ASTC_2D_4X4>, 67 MortonCopy<true, PixelFormat::BC3_UNORM>,
68 MortonCopy<true, PixelFormat::BGRA8>, 68 MortonCopy<true, PixelFormat::BC4_UNORM>,
69 MortonCopy<true, PixelFormat::RGBA32F>, 69 MortonCopy<true, PixelFormat::BC4_SNORM>,
70 MortonCopy<true, PixelFormat::RG32F>, 70 MortonCopy<true, PixelFormat::BC5_UNORM>,
71 MortonCopy<true, PixelFormat::R32F>, 71 MortonCopy<true, PixelFormat::BC5_SNORM>,
72 MortonCopy<true, PixelFormat::R16F>, 72 MortonCopy<true, PixelFormat::BC7_UNORM>,
73 MortonCopy<true, PixelFormat::R16U>, 73 MortonCopy<true, PixelFormat::BC6H_UFLOAT>,
74 MortonCopy<true, PixelFormat::R16S>, 74 MortonCopy<true, PixelFormat::BC6H_SFLOAT>,
75 MortonCopy<true, PixelFormat::R16UI>, 75 MortonCopy<true, PixelFormat::ASTC_2D_4X4_UNORM>,
76 MortonCopy<true, PixelFormat::R16I>, 76 MortonCopy<true, PixelFormat::B8G8R8A8_UNORM>,
77 MortonCopy<true, PixelFormat::RG16>, 77 MortonCopy<true, PixelFormat::R32G32B32A32_FLOAT>,
78 MortonCopy<true, PixelFormat::RG16F>, 78 MortonCopy<true, PixelFormat::R32G32B32A32_SINT>,
79 MortonCopy<true, PixelFormat::RG16UI>, 79 MortonCopy<true, PixelFormat::R32G32_FLOAT>,
80 MortonCopy<true, PixelFormat::RG16I>, 80 MortonCopy<true, PixelFormat::R32G32_SINT>,
81 MortonCopy<true, PixelFormat::RG16S>, 81 MortonCopy<true, PixelFormat::R32_FLOAT>,
82 MortonCopy<true, PixelFormat::RGB32F>, 82 MortonCopy<true, PixelFormat::R16_FLOAT>,
83 MortonCopy<true, PixelFormat::RGBA8_SRGB>, 83 MortonCopy<true, PixelFormat::R16_UNORM>,
84 MortonCopy<true, PixelFormat::RG8U>, 84 MortonCopy<true, PixelFormat::R16_SNORM>,
85 MortonCopy<true, PixelFormat::RG8S>, 85 MortonCopy<true, PixelFormat::R16_UINT>,
86 MortonCopy<true, PixelFormat::RG8UI>, 86 MortonCopy<true, PixelFormat::R16_SINT>,
87 MortonCopy<true, PixelFormat::RG32UI>, 87 MortonCopy<true, PixelFormat::R16G16_UNORM>,
88 MortonCopy<true, PixelFormat::RGBX16F>, 88 MortonCopy<true, PixelFormat::R16G16_FLOAT>,
89 MortonCopy<true, PixelFormat::R32UI>, 89 MortonCopy<true, PixelFormat::R16G16_UINT>,
90 MortonCopy<true, PixelFormat::R32I>, 90 MortonCopy<true, PixelFormat::R16G16_SINT>,
91 MortonCopy<true, PixelFormat::ASTC_2D_8X8>, 91 MortonCopy<true, PixelFormat::R16G16_SNORM>,
92 MortonCopy<true, PixelFormat::ASTC_2D_8X5>, 92 MortonCopy<true, PixelFormat::R32G32B32_FLOAT>,
93 MortonCopy<true, PixelFormat::ASTC_2D_5X4>, 93 MortonCopy<true, PixelFormat::A8B8G8R8_SRGB>,
94 MortonCopy<true, PixelFormat::BGRA8_SRGB>, 94 MortonCopy<true, PixelFormat::R8G8_UNORM>,
95 MortonCopy<true, PixelFormat::DXT1_SRGB>, 95 MortonCopy<true, PixelFormat::R8G8_SNORM>,
96 MortonCopy<true, PixelFormat::DXT23_SRGB>, 96 MortonCopy<true, PixelFormat::R8G8_SINT>,
97 MortonCopy<true, PixelFormat::DXT45_SRGB>, 97 MortonCopy<true, PixelFormat::R8G8_UINT>,
98 MortonCopy<true, PixelFormat::BC7U_SRGB>, 98 MortonCopy<true, PixelFormat::R32G32_UINT>,
99 MortonCopy<true, PixelFormat::R4G4B4A4U>, 99 MortonCopy<true, PixelFormat::R16G16B16X16_FLOAT>,
100 MortonCopy<true, PixelFormat::R32_UINT>,
101 MortonCopy<true, PixelFormat::R32_SINT>,
102 MortonCopy<true, PixelFormat::ASTC_2D_8X8_UNORM>,
103 MortonCopy<true, PixelFormat::ASTC_2D_8X5_UNORM>,
104 MortonCopy<true, PixelFormat::ASTC_2D_5X4_UNORM>,
105 MortonCopy<true, PixelFormat::B8G8R8A8_SRGB>,
106 MortonCopy<true, PixelFormat::BC1_RGBA_SRGB>,
107 MortonCopy<true, PixelFormat::BC2_SRGB>,
108 MortonCopy<true, PixelFormat::BC3_SRGB>,
109 MortonCopy<true, PixelFormat::BC7_SRGB>,
110 MortonCopy<true, PixelFormat::A4B4G4R4_UNORM>,
100 MortonCopy<true, PixelFormat::ASTC_2D_4X4_SRGB>, 111 MortonCopy<true, PixelFormat::ASTC_2D_4X4_SRGB>,
101 MortonCopy<true, PixelFormat::ASTC_2D_8X8_SRGB>, 112 MortonCopy<true, PixelFormat::ASTC_2D_8X8_SRGB>,
102 MortonCopy<true, PixelFormat::ASTC_2D_8X5_SRGB>, 113 MortonCopy<true, PixelFormat::ASTC_2D_8X5_SRGB>,
103 MortonCopy<true, PixelFormat::ASTC_2D_5X4_SRGB>, 114 MortonCopy<true, PixelFormat::ASTC_2D_5X4_SRGB>,
104 MortonCopy<true, PixelFormat::ASTC_2D_5X5>, 115 MortonCopy<true, PixelFormat::ASTC_2D_5X5_UNORM>,
105 MortonCopy<true, PixelFormat::ASTC_2D_5X5_SRGB>, 116 MortonCopy<true, PixelFormat::ASTC_2D_5X5_SRGB>,
106 MortonCopy<true, PixelFormat::ASTC_2D_10X8>, 117 MortonCopy<true, PixelFormat::ASTC_2D_10X8_UNORM>,
107 MortonCopy<true, PixelFormat::ASTC_2D_10X8_SRGB>, 118 MortonCopy<true, PixelFormat::ASTC_2D_10X8_SRGB>,
108 MortonCopy<true, PixelFormat::ASTC_2D_6X6>, 119 MortonCopy<true, PixelFormat::ASTC_2D_6X6_UNORM>,
109 MortonCopy<true, PixelFormat::ASTC_2D_6X6_SRGB>, 120 MortonCopy<true, PixelFormat::ASTC_2D_6X6_SRGB>,
110 MortonCopy<true, PixelFormat::ASTC_2D_10X10>, 121 MortonCopy<true, PixelFormat::ASTC_2D_10X10_UNORM>,
111 MortonCopy<true, PixelFormat::ASTC_2D_10X10_SRGB>, 122 MortonCopy<true, PixelFormat::ASTC_2D_10X10_SRGB>,
112 MortonCopy<true, PixelFormat::ASTC_2D_12X12>, 123 MortonCopy<true, PixelFormat::ASTC_2D_12X12_UNORM>,
113 MortonCopy<true, PixelFormat::ASTC_2D_12X12_SRGB>, 124 MortonCopy<true, PixelFormat::ASTC_2D_12X12_SRGB>,
114 MortonCopy<true, PixelFormat::ASTC_2D_8X6>, 125 MortonCopy<true, PixelFormat::ASTC_2D_8X6_UNORM>,
115 MortonCopy<true, PixelFormat::ASTC_2D_8X6_SRGB>, 126 MortonCopy<true, PixelFormat::ASTC_2D_8X6_SRGB>,
116 MortonCopy<true, PixelFormat::ASTC_2D_6X5>, 127 MortonCopy<true, PixelFormat::ASTC_2D_6X5_UNORM>,
117 MortonCopy<true, PixelFormat::ASTC_2D_6X5_SRGB>, 128 MortonCopy<true, PixelFormat::ASTC_2D_6X5_SRGB>,
118 MortonCopy<true, PixelFormat::E5B9G9R9F>, 129 MortonCopy<true, PixelFormat::E5B9G9R9_FLOAT>,
119 MortonCopy<true, PixelFormat::Z32F>, 130 MortonCopy<true, PixelFormat::D32_FLOAT>,
120 MortonCopy<true, PixelFormat::Z16>, 131 MortonCopy<true, PixelFormat::D16_UNORM>,
121 MortonCopy<true, PixelFormat::Z24S8>, 132 MortonCopy<true, PixelFormat::D24_UNORM_S8_UINT>,
122 MortonCopy<true, PixelFormat::S8Z24>, 133 MortonCopy<true, PixelFormat::S8_UINT_D24_UNORM>,
123 MortonCopy<true, PixelFormat::Z32FS8>, 134 MortonCopy<true, PixelFormat::D32_FLOAT_S8_UINT>,
124}; 135};
125 136
126static constexpr ConversionArray linear_to_morton_fns = { 137static constexpr ConversionArray linear_to_morton_fns = {
127 MortonCopy<false, PixelFormat::ABGR8U>, 138 MortonCopy<false, PixelFormat::A8B8G8R8_UNORM>,
128 MortonCopy<false, PixelFormat::ABGR8S>, 139 MortonCopy<false, PixelFormat::A8B8G8R8_SNORM>,
129 MortonCopy<false, PixelFormat::ABGR8UI>, 140 MortonCopy<false, PixelFormat::A8B8G8R8_SINT>,
130 MortonCopy<false, PixelFormat::B5G6R5U>, 141 MortonCopy<false, PixelFormat::A8B8G8R8_UINT>,
131 MortonCopy<false, PixelFormat::A2B10G10R10U>, 142 MortonCopy<false, PixelFormat::R5G6B5_UNORM>,
132 MortonCopy<false, PixelFormat::A1B5G5R5U>, 143 MortonCopy<false, PixelFormat::B5G6R5_UNORM>,
133 MortonCopy<false, PixelFormat::R8U>, 144 MortonCopy<false, PixelFormat::A1R5G5B5_UNORM>,
134 MortonCopy<false, PixelFormat::R8UI>, 145 MortonCopy<false, PixelFormat::A2B10G10R10_UNORM>,
135 MortonCopy<false, PixelFormat::RGBA16F>, 146 MortonCopy<false, PixelFormat::A2B10G10R10_UINT>,
136 MortonCopy<false, PixelFormat::RGBA16S>, 147 MortonCopy<false, PixelFormat::A1B5G5R5_UNORM>,
137 MortonCopy<false, PixelFormat::RGBA16U>, 148 MortonCopy<false, PixelFormat::R8_UNORM>,
138 MortonCopy<false, PixelFormat::RGBA16UI>, 149 MortonCopy<false, PixelFormat::R8_SNORM>,
139 MortonCopy<false, PixelFormat::R11FG11FB10F>, 150 MortonCopy<false, PixelFormat::R8_SINT>,
140 MortonCopy<false, PixelFormat::RGBA32UI>, 151 MortonCopy<false, PixelFormat::R8_UINT>,
141 MortonCopy<false, PixelFormat::DXT1>, 152 MortonCopy<false, PixelFormat::R16G16B16A16_FLOAT>,
142 MortonCopy<false, PixelFormat::DXT23>, 153 MortonCopy<false, PixelFormat::R16G16B16A16_SNORM>,
143 MortonCopy<false, PixelFormat::DXT45>, 154 MortonCopy<false, PixelFormat::R16G16B16A16_SINT>,
144 MortonCopy<false, PixelFormat::DXN1>, 155 MortonCopy<false, PixelFormat::R16G16B16A16_UNORM>,
145 MortonCopy<false, PixelFormat::DXN2UNORM>, 156 MortonCopy<false, PixelFormat::R16G16B16A16_UINT>,
146 MortonCopy<false, PixelFormat::DXN2SNORM>, 157 MortonCopy<false, PixelFormat::B10G11R11_FLOAT>,
147 MortonCopy<false, PixelFormat::BC7U>, 158 MortonCopy<false, PixelFormat::R32G32B32A32_UINT>,
148 MortonCopy<false, PixelFormat::BC6H_UF16>, 159 MortonCopy<false, PixelFormat::BC1_RGBA_UNORM>,
149 MortonCopy<false, PixelFormat::BC6H_SF16>, 160 MortonCopy<false, PixelFormat::BC2_UNORM>,
161 MortonCopy<false, PixelFormat::BC3_UNORM>,
162 MortonCopy<false, PixelFormat::BC4_UNORM>,
163 MortonCopy<false, PixelFormat::BC4_SNORM>,
164 MortonCopy<false, PixelFormat::BC5_UNORM>,
165 MortonCopy<false, PixelFormat::BC5_SNORM>,
166 MortonCopy<false, PixelFormat::BC7_UNORM>,
167 MortonCopy<false, PixelFormat::BC6H_UFLOAT>,
168 MortonCopy<false, PixelFormat::BC6H_SFLOAT>,
150 // TODO(Subv): Swizzling ASTC formats are not supported 169 // TODO(Subv): Swizzling ASTC formats are not supported
151 nullptr, 170 nullptr,
152 MortonCopy<false, PixelFormat::BGRA8>, 171 MortonCopy<false, PixelFormat::B8G8R8A8_UNORM>,
153 MortonCopy<false, PixelFormat::RGBA32F>, 172 MortonCopy<false, PixelFormat::R32G32B32A32_FLOAT>,
154 MortonCopy<false, PixelFormat::RG32F>, 173 MortonCopy<false, PixelFormat::R32G32B32A32_SINT>,
155 MortonCopy<false, PixelFormat::R32F>, 174 MortonCopy<false, PixelFormat::R32G32_FLOAT>,
156 MortonCopy<false, PixelFormat::R16F>, 175 MortonCopy<false, PixelFormat::R32G32_SINT>,
157 MortonCopy<false, PixelFormat::R16U>, 176 MortonCopy<false, PixelFormat::R32_FLOAT>,
158 MortonCopy<false, PixelFormat::R16S>, 177 MortonCopy<false, PixelFormat::R16_FLOAT>,
159 MortonCopy<false, PixelFormat::R16UI>, 178 MortonCopy<false, PixelFormat::R16_UNORM>,
160 MortonCopy<false, PixelFormat::R16I>, 179 MortonCopy<false, PixelFormat::R16_SNORM>,
161 MortonCopy<false, PixelFormat::RG16>, 180 MortonCopy<false, PixelFormat::R16_UINT>,
162 MortonCopy<false, PixelFormat::RG16F>, 181 MortonCopy<false, PixelFormat::R16_SINT>,
163 MortonCopy<false, PixelFormat::RG16UI>, 182 MortonCopy<false, PixelFormat::R16G16_UNORM>,
164 MortonCopy<false, PixelFormat::RG16I>, 183 MortonCopy<false, PixelFormat::R16G16_FLOAT>,
165 MortonCopy<false, PixelFormat::RG16S>, 184 MortonCopy<false, PixelFormat::R16G16_UINT>,
166 MortonCopy<false, PixelFormat::RGB32F>, 185 MortonCopy<false, PixelFormat::R16G16_SINT>,
167 MortonCopy<false, PixelFormat::RGBA8_SRGB>, 186 MortonCopy<false, PixelFormat::R16G16_SNORM>,
168 MortonCopy<false, PixelFormat::RG8U>, 187 MortonCopy<false, PixelFormat::R32G32B32_FLOAT>,
169 MortonCopy<false, PixelFormat::RG8S>, 188 MortonCopy<false, PixelFormat::A8B8G8R8_SRGB>,
170 MortonCopy<false, PixelFormat::RG8UI>, 189 MortonCopy<false, PixelFormat::R8G8_UNORM>,
171 MortonCopy<false, PixelFormat::RG32UI>, 190 MortonCopy<false, PixelFormat::R8G8_SNORM>,
172 MortonCopy<false, PixelFormat::RGBX16F>, 191 MortonCopy<false, PixelFormat::R8G8_SINT>,
173 MortonCopy<false, PixelFormat::R32UI>, 192 MortonCopy<false, PixelFormat::R8G8_UINT>,
174 MortonCopy<false, PixelFormat::R32I>, 193 MortonCopy<false, PixelFormat::R32G32_UINT>,
194 MortonCopy<false, PixelFormat::R16G16B16X16_FLOAT>,
195 MortonCopy<false, PixelFormat::R32_UINT>,
196 MortonCopy<false, PixelFormat::R32_SINT>,
175 nullptr, 197 nullptr,
176 nullptr, 198 nullptr,
177 nullptr, 199 nullptr,
178 MortonCopy<false, PixelFormat::BGRA8_SRGB>, 200 MortonCopy<false, PixelFormat::B8G8R8A8_SRGB>,
179 MortonCopy<false, PixelFormat::DXT1_SRGB>, 201 MortonCopy<false, PixelFormat::BC1_RGBA_SRGB>,
180 MortonCopy<false, PixelFormat::DXT23_SRGB>, 202 MortonCopy<false, PixelFormat::BC2_SRGB>,
181 MortonCopy<false, PixelFormat::DXT45_SRGB>, 203 MortonCopy<false, PixelFormat::BC3_SRGB>,
182 MortonCopy<false, PixelFormat::BC7U_SRGB>, 204 MortonCopy<false, PixelFormat::BC7_SRGB>,
183 MortonCopy<false, PixelFormat::R4G4B4A4U>, 205 MortonCopy<false, PixelFormat::A4B4G4R4_UNORM>,
184 nullptr, 206 nullptr,
185 nullptr, 207 nullptr,
186 nullptr, 208 nullptr,
@@ -199,12 +221,12 @@ static constexpr ConversionArray linear_to_morton_fns = {
199 nullptr, 221 nullptr,
200 nullptr, 222 nullptr,
201 nullptr, 223 nullptr,
202 MortonCopy<false, PixelFormat::E5B9G9R9F>, 224 MortonCopy<false, PixelFormat::E5B9G9R9_FLOAT>,
203 MortonCopy<false, PixelFormat::Z32F>, 225 MortonCopy<false, PixelFormat::D32_FLOAT>,
204 MortonCopy<false, PixelFormat::Z16>, 226 MortonCopy<false, PixelFormat::D16_UNORM>,
205 MortonCopy<false, PixelFormat::Z24S8>, 227 MortonCopy<false, PixelFormat::D24_UNORM_S8_UINT>,
206 MortonCopy<false, PixelFormat::S8Z24>, 228 MortonCopy<false, PixelFormat::S8_UINT_D24_UNORM>,
207 MortonCopy<false, PixelFormat::Z32FS8>, 229 MortonCopy<false, PixelFormat::D32_FLOAT_S8_UINT>,
208}; 230};
209 231
210static MortonCopyFn GetSwizzleFunction(MortonSwizzleMode mode, Surface::PixelFormat format) { 232static MortonCopyFn GetSwizzleFunction(MortonSwizzleMode mode, Surface::PixelFormat format) {
diff --git a/src/video_core/renderer_opengl/gl_arb_decompiler.cpp b/src/video_core/renderer_opengl/gl_arb_decompiler.cpp
index eb5158407..b7e9ed2e9 100644
--- a/src/video_core/renderer_opengl/gl_arb_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_arb_decompiler.cpp
@@ -185,10 +185,6 @@ std::string TextureType(const MetaTexture& meta) {
185 return type; 185 return type;
186} 186}
187 187
188std::string GlobalMemoryName(const GlobalMemoryBase& base) {
189 return fmt::format("gmem{}_{}", base.cbuf_index, base.cbuf_offset);
190}
191
192class ARBDecompiler final { 188class ARBDecompiler final {
193public: 189public:
194 explicit ARBDecompiler(const Device& device, const ShaderIR& ir, const Registry& registry, 190 explicit ARBDecompiler(const Device& device, const ShaderIR& ir, const Registry& registry,
@@ -199,6 +195,8 @@ public:
199 } 195 }
200 196
201private: 197private:
198 void DefineGlobalMemory();
199
202 void DeclareHeader(); 200 void DeclareHeader();
203 void DeclareVertex(); 201 void DeclareVertex();
204 void DeclareGeometry(); 202 void DeclareGeometry();
@@ -228,6 +226,7 @@ private:
228 226
229 std::pair<std::string, std::size_t> BuildCoords(Operation); 227 std::pair<std::string, std::size_t> BuildCoords(Operation);
230 std::string BuildAoffi(Operation); 228 std::string BuildAoffi(Operation);
229 std::string GlobalMemoryPointer(const GmemNode& gmem);
231 void Exit(); 230 void Exit();
232 231
233 std::string Assign(Operation); 232 std::string Assign(Operation);
@@ -378,10 +377,8 @@ private:
378 std::string address; 377 std::string address;
379 std::string_view opname; 378 std::string_view opname;
380 if (const auto gmem = std::get_if<GmemNode>(&*operation[0])) { 379 if (const auto gmem = std::get_if<GmemNode>(&*operation[0])) {
381 AddLine("SUB.U {}, {}, {};", temporary, Visit(gmem->GetRealAddress()), 380 address = GlobalMemoryPointer(*gmem);
382 Visit(gmem->GetBaseAddress())); 381 opname = "ATOM";
383 address = fmt::format("{}[{}]", GlobalMemoryName(gmem->GetDescriptor()), temporary);
384 opname = "ATOMB";
385 } else if (const auto smem = std::get_if<SmemNode>(&*operation[0])) { 382 } else if (const auto smem = std::get_if<SmemNode>(&*operation[0])) {
386 address = fmt::format("shared_mem[{}]", Visit(smem->GetAddress())); 383 address = fmt::format("shared_mem[{}]", Visit(smem->GetAddress()));
387 opname = "ATOMS"; 384 opname = "ATOMS";
@@ -456,9 +453,13 @@ private:
456 shader_source += '\n'; 453 shader_source += '\n';
457 } 454 }
458 455
459 std::string AllocTemporary() { 456 std::string AllocLongVectorTemporary() {
460 max_temporaries = std::max(max_temporaries, num_temporaries + 1); 457 max_long_temporaries = std::max(max_long_temporaries, num_long_temporaries + 1);
461 return fmt::format("T{}.x", num_temporaries++); 458 return fmt::format("L{}", num_long_temporaries++);
459 }
460
461 std::string AllocLongTemporary() {
462 return fmt::format("{}.x", AllocLongVectorTemporary());
462 } 463 }
463 464
464 std::string AllocVectorTemporary() { 465 std::string AllocVectorTemporary() {
@@ -466,8 +467,13 @@ private:
466 return fmt::format("T{}", num_temporaries++); 467 return fmt::format("T{}", num_temporaries++);
467 } 468 }
468 469
470 std::string AllocTemporary() {
471 return fmt::format("{}.x", AllocVectorTemporary());
472 }
473
469 void ResetTemporaries() noexcept { 474 void ResetTemporaries() noexcept {
470 num_temporaries = 0; 475 num_temporaries = 0;
476 num_long_temporaries = 0;
471 } 477 }
472 478
473 const Device& device; 479 const Device& device;
@@ -478,6 +484,11 @@ private:
478 std::size_t num_temporaries = 0; 484 std::size_t num_temporaries = 0;
479 std::size_t max_temporaries = 0; 485 std::size_t max_temporaries = 0;
480 486
487 std::size_t num_long_temporaries = 0;
488 std::size_t max_long_temporaries = 0;
489
490 std::map<GlobalMemoryBase, u32> global_memory_names;
491
481 std::string shader_source; 492 std::string shader_source;
482 493
483 static constexpr std::string_view ADD_F32 = "ADD.F32"; 494 static constexpr std::string_view ADD_F32 = "ADD.F32";
@@ -784,6 +795,8 @@ private:
784ARBDecompiler::ARBDecompiler(const Device& device, const ShaderIR& ir, const Registry& registry, 795ARBDecompiler::ARBDecompiler(const Device& device, const ShaderIR& ir, const Registry& registry,
785 ShaderType stage, std::string_view identifier) 796 ShaderType stage, std::string_view identifier)
786 : device{device}, ir{ir}, registry{registry}, stage{stage} { 797 : device{device}, ir{ir}, registry{registry}, stage{stage} {
798 DefineGlobalMemory();
799
787 AddLine("TEMP RC;"); 800 AddLine("TEMP RC;");
788 AddLine("TEMP FSWZA[4];"); 801 AddLine("TEMP FSWZA[4];");
789 AddLine("TEMP FSWZB[4];"); 802 AddLine("TEMP FSWZB[4];");
@@ -829,12 +842,20 @@ std::string_view HeaderStageName(ShaderType stage) {
829 } 842 }
830} 843}
831 844
845void ARBDecompiler::DefineGlobalMemory() {
846 u32 binding = 0;
847 for (const auto& pair : ir.GetGlobalMemory()) {
848 const GlobalMemoryBase base = pair.first;
849 global_memory_names.emplace(base, binding);
850 ++binding;
851 }
852}
853
832void ARBDecompiler::DeclareHeader() { 854void ARBDecompiler::DeclareHeader() {
833 AddLine("!!NV{}5.0", HeaderStageName(stage)); 855 AddLine("!!NV{}5.0", HeaderStageName(stage));
834 // Enabling this allows us to cheat on some instructions like TXL with SHADOWARRAY2D 856 // Enabling this allows us to cheat on some instructions like TXL with SHADOWARRAY2D
835 AddLine("OPTION NV_internal;"); 857 AddLine("OPTION NV_internal;");
836 AddLine("OPTION NV_gpu_program_fp64;"); 858 AddLine("OPTION NV_gpu_program_fp64;");
837 AddLine("OPTION NV_shader_storage_buffer;");
838 AddLine("OPTION NV_shader_thread_group;"); 859 AddLine("OPTION NV_shader_thread_group;");
839 if (ir.UsesWarps() && device.HasWarpIntrinsics()) { 860 if (ir.UsesWarps() && device.HasWarpIntrinsics()) {
840 AddLine("OPTION NV_shader_thread_shuffle;"); 861 AddLine("OPTION NV_shader_thread_shuffle;");
@@ -892,11 +913,19 @@ void ARBDecompiler::DeclareCompute() {
892 const ComputeInfo& info = registry.GetComputeInfo(); 913 const ComputeInfo& info = registry.GetComputeInfo();
893 AddLine("GROUP_SIZE {} {} {};", info.workgroup_size[0], info.workgroup_size[1], 914 AddLine("GROUP_SIZE {} {} {};", info.workgroup_size[0], info.workgroup_size[1],
894 info.workgroup_size[2]); 915 info.workgroup_size[2]);
895 if (info.shared_memory_size_in_words > 0) { 916 if (info.shared_memory_size_in_words == 0) {
896 const u32 size_in_bytes = info.shared_memory_size_in_words * 4; 917 return;
897 AddLine("SHARED_MEMORY {};", size_in_bytes); 918 }
898 AddLine("SHARED shared_mem[] = {{program.sharedmem}};"); 919 const u32 limit = device.GetMaxComputeSharedMemorySize();
920 u32 size_in_bytes = info.shared_memory_size_in_words * 4;
921 if (size_in_bytes > limit) {
922 LOG_ERROR(Render_OpenGL, "Shared memory size {} is clamped to host's limit {}",
923 size_in_bytes, limit);
924 size_in_bytes = limit;
899 } 925 }
926
927 AddLine("SHARED_MEMORY {};", size_in_bytes);
928 AddLine("SHARED shared_mem[] = {{program.sharedmem}};");
900} 929}
901 930
902void ARBDecompiler::DeclareInputAttributes() { 931void ARBDecompiler::DeclareInputAttributes() {
@@ -951,11 +980,10 @@ void ARBDecompiler::DeclareLocalMemory() {
951} 980}
952 981
953void ARBDecompiler::DeclareGlobalMemory() { 982void ARBDecompiler::DeclareGlobalMemory() {
954 u32 binding = 0; // device.GetBaseBindings(stage).shader_storage_buffer; 983 const std::size_t num_entries = ir.GetGlobalMemory().size();
955 for (const auto& pair : ir.GetGlobalMemory()) { 984 if (num_entries > 0) {
956 const auto& base = pair.first; 985 const std::size_t num_vectors = Common::AlignUp(num_entries, 2) / 2;
957 AddLine("STORAGE {}[] = {{ program.storage[{}] }};", GlobalMemoryName(base), binding); 986 AddLine("PARAM c[{}] = {{ program.local[0..{}] }};", num_vectors, num_vectors - 1);
958 ++binding;
959 } 987 }
960} 988}
961 989
@@ -977,6 +1005,9 @@ void ARBDecompiler::DeclareTemporaries() {
977 for (std::size_t i = 0; i < max_temporaries; ++i) { 1005 for (std::size_t i = 0; i < max_temporaries; ++i) {
978 AddLine("TEMP T{};", i); 1006 AddLine("TEMP T{};", i);
979 } 1007 }
1008 for (std::size_t i = 0; i < max_long_temporaries; ++i) {
1009 AddLine("LONG TEMP L{};", i);
1010 }
980} 1011}
981 1012
982void ARBDecompiler::DeclarePredicates() { 1013void ARBDecompiler::DeclarePredicates() {
@@ -1260,13 +1291,6 @@ std::string ARBDecompiler::Visit(const Node& node) {
1260 return "{0, 0, 0, 0}.x"; 1291 return "{0, 0, 0, 0}.x";
1261 } 1292 }
1262 1293
1263 const auto buffer_index = [this, &abuf]() -> std::string {
1264 if (stage != ShaderType::Geometry) {
1265 return "";
1266 }
1267 return fmt::format("[{}]", Visit(abuf->GetBuffer()));
1268 };
1269
1270 const Attribute::Index index = abuf->GetIndex(); 1294 const Attribute::Index index = abuf->GetIndex();
1271 const u32 element = abuf->GetElement(); 1295 const u32 element = abuf->GetElement();
1272 const char swizzle = Swizzle(element); 1296 const char swizzle = Swizzle(element);
@@ -1339,10 +1363,7 @@ std::string ARBDecompiler::Visit(const Node& node) {
1339 1363
1340 if (const auto gmem = std::get_if<GmemNode>(&*node)) { 1364 if (const auto gmem = std::get_if<GmemNode>(&*node)) {
1341 std::string temporary = AllocTemporary(); 1365 std::string temporary = AllocTemporary();
1342 AddLine("SUB.U {}, {}, {};", temporary, Visit(gmem->GetRealAddress()), 1366 AddLine("LOAD.U32 {}, {};", temporary, GlobalMemoryPointer(*gmem));
1343 Visit(gmem->GetBaseAddress()));
1344 AddLine("LDB.U32 {}, {}[{}];", temporary, GlobalMemoryName(gmem->GetDescriptor()),
1345 temporary);
1346 return temporary; 1367 return temporary;
1347 } 1368 }
1348 1369
@@ -1375,7 +1396,7 @@ std::string ARBDecompiler::Visit(const Node& node) {
1375 return {}; 1396 return {};
1376 } 1397 }
1377 1398
1378 if (const auto cmt = std::get_if<CommentNode>(&*node)) { 1399 if ([[maybe_unused]] const auto cmt = std::get_if<CommentNode>(&*node)) {
1379 // Uncommenting this will generate invalid code. GLASM lacks comments. 1400 // Uncommenting this will generate invalid code. GLASM lacks comments.
1380 // AddLine("// {}", cmt->GetText()); 1401 // AddLine("// {}", cmt->GetText());
1381 return {}; 1402 return {};
@@ -1419,6 +1440,22 @@ std::string ARBDecompiler::BuildAoffi(Operation operation) {
1419 return fmt::format(", offset({})", temporary); 1440 return fmt::format(", offset({})", temporary);
1420} 1441}
1421 1442
1443std::string ARBDecompiler::GlobalMemoryPointer(const GmemNode& gmem) {
1444 const u32 binding = global_memory_names.at(gmem.GetDescriptor());
1445 const char result_swizzle = binding % 2 == 0 ? 'x' : 'y';
1446
1447 const std::string pointer = AllocLongVectorTemporary();
1448 std::string temporary = AllocTemporary();
1449
1450 const u32 local_index = binding / 2;
1451 AddLine("PK64.U {}, c[{}];", pointer, local_index);
1452 AddLine("SUB.U {}, {}, {};", temporary, Visit(gmem.GetRealAddress()),
1453 Visit(gmem.GetBaseAddress()));
1454 AddLine("CVT.U64.U32 {}.z, {};", pointer, temporary);
1455 AddLine("ADD.U64 {}.x, {}.{}, {}.z;", pointer, pointer, result_swizzle, pointer);
1456 return fmt::format("{}.x", pointer);
1457}
1458
1422void ARBDecompiler::Exit() { 1459void ARBDecompiler::Exit() {
1423 if (stage != ShaderType::Fragment) { 1460 if (stage != ShaderType::Fragment) {
1424 AddLine("RET;"); 1461 AddLine("RET;");
@@ -1515,11 +1552,7 @@ std::string ARBDecompiler::Assign(Operation operation) {
1515 ResetTemporaries(); 1552 ResetTemporaries();
1516 return {}; 1553 return {};
1517 } else if (const auto gmem = std::get_if<GmemNode>(&*dest)) { 1554 } else if (const auto gmem = std::get_if<GmemNode>(&*dest)) {
1518 const std::string temporary = AllocTemporary(); 1555 AddLine("STORE.U32 {}, {};", Visit(src), GlobalMemoryPointer(*gmem));
1519 AddLine("SUB.U {}, {}, {};", temporary, Visit(gmem->GetRealAddress()),
1520 Visit(gmem->GetBaseAddress()));
1521 AddLine("STB.U32 {}, {}[{}];", Visit(src), GlobalMemoryName(gmem->GetDescriptor()),
1522 temporary);
1523 ResetTemporaries(); 1556 ResetTemporaries();
1524 return {}; 1557 return {};
1525 } else { 1558 } else {
@@ -1671,7 +1704,7 @@ std::string ARBDecompiler::HCastFloat(Operation operation) {
1671} 1704}
1672 1705
1673std::string ARBDecompiler::HUnpack(Operation operation) { 1706std::string ARBDecompiler::HUnpack(Operation operation) {
1674 const std::string operand = Visit(operation[0]); 1707 std::string operand = Visit(operation[0]);
1675 switch (std::get<Tegra::Shader::HalfType>(operation.GetMeta())) { 1708 switch (std::get<Tegra::Shader::HalfType>(operation.GetMeta())) {
1676 case Tegra::Shader::HalfType::H0_H1: 1709 case Tegra::Shader::HalfType::H0_H1:
1677 return operand; 1710 return operand;
@@ -2021,7 +2054,7 @@ std::string ARBDecompiler::InvocationId(Operation) {
2021 2054
2022std::string ARBDecompiler::YNegate(Operation) { 2055std::string ARBDecompiler::YNegate(Operation) {
2023 LOG_WARNING(Render_OpenGL, "(STUBBED)"); 2056 LOG_WARNING(Render_OpenGL, "(STUBBED)");
2024 const std::string temporary = AllocTemporary(); 2057 std::string temporary = AllocTemporary();
2025 AddLine("MOV.F {}, 1;", temporary); 2058 AddLine("MOV.F {}, 1;", temporary);
2026 return temporary; 2059 return temporary;
2027} 2060}
@@ -2044,10 +2077,6 @@ std::string ARBDecompiler::ShuffleIndexed(Operation operation) {
2044} 2077}
2045 2078
2046std::string ARBDecompiler::Barrier(Operation) { 2079std::string ARBDecompiler::Barrier(Operation) {
2047 if (!ir.IsDecompiled()) {
2048 LOG_ERROR(Render_OpenGL, "BAR used but shader is not decompiled");
2049 return {};
2050 }
2051 AddLine("BAR;"); 2080 AddLine("BAR;");
2052 return {}; 2081 return {};
2053} 2082}
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.cpp b/src/video_core/renderer_opengl/gl_buffer_cache.cpp
index e461e4c70..e866d8f2f 100644
--- a/src/video_core/renderer_opengl/gl_buffer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_buffer_cache.cpp
@@ -26,7 +26,7 @@ Buffer::Buffer(const Device& device, VAddr cpu_addr, std::size_t size)
26 : VideoCommon::BufferBlock{cpu_addr, size} { 26 : VideoCommon::BufferBlock{cpu_addr, size} {
27 gl_buffer.Create(); 27 gl_buffer.Create();
28 glNamedBufferData(gl_buffer.handle, static_cast<GLsizeiptr>(size), nullptr, GL_DYNAMIC_DRAW); 28 glNamedBufferData(gl_buffer.handle, static_cast<GLsizeiptr>(size), nullptr, GL_DYNAMIC_DRAW);
29 if (device.HasVertexBufferUnifiedMemory()) { 29 if (device.UseAssemblyShaders() || device.HasVertexBufferUnifiedMemory()) {
30 glMakeNamedBufferResidentNV(gl_buffer.handle, GL_READ_WRITE); 30 glMakeNamedBufferResidentNV(gl_buffer.handle, GL_READ_WRITE);
31 glGetNamedBufferParameterui64vNV(gl_buffer.handle, GL_BUFFER_GPU_ADDRESS_NV, &gpu_address); 31 glGetNamedBufferParameterui64vNV(gl_buffer.handle, GL_BUFFER_GPU_ADDRESS_NV, &gpu_address);
32 } 32 }
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp
index 630acb73b..e7d95149f 100644
--- a/src/video_core/renderer_opengl/gl_device.cpp
+++ b/src/video_core/renderer_opengl/gl_device.cpp
@@ -212,6 +212,7 @@ Device::Device()
212 shader_storage_alignment = GetInteger<std::size_t>(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT); 212 shader_storage_alignment = GetInteger<std::size_t>(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT);
213 max_vertex_attributes = GetInteger<u32>(GL_MAX_VERTEX_ATTRIBS); 213 max_vertex_attributes = GetInteger<u32>(GL_MAX_VERTEX_ATTRIBS);
214 max_varyings = GetInteger<u32>(GL_MAX_VARYING_VECTORS); 214 max_varyings = GetInteger<u32>(GL_MAX_VARYING_VECTORS);
215 max_compute_shared_memory_size = GetInteger<u32>(GL_MAX_COMPUTE_SHARED_MEMORY_SIZE);
215 has_warp_intrinsics = GLAD_GL_NV_gpu_shader5 && GLAD_GL_NV_shader_thread_group && 216 has_warp_intrinsics = GLAD_GL_NV_gpu_shader5 && GLAD_GL_NV_shader_thread_group &&
216 GLAD_GL_NV_shader_thread_shuffle; 217 GLAD_GL_NV_shader_thread_shuffle;
217 has_shader_ballot = GLAD_GL_ARB_shader_ballot; 218 has_shader_ballot = GLAD_GL_ARB_shader_ballot;
@@ -250,6 +251,7 @@ Device::Device(std::nullptr_t) {
250 shader_storage_alignment = 4; 251 shader_storage_alignment = 4;
251 max_vertex_attributes = 16; 252 max_vertex_attributes = 16;
252 max_varyings = 15; 253 max_varyings = 15;
254 max_compute_shared_memory_size = 0x10000;
253 has_warp_intrinsics = true; 255 has_warp_intrinsics = true;
254 has_shader_ballot = true; 256 has_shader_ballot = true;
255 has_vertex_viewport_layer = true; 257 has_vertex_viewport_layer = true;
diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h
index 94d38d7d1..8a4b6b9fc 100644
--- a/src/video_core/renderer_opengl/gl_device.h
+++ b/src/video_core/renderer_opengl/gl_device.h
@@ -52,6 +52,10 @@ public:
52 return max_varyings; 52 return max_varyings;
53 } 53 }
54 54
55 u32 GetMaxComputeSharedMemorySize() const {
56 return max_compute_shared_memory_size;
57 }
58
55 bool HasWarpIntrinsics() const { 59 bool HasWarpIntrinsics() const {
56 return has_warp_intrinsics; 60 return has_warp_intrinsics;
57 } 61 }
@@ -118,6 +122,7 @@ private:
118 std::size_t shader_storage_alignment{}; 122 std::size_t shader_storage_alignment{};
119 u32 max_vertex_attributes{}; 123 u32 max_vertex_attributes{};
120 u32 max_varyings{}; 124 u32 max_varyings{};
125 u32 max_compute_shared_memory_size{};
121 bool has_warp_intrinsics{}; 126 bool has_warp_intrinsics{};
122 bool has_shader_ballot{}; 127 bool has_shader_ballot{};
123 bool has_vertex_viewport_layer{}; 128 bool has_vertex_viewport_layer{};
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index c3fad563c..03e82c599 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -139,6 +139,18 @@ void oglEnable(GLenum cap, bool state) {
139 (state ? glEnable : glDisable)(cap); 139 (state ? glEnable : glDisable)(cap);
140} 140}
141 141
142void UpdateBindlessPointers(GLenum target, GLuint64EXT* pointers, std::size_t num_entries) {
143 if (num_entries == 0) {
144 return;
145 }
146 if (num_entries % 2 == 1) {
147 pointers[num_entries] = 0;
148 }
149 const GLsizei num_vectors = static_cast<GLsizei>((num_entries + 1) / 2);
150 glProgramLocalParametersI4uivNV(target, 0, num_vectors,
151 reinterpret_cast<const GLuint*>(pointers));
152}
153
142} // Anonymous namespace 154} // Anonymous namespace
143 155
144RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window, 156RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window,
@@ -324,7 +336,6 @@ GLintptr RasterizerOpenGL::SetupIndexBuffer() {
324void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { 336void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
325 MICROPROFILE_SCOPE(OpenGL_Shader); 337 MICROPROFILE_SCOPE(OpenGL_Shader);
326 auto& gpu = system.GPU().Maxwell3D(); 338 auto& gpu = system.GPU().Maxwell3D();
327 std::size_t num_ssbos = 0;
328 u32 clip_distances = 0; 339 u32 clip_distances = 0;
329 340
330 for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) { 341 for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) {
@@ -347,29 +358,13 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
347 } 358 }
348 359
349 // Currently this stages are not supported in the OpenGL backend. 360 // Currently this stages are not supported in the OpenGL backend.
350 // Todo(Blinkhawk): Port tesselation shaders from Vulkan to OpenGL 361 // TODO(Blinkhawk): Port tesselation shaders from Vulkan to OpenGL
351 if (program == Maxwell::ShaderProgram::TesselationControl) { 362 if (program == Maxwell::ShaderProgram::TesselationControl ||
363 program == Maxwell::ShaderProgram::TesselationEval) {
352 continue; 364 continue;
353 } else if (program == Maxwell::ShaderProgram::TesselationEval) {
354 continue;
355 }
356
357 Shader* shader = shader_cache.GetStageProgram(program, async_shaders);
358
359 if (device.UseAssemblyShaders()) {
360 // Check for ARB limitation. We only have 16 SSBOs per context state. To workaround this
361 // all stages share the same bindings.
362 const std::size_t num_stage_ssbos = shader->GetEntries().global_memory_entries.size();
363 ASSERT_MSG(num_stage_ssbos == 0 || num_ssbos == 0, "SSBOs on more than one stage");
364 num_ssbos += num_stage_ssbos;
365 } 365 }
366 366
367 // Stage indices are 0 - 5 367 Shader* const shader = shader_cache.GetStageProgram(program, async_shaders);
368 const std::size_t stage = index == 0 ? 0 : index - 1;
369 SetupDrawConstBuffers(stage, shader);
370 SetupDrawGlobalMemory(stage, shader);
371 SetupDrawTextures(stage, shader);
372 SetupDrawImages(stage, shader);
373 368
374 const GLuint program_handle = shader->IsBuilt() ? shader->GetHandle() : 0; 369 const GLuint program_handle = shader->IsBuilt() ? shader->GetHandle() : 0;
375 switch (program) { 370 switch (program) {
@@ -388,6 +383,13 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
388 shader_config.enable.Value(), shader_config.offset); 383 shader_config.enable.Value(), shader_config.offset);
389 } 384 }
390 385
386 // Stage indices are 0 - 5
387 const std::size_t stage = index == 0 ? 0 : index - 1;
388 SetupDrawConstBuffers(stage, shader);
389 SetupDrawGlobalMemory(stage, shader);
390 SetupDrawTextures(stage, shader);
391 SetupDrawImages(stage, shader);
392
391 // Workaround for Intel drivers. 393 // Workaround for Intel drivers.
392 // When a clip distance is enabled but not set in the shader it crops parts of the screen 394 // When a clip distance is enabled but not set in the shader it crops parts of the screen
393 // (sometimes it's half the screen, sometimes three quarters). To avoid this, enable the 395 // (sometimes it's half the screen, sometimes three quarters). To avoid this, enable the
@@ -749,6 +751,8 @@ void RasterizerOpenGL::DispatchCompute(GPUVAddr code_addr) {
749 current_cbuf = 0; 751 current_cbuf = 0;
750 752
751 auto kernel = shader_cache.GetComputeKernel(code_addr); 753 auto kernel = shader_cache.GetComputeKernel(code_addr);
754 program_manager.BindCompute(kernel->GetHandle());
755
752 SetupComputeTextures(kernel); 756 SetupComputeTextures(kernel);
753 SetupComputeImages(kernel); 757 SetupComputeImages(kernel);
754 758
@@ -763,7 +767,6 @@ void RasterizerOpenGL::DispatchCompute(GPUVAddr code_addr) {
763 buffer_cache.Unmap(); 767 buffer_cache.Unmap();
764 768
765 const auto& launch_desc = system.GPU().KeplerCompute().launch_description; 769 const auto& launch_desc = system.GPU().KeplerCompute().launch_description;
766 program_manager.BindCompute(kernel->GetHandle());
767 glDispatchCompute(launch_desc.grid_dim_x, launch_desc.grid_dim_y, launch_desc.grid_dim_z); 770 glDispatchCompute(launch_desc.grid_dim_x, launch_desc.grid_dim_y, launch_desc.grid_dim_z);
768 ++num_queued_commands; 771 ++num_queued_commands;
769} 772}
@@ -1023,40 +1026,66 @@ void RasterizerOpenGL::SetupConstBuffer(GLenum stage, u32 binding,
1023} 1026}
1024 1027
1025void RasterizerOpenGL::SetupDrawGlobalMemory(std::size_t stage_index, Shader* shader) { 1028void RasterizerOpenGL::SetupDrawGlobalMemory(std::size_t stage_index, Shader* shader) {
1029 static constexpr std::array TARGET_LUT = {
1030 GL_VERTEX_PROGRAM_NV, GL_TESS_CONTROL_PROGRAM_NV, GL_TESS_EVALUATION_PROGRAM_NV,
1031 GL_GEOMETRY_PROGRAM_NV, GL_FRAGMENT_PROGRAM_NV,
1032 };
1033
1026 auto& gpu{system.GPU()}; 1034 auto& gpu{system.GPU()};
1027 auto& memory_manager{gpu.MemoryManager()}; 1035 auto& memory_manager{gpu.MemoryManager()};
1028 const auto cbufs{gpu.Maxwell3D().state.shader_stages[stage_index]}; 1036 const auto& cbufs{gpu.Maxwell3D().state.shader_stages[stage_index]};
1037 const auto& entries{shader->GetEntries().global_memory_entries};
1038
1039 std::array<GLuint64EXT, 32> pointers;
1040 ASSERT(entries.size() < pointers.size());
1029 1041
1030 u32 binding = 1042 const bool assembly_shaders = device.UseAssemblyShaders();
1031 device.UseAssemblyShaders() ? 0 : device.GetBaseBindings(stage_index).shader_storage_buffer; 1043 u32 binding = assembly_shaders ? 0 : device.GetBaseBindings(stage_index).shader_storage_buffer;
1032 for (const auto& entry : shader->GetEntries().global_memory_entries) { 1044 for (const auto& entry : entries) {
1033 const GPUVAddr addr{cbufs.const_buffers[entry.cbuf_index].address + entry.cbuf_offset}; 1045 const GPUVAddr addr{cbufs.const_buffers[entry.cbuf_index].address + entry.cbuf_offset};
1034 const GPUVAddr gpu_addr{memory_manager.Read<u64>(addr)}; 1046 const GPUVAddr gpu_addr{memory_manager.Read<u64>(addr)};
1035 const u32 size{memory_manager.Read<u32>(addr + 8)}; 1047 const u32 size{memory_manager.Read<u32>(addr + 8)};
1036 SetupGlobalMemory(binding++, entry, gpu_addr, size); 1048 SetupGlobalMemory(binding, entry, gpu_addr, size, &pointers[binding]);
1049 ++binding;
1050 }
1051 if (assembly_shaders) {
1052 UpdateBindlessPointers(TARGET_LUT[stage_index], pointers.data(), entries.size());
1037 } 1053 }
1038} 1054}
1039 1055
1040void RasterizerOpenGL::SetupComputeGlobalMemory(Shader* kernel) { 1056void RasterizerOpenGL::SetupComputeGlobalMemory(Shader* kernel) {
1041 auto& gpu{system.GPU()}; 1057 auto& gpu{system.GPU()};
1042 auto& memory_manager{gpu.MemoryManager()}; 1058 auto& memory_manager{gpu.MemoryManager()};
1043 const auto cbufs{gpu.KeplerCompute().launch_description.const_buffer_config}; 1059 const auto& cbufs{gpu.KeplerCompute().launch_description.const_buffer_config};
1060 const auto& entries{kernel->GetEntries().global_memory_entries};
1061
1062 std::array<GLuint64EXT, 32> pointers;
1063 ASSERT(entries.size() < pointers.size());
1044 1064
1045 u32 binding = 0; 1065 u32 binding = 0;
1046 for (const auto& entry : kernel->GetEntries().global_memory_entries) { 1066 for (const auto& entry : entries) {
1047 const auto addr{cbufs[entry.cbuf_index].Address() + entry.cbuf_offset}; 1067 const GPUVAddr addr{cbufs[entry.cbuf_index].Address() + entry.cbuf_offset};
1048 const auto gpu_addr{memory_manager.Read<u64>(addr)}; 1068 const GPUVAddr gpu_addr{memory_manager.Read<u64>(addr)};
1049 const auto size{memory_manager.Read<u32>(addr + 8)}; 1069 const u32 size{memory_manager.Read<u32>(addr + 8)};
1050 SetupGlobalMemory(binding++, entry, gpu_addr, size); 1070 SetupGlobalMemory(binding, entry, gpu_addr, size, &pointers[binding]);
1071 ++binding;
1072 }
1073 if (device.UseAssemblyShaders()) {
1074 UpdateBindlessPointers(GL_COMPUTE_PROGRAM_NV, pointers.data(), entries.size());
1051 } 1075 }
1052} 1076}
1053 1077
1054void RasterizerOpenGL::SetupGlobalMemory(u32 binding, const GlobalMemoryEntry& entry, 1078void RasterizerOpenGL::SetupGlobalMemory(u32 binding, const GlobalMemoryEntry& entry,
1055 GPUVAddr gpu_addr, std::size_t size) { 1079 GPUVAddr gpu_addr, std::size_t size,
1056 const auto alignment{device.GetShaderStorageBufferAlignment()}; 1080 GLuint64EXT* pointer) {
1081 const std::size_t alignment{device.GetShaderStorageBufferAlignment()};
1057 const auto info = buffer_cache.UploadMemory(gpu_addr, size, alignment, entry.is_written); 1082 const auto info = buffer_cache.UploadMemory(gpu_addr, size, alignment, entry.is_written);
1058 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, binding, info.handle, info.offset, 1083 if (device.UseAssemblyShaders()) {
1059 static_cast<GLsizeiptr>(size)); 1084 *pointer = info.address + info.offset;
1085 } else {
1086 glBindBufferRange(GL_SHADER_STORAGE_BUFFER, binding, info.handle, info.offset,
1087 static_cast<GLsizeiptr>(size));
1088 }
1060} 1089}
1061 1090
1062void RasterizerOpenGL::SetupDrawTextures(std::size_t stage_index, Shader* shader) { 1091void RasterizerOpenGL::SetupDrawTextures(std::size_t stage_index, Shader* shader) {
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index a95646936..ccc6f50f6 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -124,9 +124,9 @@ private:
124 /// Configures the current global memory entries to use for the kernel invocation. 124 /// Configures the current global memory entries to use for the kernel invocation.
125 void SetupComputeGlobalMemory(Shader* kernel); 125 void SetupComputeGlobalMemory(Shader* kernel);
126 126
127 /// Configures a constant buffer. 127 /// Configures a global memory buffer.
128 void SetupGlobalMemory(u32 binding, const GlobalMemoryEntry& entry, GPUVAddr gpu_addr, 128 void SetupGlobalMemory(u32 binding, const GlobalMemoryEntry& entry, GPUVAddr gpu_addr,
129 std::size_t size); 129 std::size_t size, GLuint64EXT* pointer);
130 130
131 /// Configures the current textures to use for the draw command. 131 /// Configures the current textures to use for the draw command.
132 void SetupDrawTextures(std::size_t stage_index, Shader* shader); 132 void SetupDrawTextures(std::size_t stage_index, Shader* shader);
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index f469ed656..be71e1733 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -126,7 +126,7 @@ std::shared_ptr<Registry> MakeRegistry(const ShaderDiskCacheEntry& entry) {
126 const VideoCore::GuestDriverProfile guest_profile{entry.texture_handler_size}; 126 const VideoCore::GuestDriverProfile guest_profile{entry.texture_handler_size};
127 const VideoCommon::Shader::SerializedRegistryInfo info{guest_profile, entry.bound_buffer, 127 const VideoCommon::Shader::SerializedRegistryInfo info{guest_profile, entry.bound_buffer,
128 entry.graphics_info, entry.compute_info}; 128 entry.graphics_info, entry.compute_info};
129 const auto registry = std::make_shared<Registry>(entry.type, info); 129 auto registry = std::make_shared<Registry>(entry.type, info);
130 for (const auto& [address, value] : entry.keys) { 130 for (const auto& [address, value] : entry.keys) {
131 const auto [buffer, offset] = address; 131 const auto [buffer, offset] = address;
132 registry->InsertKey(buffer, offset, value); 132 registry->InsertKey(buffer, offset, value);
@@ -237,7 +237,6 @@ std::unique_ptr<Shader> Shader::CreateStageFromMemory(
237 const ShaderParameters& params, Maxwell::ShaderProgram program_type, ProgramCode code, 237 const ShaderParameters& params, Maxwell::ShaderProgram program_type, ProgramCode code,
238 ProgramCode code_b, VideoCommon::Shader::AsyncShaders& async_shaders, VAddr cpu_addr) { 238 ProgramCode code_b, VideoCommon::Shader::AsyncShaders& async_shaders, VAddr cpu_addr) {
239 const auto shader_type = GetShaderType(program_type); 239 const auto shader_type = GetShaderType(program_type);
240 const std::size_t size_in_bytes = code.size() * sizeof(u64);
241 240
242 auto& gpu = params.system.GPU(); 241 auto& gpu = params.system.GPU();
243 gpu.ShaderNotify().MarkSharderBuilding(); 242 gpu.ShaderNotify().MarkSharderBuilding();
@@ -287,8 +286,6 @@ std::unique_ptr<Shader> Shader::CreateStageFromMemory(
287 286
288std::unique_ptr<Shader> Shader::CreateKernelFromMemory(const ShaderParameters& params, 287std::unique_ptr<Shader> Shader::CreateKernelFromMemory(const ShaderParameters& params,
289 ProgramCode code) { 288 ProgramCode code) {
290 const std::size_t size_in_bytes = code.size() * sizeof(u64);
291
292 auto& gpu = params.system.GPU(); 289 auto& gpu = params.system.GPU();
293 gpu.ShaderNotify().MarkSharderBuilding(); 290 gpu.ShaderNotify().MarkSharderBuilding();
294 291
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 2c49aeaac..3f75fcd2b 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -602,8 +602,15 @@ private:
602 return; 602 return;
603 } 603 }
604 const auto& info = registry.GetComputeInfo(); 604 const auto& info = registry.GetComputeInfo();
605 if (const u32 size = info.shared_memory_size_in_words; size > 0) { 605 if (u32 size = info.shared_memory_size_in_words * 4; size > 0) {
606 code.AddLine("shared uint smem[{}];", size); 606 const u32 limit = device.GetMaxComputeSharedMemorySize();
607 if (size > limit) {
608 LOG_ERROR(Render_OpenGL, "Shared memory size {} is clamped to host's limit {}",
609 size, limit);
610 size = limit;
611 }
612
613 code.AddLine("shared uint smem[{}];", size / 4);
607 code.AddNewLine(); 614 code.AddNewLine();
608 } 615 }
609 code.AddLine("layout (local_size_x = {}, local_size_y = {}, local_size_z = {}) in;", 616 code.AddLine("layout (local_size_x = {}, local_size_y = {}, local_size_z = {}) in;",
@@ -1912,7 +1919,7 @@ private:
1912 Expression Comparison(Operation operation) { 1919 Expression Comparison(Operation operation) {
1913 static_assert(!unordered || type == Type::Float); 1920 static_assert(!unordered || type == Type::Float);
1914 1921
1915 const Expression expr = GenerateBinaryInfix(operation, op, Type::Bool, type, type); 1922 Expression expr = GenerateBinaryInfix(operation, op, Type::Bool, type, type);
1916 1923
1917 if constexpr (op.compare("!=") == 0 && type == Type::Float && !unordered) { 1924 if constexpr (op.compare("!=") == 0 && type == Type::Float && !unordered) {
1918 // GLSL's operator!=(float, float) doesn't seem be ordered. This happens on both AMD's 1925 // GLSL's operator!=(float, float) doesn't seem be ordered. This happens on both AMD's
@@ -1952,10 +1959,6 @@ private:
1952 return {fmt::format("({} != 0)", carry), Type::Bool}; 1959 return {fmt::format("({} != 0)", carry), Type::Bool};
1953 } 1960 }
1954 1961
1955 Expression LogicalFIsNan(Operation operation) {
1956 return GenerateUnary(operation, "isnan", Type::Bool, Type::Float);
1957 }
1958
1959 Expression LogicalAssign(Operation operation) { 1962 Expression LogicalAssign(Operation operation) {
1960 const Node& dest = operation[0]; 1963 const Node& dest = operation[0];
1961 const Node& src = operation[1]; 1964 const Node& src = operation[1];
@@ -2771,15 +2774,6 @@ private:
2771 return std::min<u32>(device.GetMaxVaryings(), Maxwell::NumVaryings); 2774 return std::min<u32>(device.GetMaxVaryings(), Maxwell::NumVaryings);
2772 } 2775 }
2773 2776
2774 bool IsRenderTargetEnabled(u32 render_target) const {
2775 for (u32 component = 0; component < 4; ++component) {
2776 if (header.ps.IsColorComponentOutputEnabled(render_target, component)) {
2777 return true;
2778 }
2779 }
2780 return false;
2781 }
2782
2783 const Device& device; 2777 const Device& device;
2784 const ShaderIR& ir; 2778 const ShaderIR& ir;
2785 const Registry& registry; 2779 const Registry& registry;
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.cpp b/src/video_core/renderer_opengl/gl_shader_manager.cpp
index 8e754fa90..691c6c79b 100644
--- a/src/video_core/renderer_opengl/gl_shader_manager.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_manager.cpp
@@ -11,8 +11,30 @@
11 11
12namespace OpenGL { 12namespace OpenGL {
13 13
14ProgramManager::ProgramManager(const Device& device) { 14namespace {
15 use_assembly_programs = device.UseAssemblyShaders(); 15
16void BindProgram(GLenum stage, GLuint current, GLuint old, bool& enabled) {
17 if (current == old) {
18 return;
19 }
20 if (current == 0) {
21 if (enabled) {
22 enabled = false;
23 glDisable(stage);
24 }
25 return;
26 }
27 if (!enabled) {
28 enabled = true;
29 glEnable(stage);
30 }
31 glBindProgramARB(stage, current);
32}
33
34} // Anonymous namespace
35
36ProgramManager::ProgramManager(const Device& device)
37 : use_assembly_programs{device.UseAssemblyShaders()} {
16 if (use_assembly_programs) { 38 if (use_assembly_programs) {
17 glEnable(GL_COMPUTE_PROGRAM_NV); 39 glEnable(GL_COMPUTE_PROGRAM_NV);
18 } else { 40 } else {
@@ -33,9 +55,7 @@ void ProgramManager::BindCompute(GLuint program) {
33} 55}
34 56
35void ProgramManager::BindGraphicsPipeline() { 57void ProgramManager::BindGraphicsPipeline() {
36 if (use_assembly_programs) { 58 if (!use_assembly_programs) {
37 UpdateAssemblyPrograms();
38 } else {
39 UpdateSourcePrograms(); 59 UpdateSourcePrograms();
40 } 60 }
41} 61}
@@ -63,32 +83,25 @@ void ProgramManager::RestoreGuestPipeline() {
63 } 83 }
64} 84}
65 85
66void ProgramManager::UpdateAssemblyPrograms() { 86void ProgramManager::UseVertexShader(GLuint program) {
67 const auto update_state = [](GLenum stage, bool& enabled, GLuint current, GLuint old) { 87 if (use_assembly_programs) {
68 if (current == old) { 88 BindProgram(GL_VERTEX_PROGRAM_NV, program, current_state.vertex, vertex_enabled);
69 return; 89 }
70 } 90 current_state.vertex = program;
71 if (current == 0) { 91}
72 if (enabled) {
73 enabled = false;
74 glDisable(stage);
75 }
76 return;
77 }
78 if (!enabled) {
79 enabled = true;
80 glEnable(stage);
81 }
82 glBindProgramARB(stage, current);
83 };
84 92
85 update_state(GL_VERTEX_PROGRAM_NV, vertex_enabled, current_state.vertex, old_state.vertex); 93void ProgramManager::UseGeometryShader(GLuint program) {
86 update_state(GL_GEOMETRY_PROGRAM_NV, geometry_enabled, current_state.geometry, 94 if (use_assembly_programs) {
87 old_state.geometry); 95 BindProgram(GL_GEOMETRY_PROGRAM_NV, program, current_state.vertex, geometry_enabled);
88 update_state(GL_FRAGMENT_PROGRAM_NV, fragment_enabled, current_state.fragment, 96 }
89 old_state.fragment); 97 current_state.geometry = program;
98}
90 99
91 old_state = current_state; 100void ProgramManager::UseFragmentShader(GLuint program) {
101 if (use_assembly_programs) {
102 BindProgram(GL_FRAGMENT_PROGRAM_NV, program, current_state.vertex, fragment_enabled);
103 }
104 current_state.fragment = program;
92} 105}
93 106
94void ProgramManager::UpdateSourcePrograms() { 107void ProgramManager::UpdateSourcePrograms() {
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h
index 0f03b4f12..950e0dfcb 100644
--- a/src/video_core/renderer_opengl/gl_shader_manager.h
+++ b/src/video_core/renderer_opengl/gl_shader_manager.h
@@ -45,17 +45,9 @@ public:
45 /// Rewinds BindHostPipeline state changes. 45 /// Rewinds BindHostPipeline state changes.
46 void RestoreGuestPipeline(); 46 void RestoreGuestPipeline();
47 47
48 void UseVertexShader(GLuint program) { 48 void UseVertexShader(GLuint program);
49 current_state.vertex = program; 49 void UseGeometryShader(GLuint program);
50 } 50 void UseFragmentShader(GLuint program);
51
52 void UseGeometryShader(GLuint program) {
53 current_state.geometry = program;
54 }
55
56 void UseFragmentShader(GLuint program) {
57 current_state.fragment = program;
58 }
59 51
60private: 52private:
61 struct PipelineState { 53 struct PipelineState {
@@ -64,9 +56,6 @@ private:
64 GLuint fragment = 0; 56 GLuint fragment = 0;
65 }; 57 };
66 58
67 /// Update NV_gpu_program5 programs.
68 void UpdateAssemblyPrograms();
69
70 /// Update GLSL programs. 59 /// Update GLSL programs.
71 void UpdateSourcePrograms(); 60 void UpdateSourcePrograms();
72 61
diff --git a/src/video_core/renderer_opengl/gl_stream_buffer.cpp b/src/video_core/renderer_opengl/gl_stream_buffer.cpp
index 3655ff629..887995cf4 100644
--- a/src/video_core/renderer_opengl/gl_stream_buffer.cpp
+++ b/src/video_core/renderer_opengl/gl_stream_buffer.cpp
@@ -35,7 +35,7 @@ OGLStreamBuffer::OGLStreamBuffer(const Device& device, GLsizeiptr size, bool ver
35 mapped_ptr = static_cast<u8*>( 35 mapped_ptr = static_cast<u8*>(
36 glMapNamedBufferRange(gl_buffer.handle, 0, buffer_size, flags | GL_MAP_FLUSH_EXPLICIT_BIT)); 36 glMapNamedBufferRange(gl_buffer.handle, 0, buffer_size, flags | GL_MAP_FLUSH_EXPLICIT_BIT));
37 37
38 if (device.HasVertexBufferUnifiedMemory()) { 38 if (device.UseAssemblyShaders() || device.HasVertexBufferUnifiedMemory()) {
39 glMakeNamedBufferResidentNV(gl_buffer.handle, GL_READ_ONLY); 39 glMakeNamedBufferResidentNV(gl_buffer.handle, GL_READ_ONLY);
40 glGetNamedBufferParameterui64vNV(gl_buffer.handle, GL_BUFFER_GPU_ADDRESS_NV, &gpu_address); 40 glGetNamedBufferParameterui64vNV(gl_buffer.handle, GL_BUFFER_GPU_ADDRESS_NV, &gpu_address);
41 } 41 }
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp
index 61505879b..0a7bc9e2b 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp
@@ -41,91 +41,103 @@ struct FormatTuple {
41}; 41};
42 42
43constexpr std::array<FormatTuple, VideoCore::Surface::MaxPixelFormat> tex_format_tuples = {{ 43constexpr std::array<FormatTuple, VideoCore::Surface::MaxPixelFormat> tex_format_tuples = {{
44 {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV}, // ABGR8U 44 {GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV}, // A8B8G8R8_UNORM
45 {GL_RGBA8_SNORM, GL_RGBA, GL_BYTE}, // ABGR8S 45 {GL_RGBA8_SNORM, GL_RGBA, GL_BYTE}, // A8B8G8R8_SNORM
46 {GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE}, // ABGR8UI 46 {GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE}, // A8B8G8R8_SINT
47 {GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV}, // B5G6R5U 47 {GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE}, // A8B8G8R8_UINT
48 {GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV}, // A2B10G10R10U 48 {GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5}, // R5G6B5_UNORM
49 {GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV}, // A1B5G5R5U 49 {GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV}, // B5G6R5_UNORM
50 {GL_R8, GL_RED, GL_UNSIGNED_BYTE}, // R8U 50 {GL_RGB5_A1, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV}, // A1R5G5B5_UNORM
51 {GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE}, // R8UI 51 {GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV}, // A2B10G10R10_UNORM
52 {GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT}, // RGBA16F 52 {GL_RGB10_A2UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV}, // A2B10G10R10_UINT
53 {GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT}, // RGBA16U 53 {GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV}, // A1B5G5R5_UNORM
54 {GL_RGBA16_SNORM, GL_RGBA, GL_SHORT}, // RGBA16S 54 {GL_R8, GL_RED, GL_UNSIGNED_BYTE}, // R8_UNORM
55 {GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT}, // RGBA16UI 55 {GL_R8_SNORM, GL_RED, GL_BYTE}, // R8_SNORM
56 {GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV}, // R11FG11FB10F 56 {GL_R8I, GL_RED_INTEGER, GL_BYTE}, // R8_SINT
57 {GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT}, // RGBA32UI 57 {GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE}, // R8_UINT
58 {GL_COMPRESSED_RGBA_S3TC_DXT1_EXT}, // DXT1 58 {GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT}, // R16G16B16A16_FLOAT
59 {GL_COMPRESSED_RGBA_S3TC_DXT3_EXT}, // DXT23 59 {GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT}, // R16G16B16A16_UNORM
60 {GL_COMPRESSED_RGBA_S3TC_DXT5_EXT}, // DXT45 60 {GL_RGBA16_SNORM, GL_RGBA, GL_SHORT}, // R16G16B16A16_SNORM
61 {GL_COMPRESSED_RED_RGTC1}, // DXN1 61 {GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT}, // R16G16B16A16_SINT
62 {GL_COMPRESSED_RG_RGTC2}, // DXN2UNORM 62 {GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT}, // R16G16B16A16_UINT
63 {GL_COMPRESSED_SIGNED_RG_RGTC2}, // DXN2SNORM 63 {GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV}, // B10G11R11_FLOAT
64 {GL_COMPRESSED_RGBA_BPTC_UNORM}, // BC7U 64 {GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT}, // R32G32B32A32_UINT
65 {GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT}, // BC6H_UF16 65 {GL_COMPRESSED_RGBA_S3TC_DXT1_EXT}, // BC1_RGBA_UNORM
66 {GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT}, // BC6H_SF16 66 {GL_COMPRESSED_RGBA_S3TC_DXT3_EXT}, // BC2_UNORM
67 {GL_COMPRESSED_RGBA_ASTC_4x4_KHR}, // ASTC_2D_4X4 67 {GL_COMPRESSED_RGBA_S3TC_DXT5_EXT}, // BC3_UNORM
68 {GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE}, // BGRA8 68 {GL_COMPRESSED_RED_RGTC1}, // BC4_UNORM
69 {GL_RGBA32F, GL_RGBA, GL_FLOAT}, // RGBA32F 69 {GL_COMPRESSED_SIGNED_RED_RGTC1}, // BC4_SNORM
70 {GL_RG32F, GL_RG, GL_FLOAT}, // RG32F 70 {GL_COMPRESSED_RG_RGTC2}, // BC5_UNORM
71 {GL_R32F, GL_RED, GL_FLOAT}, // R32F 71 {GL_COMPRESSED_SIGNED_RG_RGTC2}, // BC5_SNORM
72 {GL_R16F, GL_RED, GL_HALF_FLOAT}, // R16F 72 {GL_COMPRESSED_RGBA_BPTC_UNORM}, // BC7_UNORM
73 {GL_R16, GL_RED, GL_UNSIGNED_SHORT}, // R16U 73 {GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT}, // BC6H_UFLOAT
74 {GL_R16_SNORM, GL_RED, GL_SHORT}, // R16S 74 {GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT}, // BC6H_SFLOAT
75 {GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT}, // R16UI 75 {GL_COMPRESSED_RGBA_ASTC_4x4_KHR}, // ASTC_2D_4X4_UNORM
76 {GL_R16I, GL_RED_INTEGER, GL_SHORT}, // R16I 76 {GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE}, // B8G8R8A8_UNORM
77 {GL_RG16, GL_RG, GL_UNSIGNED_SHORT}, // RG16 77 {GL_RGBA32F, GL_RGBA, GL_FLOAT}, // R32G32B32A32_FLOAT
78 {GL_RG16F, GL_RG, GL_HALF_FLOAT}, // RG16F 78 {GL_RGBA32I, GL_RGBA_INTEGER, GL_INT}, // R32G32B32A32_SINT
79 {GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT}, // RG16UI 79 {GL_RG32F, GL_RG, GL_FLOAT}, // R32G32_FLOAT
80 {GL_RG16I, GL_RG_INTEGER, GL_SHORT}, // RG16I 80 {GL_RG32I, GL_RG_INTEGER, GL_INT}, // R32G32_SINT
81 {GL_RG16_SNORM, GL_RG, GL_SHORT}, // RG16S 81 {GL_R32F, GL_RED, GL_FLOAT}, // R32_FLOAT
82 {GL_RGB32F, GL_RGB, GL_FLOAT}, // RGB32F 82 {GL_R16F, GL_RED, GL_HALF_FLOAT}, // R16_FLOAT
83 {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV}, // RGBA8_SRGB 83 {GL_R16, GL_RED, GL_UNSIGNED_SHORT}, // R16_UNORM
84 {GL_RG8, GL_RG, GL_UNSIGNED_BYTE}, // RG8U 84 {GL_R16_SNORM, GL_RED, GL_SHORT}, // R16_SNORM
85 {GL_RG8_SNORM, GL_RG, GL_BYTE}, // RG8S 85 {GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT}, // R16_UINT
86 {GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_INT}, // RG8UI 86 {GL_R16I, GL_RED_INTEGER, GL_SHORT}, // R16_SINT
87 {GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT}, // RG32UI 87 {GL_RG16, GL_RG, GL_UNSIGNED_SHORT}, // R16G16_UNORM
88 {GL_RGB16F, GL_RGBA, GL_HALF_FLOAT}, // RGBX16F 88 {GL_RG16F, GL_RG, GL_HALF_FLOAT}, // R16G16_FLOAT
89 {GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT}, // R32UI 89 {GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT}, // R16G16_UINT
90 {GL_R32I, GL_RED_INTEGER, GL_INT}, // R32I 90 {GL_RG16I, GL_RG_INTEGER, GL_SHORT}, // R16G16_SINT
91 {GL_COMPRESSED_RGBA_ASTC_8x8_KHR}, // ASTC_2D_8X8 91 {GL_RG16_SNORM, GL_RG, GL_SHORT}, // R16G16_SNORM
92 {GL_COMPRESSED_RGBA_ASTC_8x5_KHR}, // ASTC_2D_8X5 92 {GL_RGB32F, GL_RGB, GL_FLOAT}, // R32G32B32_FLOAT
93 {GL_COMPRESSED_RGBA_ASTC_5x4_KHR}, // ASTC_2D_5X4 93 {GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV}, // A8B8G8R8_SRGB
94 {GL_SRGB8_ALPHA8, GL_BGRA, GL_UNSIGNED_BYTE}, // BGRA8 94 {GL_RG8, GL_RG, GL_UNSIGNED_BYTE}, // R8G8_UNORM
95 {GL_RG8_SNORM, GL_RG, GL_BYTE}, // R8G8_SNORM
96 {GL_RG8I, GL_RG_INTEGER, GL_BYTE}, // R8G8_SINT
97 {GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE}, // R8G8_UINT
98 {GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT}, // R32G32_UINT
99 {GL_RGB16F, GL_RGBA, GL_HALF_FLOAT}, // R16G16B16X16_FLOAT
100 {GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT}, // R32_UINT
101 {GL_R32I, GL_RED_INTEGER, GL_INT}, // R32_SINT
102 {GL_COMPRESSED_RGBA_ASTC_8x8_KHR}, // ASTC_2D_8X8_UNORM
103 {GL_COMPRESSED_RGBA_ASTC_8x5_KHR}, // ASTC_2D_8X5_UNORM
104 {GL_COMPRESSED_RGBA_ASTC_5x4_KHR}, // ASTC_2D_5X4_UNORM
105 {GL_SRGB8_ALPHA8, GL_BGRA, GL_UNSIGNED_BYTE}, // B8G8R8A8_UNORM
95 // Compressed sRGB formats 106 // Compressed sRGB formats
96 {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT}, // DXT1_SRGB 107 {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT}, // BC1_RGBA_SRGB
97 {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT}, // DXT23_SRGB 108 {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT}, // BC2_SRGB
98 {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT}, // DXT45_SRGB 109 {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT}, // BC3_SRGB
99 {GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM}, // BC7U_SRGB 110 {GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM}, // BC7_SRGB
100 {GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV}, // R4G4B4A4U 111 {GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4_REV}, // A4B4G4R4_UNORM
101 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR}, // ASTC_2D_4X4_SRGB 112 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR}, // ASTC_2D_4X4_SRGB
102 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR}, // ASTC_2D_8X8_SRGB 113 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR}, // ASTC_2D_8X8_SRGB
103 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR}, // ASTC_2D_8X5_SRGB 114 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR}, // ASTC_2D_8X5_SRGB
104 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR}, // ASTC_2D_5X4_SRGB 115 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR}, // ASTC_2D_5X4_SRGB
105 {GL_COMPRESSED_RGBA_ASTC_5x5_KHR}, // ASTC_2D_5X5 116 {GL_COMPRESSED_RGBA_ASTC_5x5_KHR}, // ASTC_2D_5X5_UNORM
106 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR}, // ASTC_2D_5X5_SRGB 117 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR}, // ASTC_2D_5X5_SRGB
107 {GL_COMPRESSED_RGBA_ASTC_10x8_KHR}, // ASTC_2D_10X8 118 {GL_COMPRESSED_RGBA_ASTC_10x8_KHR}, // ASTC_2D_10X8_UNORM
108 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR}, // ASTC_2D_10X8_SRGB 119 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR}, // ASTC_2D_10X8_SRGB
109 {GL_COMPRESSED_RGBA_ASTC_6x6_KHR}, // ASTC_2D_6X6 120 {GL_COMPRESSED_RGBA_ASTC_6x6_KHR}, // ASTC_2D_6X6_UNORM
110 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR}, // ASTC_2D_6X6_SRGB 121 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR}, // ASTC_2D_6X6_SRGB
111 {GL_COMPRESSED_RGBA_ASTC_10x10_KHR}, // ASTC_2D_10X10 122 {GL_COMPRESSED_RGBA_ASTC_10x10_KHR}, // ASTC_2D_10X10_UNORM
112 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR}, // ASTC_2D_10X10_SRGB 123 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR}, // ASTC_2D_10X10_SRGB
113 {GL_COMPRESSED_RGBA_ASTC_12x12_KHR}, // ASTC_2D_12X12 124 {GL_COMPRESSED_RGBA_ASTC_12x12_KHR}, // ASTC_2D_12X12_UNORM
114 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR}, // ASTC_2D_12X12_SRGB 125 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR}, // ASTC_2D_12X12_SRGB
115 {GL_COMPRESSED_RGBA_ASTC_8x6_KHR}, // ASTC_2D_8X6 126 {GL_COMPRESSED_RGBA_ASTC_8x6_KHR}, // ASTC_2D_8X6_UNORM
116 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR}, // ASTC_2D_8X6_SRGB 127 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR}, // ASTC_2D_8X6_SRGB
117 {GL_COMPRESSED_RGBA_ASTC_6x5_KHR}, // ASTC_2D_6X5 128 {GL_COMPRESSED_RGBA_ASTC_6x5_KHR}, // ASTC_2D_6X5_UNORM
118 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR}, // ASTC_2D_6X5_SRGB 129 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR}, // ASTC_2D_6X5_SRGB
119 {GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV}, // E5B9G9R9F 130 {GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV}, // E5B9G9R9_FLOAT
120 131
121 // Depth formats 132 // Depth formats
122 {GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT}, // Z32F 133 {GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT}, // D32_FLOAT
123 {GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}, // Z16 134 {GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}, // D16_UNORM
124 135
125 // DepthStencil formats 136 // DepthStencil formats
126 {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // Z24S8 137 {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // D24_UNORM_S8_UINT
127 {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // S8Z24 138 {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // S8_UINT_D24_UNORM
128 {GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV}, // Z32FS8 139 {GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL,
140 GL_FLOAT_32_UNSIGNED_INT_24_8_REV}, // D32_FLOAT_S8_UINT
129}}; 141}};
130 142
131const FormatTuple& GetFormatTuple(PixelFormat pixel_format) { 143const FormatTuple& GetFormatTuple(PixelFormat pixel_format) {
@@ -178,10 +190,10 @@ GLint GetSwizzleSource(SwizzleSource source) {
178 190
179GLenum GetComponent(PixelFormat format, bool is_first) { 191GLenum GetComponent(PixelFormat format, bool is_first) {
180 switch (format) { 192 switch (format) {
181 case PixelFormat::Z24S8: 193 case PixelFormat::D24_UNORM_S8_UINT:
182 case PixelFormat::Z32FS8: 194 case PixelFormat::D32_FLOAT_S8_UINT:
183 return is_first ? GL_DEPTH_COMPONENT : GL_STENCIL_INDEX; 195 return is_first ? GL_DEPTH_COMPONENT : GL_STENCIL_INDEX;
184 case PixelFormat::S8Z24: 196 case PixelFormat::S8_UINT_D24_UNORM:
185 return is_first ? GL_STENCIL_INDEX : GL_DEPTH_COMPONENT; 197 return is_first ? GL_STENCIL_INDEX : GL_DEPTH_COMPONENT;
186 default: 198 default:
187 UNREACHABLE(); 199 UNREACHABLE();
@@ -482,9 +494,9 @@ GLuint CachedSurfaceView::GetTexture(SwizzleSource x_source, SwizzleSource y_sou
482 std::array swizzle{x_source, y_source, z_source, w_source}; 494 std::array swizzle{x_source, y_source, z_source, w_source};
483 495
484 switch (const PixelFormat format = GetSurfaceParams().pixel_format) { 496 switch (const PixelFormat format = GetSurfaceParams().pixel_format) {
485 case PixelFormat::Z24S8: 497 case PixelFormat::D24_UNORM_S8_UINT:
486 case PixelFormat::Z32FS8: 498 case PixelFormat::D32_FLOAT_S8_UINT:
487 case PixelFormat::S8Z24: 499 case PixelFormat::S8_UINT_D24_UNORM:
488 UNIMPLEMENTED_IF(x_source != SwizzleSource::R && x_source != SwizzleSource::G); 500 UNIMPLEMENTED_IF(x_source != SwizzleSource::R && x_source != SwizzleSource::G);
489 glTextureParameteri(view.handle, GL_DEPTH_STENCIL_TEXTURE_MODE, 501 glTextureParameteri(view.handle, GL_DEPTH_STENCIL_TEXTURE_MODE,
490 GetComponent(format, x_source == SwizzleSource::R)); 502 GetComponent(format, x_source == SwizzleSource::R));
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index e66cdc083..52e9e8250 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -535,12 +535,12 @@ void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture,
535 535
536 GLint internal_format; 536 GLint internal_format;
537 switch (framebuffer.pixel_format) { 537 switch (framebuffer.pixel_format) {
538 case Tegra::FramebufferConfig::PixelFormat::ABGR8: 538 case Tegra::FramebufferConfig::PixelFormat::A8B8G8R8_UNORM:
539 internal_format = GL_RGBA8; 539 internal_format = GL_RGBA8;
540 texture.gl_format = GL_RGBA; 540 texture.gl_format = GL_RGBA;
541 texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV; 541 texture.gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
542 break; 542 break;
543 case Tegra::FramebufferConfig::PixelFormat::RGB565: 543 case Tegra::FramebufferConfig::PixelFormat::RGB565_UNORM:
544 internal_format = GL_RGB565; 544 internal_format = GL_RGB565;
545 texture.gl_format = GL_RGB; 545 texture.gl_format = GL_RGB;
546 texture.gl_type = GL_UNSIGNED_SHORT_5_6_5; 546 texture.gl_type = GL_UNSIGNED_SHORT_5_6_5;
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
index d1f0ea932..81a39a3b8 100644
--- a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
+++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
@@ -40,7 +40,6 @@ constexpr std::array POLYGON_OFFSET_ENABLE_LUT = {
40} // Anonymous namespace 40} // Anonymous namespace
41 41
42void FixedPipelineState::Fill(const Maxwell& regs, bool has_extended_dynamic_state) { 42void FixedPipelineState::Fill(const Maxwell& regs, bool has_extended_dynamic_state) {
43 const auto& clip = regs.view_volume_clip_control;
44 const std::array enabled_lut = {regs.polygon_offset_point_enable, 43 const std::array enabled_lut = {regs.polygon_offset_point_enable,
45 regs.polygon_offset_line_enable, 44 regs.polygon_offset_line_enable,
46 regs.polygon_offset_fill_enable}; 45 regs.polygon_offset_fill_enable};
diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
index d7f1ae89f..f8c77f4fa 100644
--- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
+++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
@@ -117,90 +117,101 @@ struct FormatTuple {
117 VkFormat format; ///< Vulkan format 117 VkFormat format; ///< Vulkan format
118 int usage = 0; ///< Describes image format usage 118 int usage = 0; ///< Describes image format usage
119} constexpr tex_format_tuples[] = { 119} constexpr tex_format_tuples[] = {
120 {VK_FORMAT_A8B8G8R8_UNORM_PACK32, Attachable | Storage}, // ABGR8U 120 {VK_FORMAT_A8B8G8R8_UNORM_PACK32, Attachable | Storage}, // A8B8G8R8_UNORM
121 {VK_FORMAT_A8B8G8R8_SNORM_PACK32, Attachable | Storage}, // ABGR8S 121 {VK_FORMAT_A8B8G8R8_SNORM_PACK32, Attachable | Storage}, // A8B8G8R8_SNORM
122 {VK_FORMAT_A8B8G8R8_UINT_PACK32, Attachable | Storage}, // ABGR8UI 122 {VK_FORMAT_A8B8G8R8_SINT_PACK32, Attachable | Storage}, // A8B8G8R8_SINT
123 {VK_FORMAT_B5G6R5_UNORM_PACK16}, // B5G6R5U 123 {VK_FORMAT_A8B8G8R8_UINT_PACK32, Attachable | Storage}, // A8B8G8R8_UINT
124 {VK_FORMAT_A2B10G10R10_UNORM_PACK32, Attachable | Storage}, // A2B10G10R10U 124 {VK_FORMAT_R5G6B5_UNORM_PACK16, Attachable}, // R5G6B5_UNORM
125 {VK_FORMAT_A1R5G5B5_UNORM_PACK16, Attachable}, // A1B5G5R5U (flipped with swizzle) 125 {VK_FORMAT_B5G6R5_UNORM_PACK16, Attachable}, // B5G6R5_UNORM
126 {VK_FORMAT_R8_UNORM, Attachable | Storage}, // R8U 126 {VK_FORMAT_A1R5G5B5_UNORM_PACK16, Attachable}, // A1R5G5B5_UNORM
127 {VK_FORMAT_R8_UINT, Attachable | Storage}, // R8UI 127 {VK_FORMAT_A2B10G10R10_UNORM_PACK32, Attachable | Storage}, // A2B10G10R10_UNORM
128 {VK_FORMAT_R16G16B16A16_SFLOAT, Attachable | Storage}, // RGBA16F 128 {VK_FORMAT_A2B10G10R10_UINT_PACK32, Attachable | Storage}, // A2B10G10R10_UINT
129 {VK_FORMAT_R16G16B16A16_UNORM, Attachable | Storage}, // RGBA16U 129 {VK_FORMAT_A1R5G5B5_UNORM_PACK16, Attachable}, // A1B5G5R5_UNORM (flipped with swizzle)
130 {VK_FORMAT_R16G16B16A16_SNORM, Attachable | Storage}, // RGBA16S 130 {VK_FORMAT_R8_UNORM, Attachable | Storage}, // R8_UNORM
131 {VK_FORMAT_R16G16B16A16_UINT, Attachable | Storage}, // RGBA16UI 131 {VK_FORMAT_R8_SNORM, Attachable | Storage}, // R8_SNORM
132 {VK_FORMAT_B10G11R11_UFLOAT_PACK32, Attachable | Storage}, // R11FG11FB10F 132 {VK_FORMAT_R8_SINT, Attachable | Storage}, // R8_SINT
133 {VK_FORMAT_R32G32B32A32_UINT, Attachable | Storage}, // RGBA32UI 133 {VK_FORMAT_R8_UINT, Attachable | Storage}, // R8_UINT
134 {VK_FORMAT_BC1_RGBA_UNORM_BLOCK}, // DXT1 134 {VK_FORMAT_R16G16B16A16_SFLOAT, Attachable | Storage}, // R16G16B16A16_FLOAT
135 {VK_FORMAT_BC2_UNORM_BLOCK}, // DXT23 135 {VK_FORMAT_R16G16B16A16_UNORM, Attachable | Storage}, // R16G16B16A16_UNORM
136 {VK_FORMAT_BC3_UNORM_BLOCK}, // DXT45 136 {VK_FORMAT_R16G16B16A16_SNORM, Attachable | Storage}, // R16G16B16A16_SNORM
137 {VK_FORMAT_BC4_UNORM_BLOCK}, // DXN1 137 {VK_FORMAT_R16G16B16A16_SINT, Attachable | Storage}, // R16G16B16A16_SINT
138 {VK_FORMAT_BC5_UNORM_BLOCK}, // DXN2UNORM 138 {VK_FORMAT_R16G16B16A16_UINT, Attachable | Storage}, // R16G16B16A16_UINT
139 {VK_FORMAT_BC5_SNORM_BLOCK}, // DXN2SNORM 139 {VK_FORMAT_B10G11R11_UFLOAT_PACK32, Attachable | Storage}, // B10G11R11_FLOAT
140 {VK_FORMAT_BC7_UNORM_BLOCK}, // BC7U 140 {VK_FORMAT_R32G32B32A32_UINT, Attachable | Storage}, // R32G32B32A32_UINT
141 {VK_FORMAT_BC6H_UFLOAT_BLOCK}, // BC6H_UF16 141 {VK_FORMAT_BC1_RGBA_UNORM_BLOCK}, // BC1_RGBA_UNORM
142 {VK_FORMAT_BC6H_SFLOAT_BLOCK}, // BC6H_SF16 142 {VK_FORMAT_BC2_UNORM_BLOCK}, // BC2_UNORM
143 {VK_FORMAT_ASTC_4x4_UNORM_BLOCK}, // ASTC_2D_4X4 143 {VK_FORMAT_BC3_UNORM_BLOCK}, // BC3_UNORM
144 {VK_FORMAT_B8G8R8A8_UNORM, Attachable}, // BGRA8 144 {VK_FORMAT_BC4_UNORM_BLOCK}, // BC4_UNORM
145 {VK_FORMAT_R32G32B32A32_SFLOAT, Attachable | Storage}, // RGBA32F 145 {VK_FORMAT_BC4_SNORM_BLOCK}, // BC4_SNORM
146 {VK_FORMAT_R32G32_SFLOAT, Attachable | Storage}, // RG32F 146 {VK_FORMAT_BC5_UNORM_BLOCK}, // BC5_UNORM
147 {VK_FORMAT_R32_SFLOAT, Attachable | Storage}, // R32F 147 {VK_FORMAT_BC5_SNORM_BLOCK}, // BC5_SNORM
148 {VK_FORMAT_R16_SFLOAT, Attachable | Storage}, // R16F 148 {VK_FORMAT_BC7_UNORM_BLOCK}, // BC7_UNORM
149 {VK_FORMAT_R16_UNORM, Attachable | Storage}, // R16U 149 {VK_FORMAT_BC6H_UFLOAT_BLOCK}, // BC6H_UFLOAT
150 {VK_FORMAT_UNDEFINED}, // R16S 150 {VK_FORMAT_BC6H_SFLOAT_BLOCK}, // BC6H_SFLOAT
151 {VK_FORMAT_R16_UINT, Attachable | Storage}, // R16UI 151 {VK_FORMAT_ASTC_4x4_UNORM_BLOCK}, // ASTC_2D_4X4_UNORM
152 {VK_FORMAT_UNDEFINED}, // R16I 152 {VK_FORMAT_B8G8R8A8_UNORM, Attachable}, // B8G8R8A8_UNORM
153 {VK_FORMAT_R16G16_UNORM, Attachable | Storage}, // RG16 153 {VK_FORMAT_R32G32B32A32_SFLOAT, Attachable | Storage}, // R32G32B32A32_FLOAT
154 {VK_FORMAT_R16G16_SFLOAT, Attachable | Storage}, // RG16F 154 {VK_FORMAT_R32G32B32A32_SINT, Attachable | Storage}, // R32G32B32A32_SINT
155 {VK_FORMAT_UNDEFINED}, // RG16UI 155 {VK_FORMAT_R32G32_SFLOAT, Attachable | Storage}, // R32G32_FLOAT
156 {VK_FORMAT_UNDEFINED}, // RG16I 156 {VK_FORMAT_R32G32_SINT, Attachable | Storage}, // R32G32_SINT
157 {VK_FORMAT_R16G16_SNORM, Attachable | Storage}, // RG16S 157 {VK_FORMAT_R32_SFLOAT, Attachable | Storage}, // R32_FLOAT
158 {VK_FORMAT_UNDEFINED}, // RGB32F 158 {VK_FORMAT_R16_SFLOAT, Attachable | Storage}, // R16_FLOAT
159 {VK_FORMAT_R8G8B8A8_SRGB, Attachable}, // RGBA8_SRGB 159 {VK_FORMAT_R16_UNORM, Attachable | Storage}, // R16_UNORM
160 {VK_FORMAT_R8G8_UNORM, Attachable | Storage}, // RG8U 160 {VK_FORMAT_UNDEFINED}, // R16_SNORM
161 {VK_FORMAT_R8G8_SNORM, Attachable | Storage}, // RG8S 161 {VK_FORMAT_R16_UINT, Attachable | Storage}, // R16_UINT
162 {VK_FORMAT_R8G8_UINT, Attachable | Storage}, // RG8UI 162 {VK_FORMAT_UNDEFINED}, // R16_SINT
163 {VK_FORMAT_R32G32_UINT, Attachable | Storage}, // RG32UI 163 {VK_FORMAT_R16G16_UNORM, Attachable | Storage}, // R16G16_UNORM
164 {VK_FORMAT_UNDEFINED}, // RGBX16F 164 {VK_FORMAT_R16G16_SFLOAT, Attachable | Storage}, // R16G16_FLOAT
165 {VK_FORMAT_R32_UINT, Attachable | Storage}, // R32UI 165 {VK_FORMAT_UNDEFINED}, // R16G16_UINT
166 {VK_FORMAT_R32_SINT, Attachable | Storage}, // R32I 166 {VK_FORMAT_UNDEFINED}, // R16G16_SINT
167 {VK_FORMAT_ASTC_8x8_UNORM_BLOCK}, // ASTC_2D_8X8 167 {VK_FORMAT_R16G16_SNORM, Attachable | Storage}, // R16G16_SNORM
168 {VK_FORMAT_UNDEFINED}, // ASTC_2D_8X5 168 {VK_FORMAT_UNDEFINED}, // R32G32B32_FLOAT
169 {VK_FORMAT_UNDEFINED}, // ASTC_2D_5X4 169 {VK_FORMAT_R8G8B8A8_SRGB, Attachable}, // A8B8G8R8_SRGB
170 {VK_FORMAT_B8G8R8A8_SRGB, Attachable}, // BGRA8_SRGB 170 {VK_FORMAT_R8G8_UNORM, Attachable | Storage}, // R8G8_UNORM
171 {VK_FORMAT_BC1_RGBA_SRGB_BLOCK}, // DXT1_SRGB 171 {VK_FORMAT_R8G8_SNORM, Attachable | Storage}, // R8G8_SNORM
172 {VK_FORMAT_BC2_SRGB_BLOCK}, // DXT23_SRGB 172 {VK_FORMAT_R8G8_SINT, Attachable | Storage}, // R8G8_SINT
173 {VK_FORMAT_BC3_SRGB_BLOCK}, // DXT45_SRGB 173 {VK_FORMAT_R8G8_UINT, Attachable | Storage}, // R8G8_UINT
174 {VK_FORMAT_BC7_SRGB_BLOCK}, // BC7U_SRGB 174 {VK_FORMAT_R32G32_UINT, Attachable | Storage}, // R32G32_UINT
175 {VK_FORMAT_R4G4B4A4_UNORM_PACK16, Attachable}, // R4G4B4A4U 175 {VK_FORMAT_UNDEFINED}, // R16G16B16X16_FLOAT
176 {VK_FORMAT_ASTC_4x4_SRGB_BLOCK}, // ASTC_2D_4X4_SRGB 176 {VK_FORMAT_R32_UINT, Attachable | Storage}, // R32_UINT
177 {VK_FORMAT_ASTC_8x8_SRGB_BLOCK}, // ASTC_2D_8X8_SRGB 177 {VK_FORMAT_R32_SINT, Attachable | Storage}, // R32_SINT
178 {VK_FORMAT_ASTC_8x5_SRGB_BLOCK}, // ASTC_2D_8X5_SRGB 178 {VK_FORMAT_ASTC_8x8_UNORM_BLOCK}, // ASTC_2D_8X8_UNORM
179 {VK_FORMAT_ASTC_5x4_SRGB_BLOCK}, // ASTC_2D_5X4_SRGB 179 {VK_FORMAT_UNDEFINED}, // ASTC_2D_8X5_UNORM
180 {VK_FORMAT_ASTC_5x5_UNORM_BLOCK}, // ASTC_2D_5X5 180 {VK_FORMAT_UNDEFINED}, // ASTC_2D_5X4_UNORM
181 {VK_FORMAT_ASTC_5x5_SRGB_BLOCK}, // ASTC_2D_5X5_SRGB 181 {VK_FORMAT_B8G8R8A8_SRGB, Attachable}, // B8G8R8A8_SRGB
182 {VK_FORMAT_ASTC_10x8_UNORM_BLOCK}, // ASTC_2D_10X8 182 {VK_FORMAT_BC1_RGBA_SRGB_BLOCK}, // BC1_RGBA_SRGB
183 {VK_FORMAT_ASTC_10x8_SRGB_BLOCK}, // ASTC_2D_10X8_SRGB 183 {VK_FORMAT_BC2_SRGB_BLOCK}, // BC2_SRGB
184 {VK_FORMAT_ASTC_6x6_UNORM_BLOCK}, // ASTC_2D_6X6 184 {VK_FORMAT_BC3_SRGB_BLOCK}, // BC3_SRGB
185 {VK_FORMAT_ASTC_6x6_SRGB_BLOCK}, // ASTC_2D_6X6_SRGB 185 {VK_FORMAT_BC7_SRGB_BLOCK}, // BC7_SRGB
186 {VK_FORMAT_ASTC_10x10_UNORM_BLOCK}, // ASTC_2D_10X10 186 {VK_FORMAT_R4G4B4A4_UNORM_PACK16, Attachable}, // A4B4G4R4_UNORM
187 {VK_FORMAT_ASTC_10x10_SRGB_BLOCK}, // ASTC_2D_10X10_SRGB 187 {VK_FORMAT_ASTC_4x4_SRGB_BLOCK}, // ASTC_2D_4X4_SRGB
188 {VK_FORMAT_ASTC_12x12_UNORM_BLOCK}, // ASTC_2D_12X12 188 {VK_FORMAT_ASTC_8x8_SRGB_BLOCK}, // ASTC_2D_8X8_SRGB
189 {VK_FORMAT_ASTC_12x12_SRGB_BLOCK}, // ASTC_2D_12X12_SRGB 189 {VK_FORMAT_ASTC_8x5_SRGB_BLOCK}, // ASTC_2D_8X5_SRGB
190 {VK_FORMAT_ASTC_8x6_UNORM_BLOCK}, // ASTC_2D_8X6 190 {VK_FORMAT_ASTC_5x4_SRGB_BLOCK}, // ASTC_2D_5X4_SRGB
191 {VK_FORMAT_ASTC_8x6_SRGB_BLOCK}, // ASTC_2D_8X6_SRGB 191 {VK_FORMAT_ASTC_5x5_UNORM_BLOCK}, // ASTC_2D_5X5_UNORM
192 {VK_FORMAT_ASTC_6x5_UNORM_BLOCK}, // ASTC_2D_6X5 192 {VK_FORMAT_ASTC_5x5_SRGB_BLOCK}, // ASTC_2D_5X5_SRGB
193 {VK_FORMAT_ASTC_6x5_SRGB_BLOCK}, // ASTC_2D_6X5_SRGB 193 {VK_FORMAT_ASTC_10x8_UNORM_BLOCK}, // ASTC_2D_10X8_UNORM
194 {VK_FORMAT_E5B9G9R9_UFLOAT_PACK32}, // E5B9G9R9F 194 {VK_FORMAT_ASTC_10x8_SRGB_BLOCK}, // ASTC_2D_10X8_SRGB
195 {VK_FORMAT_ASTC_6x6_UNORM_BLOCK}, // ASTC_2D_6X6_UNORM
196 {VK_FORMAT_ASTC_6x6_SRGB_BLOCK}, // ASTC_2D_6X6_SRGB
197 {VK_FORMAT_ASTC_10x10_UNORM_BLOCK}, // ASTC_2D_10X10_UNORM
198 {VK_FORMAT_ASTC_10x10_SRGB_BLOCK}, // ASTC_2D_10X10_SRGB
199 {VK_FORMAT_ASTC_12x12_UNORM_BLOCK}, // ASTC_2D_12X12_UNORM
200 {VK_FORMAT_ASTC_12x12_SRGB_BLOCK}, // ASTC_2D_12X12_SRGB
201 {VK_FORMAT_ASTC_8x6_UNORM_BLOCK}, // ASTC_2D_8X6_UNORM
202 {VK_FORMAT_ASTC_8x6_SRGB_BLOCK}, // ASTC_2D_8X6_SRGB
203 {VK_FORMAT_ASTC_6x5_UNORM_BLOCK}, // ASTC_2D_6X5_UNORM
204 {VK_FORMAT_ASTC_6x5_SRGB_BLOCK}, // ASTC_2D_6X5_SRGB
205 {VK_FORMAT_E5B9G9R9_UFLOAT_PACK32}, // E5B9G9R9_FLOAT
195 206
196 // Depth formats 207 // Depth formats
197 {VK_FORMAT_D32_SFLOAT, Attachable}, // Z32F 208 {VK_FORMAT_D32_SFLOAT, Attachable}, // D32_FLOAT
198 {VK_FORMAT_D16_UNORM, Attachable}, // Z16 209 {VK_FORMAT_D16_UNORM, Attachable}, // D16_UNORM
199 210
200 // DepthStencil formats 211 // DepthStencil formats
201 {VK_FORMAT_D24_UNORM_S8_UINT, Attachable}, // Z24S8 212 {VK_FORMAT_D24_UNORM_S8_UINT, Attachable}, // D24_UNORM_S8_UINT
202 {VK_FORMAT_D24_UNORM_S8_UINT, Attachable}, // S8Z24 (emulated) 213 {VK_FORMAT_D24_UNORM_S8_UINT, Attachable}, // S8_UINT_D24_UNORM (emulated)
203 {VK_FORMAT_D32_SFLOAT_S8_UINT, Attachable}, // Z32FS8 214 {VK_FORMAT_D32_SFLOAT_S8_UINT, Attachable}, // D32_FLOAT_S8_UINT
204}; 215};
205static_assert(std::size(tex_format_tuples) == VideoCore::Surface::MaxPixelFormat); 216static_assert(std::size(tex_format_tuples) == VideoCore::Surface::MaxPixelFormat);
206 217
@@ -221,7 +232,7 @@ FormatInfo SurfaceFormat(const VKDevice& device, FormatType format_type, PixelFo
221 return {VK_FORMAT_A8B8G8R8_UNORM_PACK32, true, true}; 232 return {VK_FORMAT_A8B8G8R8_UNORM_PACK32, true, true};
222 } 233 }
223 234
224 // Use ABGR8 on hardware that doesn't support ASTC natively 235 // Use A8B8G8R8_UNORM on hardware that doesn't support ASTC natively
225 if (!device.IsOptimalAstcSupported() && VideoCore::Surface::IsPixelFormatASTC(pixel_format)) { 236 if (!device.IsOptimalAstcSupported() && VideoCore::Surface::IsPixelFormatASTC(pixel_format)) {
226 tuple.format = VideoCore::Surface::IsPixelFormatSRGB(pixel_format) 237 tuple.format = VideoCore::Surface::IsPixelFormatSRGB(pixel_format)
227 ? VK_FORMAT_A8B8G8R8_SRGB_PACK32 238 ? VK_FORMAT_A8B8G8R8_SRGB_PACK32
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
index 866813465..ce53e5a6b 100644
--- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp
+++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
@@ -187,9 +187,9 @@ std::size_t GetSizeInBytes(const Tegra::FramebufferConfig& framebuffer) {
187 187
188VkFormat GetFormat(const Tegra::FramebufferConfig& framebuffer) { 188VkFormat GetFormat(const Tegra::FramebufferConfig& framebuffer) {
189 switch (framebuffer.pixel_format) { 189 switch (framebuffer.pixel_format) {
190 case Tegra::FramebufferConfig::PixelFormat::ABGR8: 190 case Tegra::FramebufferConfig::PixelFormat::A8B8G8R8_UNORM:
191 return VK_FORMAT_A8B8G8R8_UNORM_PACK32; 191 return VK_FORMAT_A8B8G8R8_UNORM_PACK32;
192 case Tegra::FramebufferConfig::PixelFormat::RGB565: 192 case Tegra::FramebufferConfig::PixelFormat::RGB565_UNORM:
193 return VK_FORMAT_R5G6B5_UNORM_PACK16; 193 return VK_FORMAT_R5G6B5_UNORM_PACK16;
194 default: 194 default:
195 UNIMPLEMENTED_MSG("Unknown framebuffer pixel format: {}", 195 UNIMPLEMENTED_MSG("Unknown framebuffer pixel format: {}",
diff --git a/src/video_core/renderer_vulkan/vk_device.cpp b/src/video_core/renderer_vulkan/vk_device.cpp
index 26379ee01..6245e0d78 100644
--- a/src/video_core/renderer_vulkan/vk_device.cpp
+++ b/src/video_core/renderer_vulkan/vk_device.cpp
@@ -84,14 +84,19 @@ std::unordered_map<VkFormat, VkFormatProperties> GetFormatProperties(
84 VK_FORMAT_A8B8G8R8_UNORM_PACK32, 84 VK_FORMAT_A8B8G8R8_UNORM_PACK32,
85 VK_FORMAT_A8B8G8R8_UINT_PACK32, 85 VK_FORMAT_A8B8G8R8_UINT_PACK32,
86 VK_FORMAT_A8B8G8R8_SNORM_PACK32, 86 VK_FORMAT_A8B8G8R8_SNORM_PACK32,
87 VK_FORMAT_A8B8G8R8_SINT_PACK32,
87 VK_FORMAT_A8B8G8R8_SRGB_PACK32, 88 VK_FORMAT_A8B8G8R8_SRGB_PACK32,
88 VK_FORMAT_B5G6R5_UNORM_PACK16, 89 VK_FORMAT_B5G6R5_UNORM_PACK16,
89 VK_FORMAT_A2B10G10R10_UNORM_PACK32, 90 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
91 VK_FORMAT_A2B10G10R10_UINT_PACK32,
90 VK_FORMAT_A1R5G5B5_UNORM_PACK16, 92 VK_FORMAT_A1R5G5B5_UNORM_PACK16,
91 VK_FORMAT_R32G32B32A32_SFLOAT, 93 VK_FORMAT_R32G32B32A32_SFLOAT,
94 VK_FORMAT_R32G32B32A32_SINT,
92 VK_FORMAT_R32G32B32A32_UINT, 95 VK_FORMAT_R32G32B32A32_UINT,
93 VK_FORMAT_R32G32_SFLOAT, 96 VK_FORMAT_R32G32_SFLOAT,
97 VK_FORMAT_R32G32_SINT,
94 VK_FORMAT_R32G32_UINT, 98 VK_FORMAT_R32G32_UINT,
99 VK_FORMAT_R16G16B16A16_SINT,
95 VK_FORMAT_R16G16B16A16_UINT, 100 VK_FORMAT_R16G16B16A16_UINT,
96 VK_FORMAT_R16G16B16A16_SNORM, 101 VK_FORMAT_R16G16B16A16_SNORM,
97 VK_FORMAT_R16G16B16A16_UNORM, 102 VK_FORMAT_R16G16B16A16_UNORM,
@@ -103,8 +108,11 @@ std::unordered_map<VkFormat, VkFormatProperties> GetFormatProperties(
103 VK_FORMAT_R8G8B8A8_SRGB, 108 VK_FORMAT_R8G8B8A8_SRGB,
104 VK_FORMAT_R8G8_UNORM, 109 VK_FORMAT_R8G8_UNORM,
105 VK_FORMAT_R8G8_SNORM, 110 VK_FORMAT_R8G8_SNORM,
111 VK_FORMAT_R8G8_SINT,
106 VK_FORMAT_R8G8_UINT, 112 VK_FORMAT_R8G8_UINT,
107 VK_FORMAT_R8_UNORM, 113 VK_FORMAT_R8_UNORM,
114 VK_FORMAT_R8_SNORM,
115 VK_FORMAT_R8_SINT,
108 VK_FORMAT_R8_UINT, 116 VK_FORMAT_R8_UINT,
109 VK_FORMAT_B10G11R11_UFLOAT_PACK32, 117 VK_FORMAT_B10G11R11_UFLOAT_PACK32,
110 VK_FORMAT_R32_SFLOAT, 118 VK_FORMAT_R32_SFLOAT,
@@ -124,6 +132,7 @@ std::unordered_map<VkFormat, VkFormatProperties> GetFormatProperties(
124 VK_FORMAT_BC2_UNORM_BLOCK, 132 VK_FORMAT_BC2_UNORM_BLOCK,
125 VK_FORMAT_BC3_UNORM_BLOCK, 133 VK_FORMAT_BC3_UNORM_BLOCK,
126 VK_FORMAT_BC4_UNORM_BLOCK, 134 VK_FORMAT_BC4_UNORM_BLOCK,
135 VK_FORMAT_BC4_SNORM_BLOCK,
127 VK_FORMAT_BC5_UNORM_BLOCK, 136 VK_FORMAT_BC5_UNORM_BLOCK,
128 VK_FORMAT_BC5_SNORM_BLOCK, 137 VK_FORMAT_BC5_SNORM_BLOCK,
129 VK_FORMAT_BC7_UNORM_BLOCK, 138 VK_FORMAT_BC7_UNORM_BLOCK,
diff --git a/src/video_core/renderer_vulkan/vk_device.h b/src/video_core/renderer_vulkan/vk_device.h
index ae5c21baa..529744f2d 100644
--- a/src/video_core/renderer_vulkan/vk_device.h
+++ b/src/video_core/renderer_vulkan/vk_device.h
@@ -122,6 +122,11 @@ public:
122 return properties.limits.maxPushConstantsSize; 122 return properties.limits.maxPushConstantsSize;
123 } 123 }
124 124
125 /// Returns the maximum size for shared memory.
126 u32 GetMaxComputeSharedMemorySize() const {
127 return properties.limits.maxComputeSharedMemorySize;
128 }
129
125 /// Returns true if ASTC is natively supported. 130 /// Returns true if ASTC is natively supported.
126 bool IsOptimalAstcSupported() const { 131 bool IsOptimalAstcSupported() const {
127 return is_optimal_astc_supported; 132 return is_optimal_astc_supported;
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 31e44aa2b..2ed2004f0 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -532,10 +532,6 @@ void RasterizerVulkan::Clear() {
532 532
533 scheduler.Record([clear_depth = regs.clear_depth, clear_stencil = regs.clear_stencil, 533 scheduler.Record([clear_depth = regs.clear_depth, clear_stencil = regs.clear_stencil,
534 clear_rect, aspect_flags](vk::CommandBuffer cmdbuf) { 534 clear_rect, aspect_flags](vk::CommandBuffer cmdbuf) {
535 VkClearValue clear_value;
536 clear_value.depthStencil.depth = clear_depth;
537 clear_value.depthStencil.stencil = clear_stencil;
538
539 VkClearAttachment attachment; 535 VkClearAttachment attachment;
540 attachment.aspectMask = aspect_flags; 536 attachment.aspectMask = aspect_flags;
541 attachment.colorAttachment = 0; 537 attachment.colorAttachment = 0;
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
index 97429cc59..cd7d7a4e4 100644
--- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
+++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
@@ -685,13 +685,19 @@ private:
685 } 685 }
686 t_smem_uint = TypePointer(spv::StorageClass::Workgroup, t_uint); 686 t_smem_uint = TypePointer(spv::StorageClass::Workgroup, t_uint);
687 687
688 const u32 smem_size = specialization.shared_memory_size; 688 u32 smem_size = specialization.shared_memory_size * 4;
689 if (smem_size == 0) { 689 if (smem_size == 0) {
690 // Avoid declaring an empty array. 690 // Avoid declaring an empty array.
691 return; 691 return;
692 } 692 }
693 const auto element_count = static_cast<u32>(Common::AlignUp(smem_size, 4) / 4); 693 const u32 limit = device.GetMaxComputeSharedMemorySize();
694 const Id type_array = TypeArray(t_uint, Constant(t_uint, element_count)); 694 if (smem_size > limit) {
695 LOG_ERROR(Render_Vulkan, "Shared memory size {} is clamped to host's limit {}",
696 smem_size, limit);
697 smem_size = limit;
698 }
699
700 const Id type_array = TypeArray(t_uint, Constant(t_uint, smem_size / 4));
695 const Id type_pointer = TypePointer(spv::StorageClass::Workgroup, type_array); 701 const Id type_pointer = TypePointer(spv::StorageClass::Workgroup, type_array);
696 Name(type_pointer, "SharedMemory"); 702 Name(type_pointer, "SharedMemory");
697 703
@@ -700,9 +706,9 @@ private:
700 } 706 }
701 707
702 void DeclareInternalFlags() { 708 void DeclareInternalFlags() {
703 constexpr std::array names = {"zero", "sign", "carry", "overflow"}; 709 static constexpr std::array names{"zero", "sign", "carry", "overflow"};
710
704 for (std::size_t flag = 0; flag < INTERNAL_FLAGS_COUNT; ++flag) { 711 for (std::size_t flag = 0; flag < INTERNAL_FLAGS_COUNT; ++flag) {
705 const auto flag_code = static_cast<InternalFlag>(flag);
706 const Id id = OpVariable(t_prv_bool, spv::StorageClass::Private, v_false); 712 const Id id = OpVariable(t_prv_bool, spv::StorageClass::Private, v_false);
707 internal_flags[flag] = AddGlobalVariable(Name(id, names[flag])); 713 internal_flags[flag] = AddGlobalVariable(Name(id, names[flag]));
708 } 714 }
@@ -2798,7 +2804,6 @@ private:
2798 std::map<GlobalMemoryBase, Id> global_buffers; 2804 std::map<GlobalMemoryBase, Id> global_buffers;
2799 std::map<u32, TexelBuffer> uniform_texels; 2805 std::map<u32, TexelBuffer> uniform_texels;
2800 std::map<u32, SampledImage> sampled_images; 2806 std::map<u32, SampledImage> sampled_images;
2801 std::map<u32, TexelBuffer> storage_texels;
2802 std::map<u32, StorageImage> images; 2807 std::map<u32, StorageImage> images;
2803 2808
2804 std::array<Id, Maxwell::NumRenderTargets> frag_colors{}; 2809 std::array<Id, Maxwell::NumRenderTargets> frag_colors{};
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index 9bc18c21a..d102e6d27 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -235,7 +235,7 @@ void CachedSurface::UploadTexture(const std::vector<u8>& staging_buffer) {
235void CachedSurface::DownloadTexture(std::vector<u8>& staging_buffer) { 235void CachedSurface::DownloadTexture(std::vector<u8>& staging_buffer) {
236 UNIMPLEMENTED_IF(params.IsBuffer()); 236 UNIMPLEMENTED_IF(params.IsBuffer());
237 237
238 if (params.pixel_format == VideoCore::Surface::PixelFormat::A1B5G5R5U) { 238 if (params.pixel_format == VideoCore::Surface::PixelFormat::A1B5G5R5_UNORM) {
239 LOG_WARNING(Render_Vulkan, "A1B5G5R5 flushing is stubbed"); 239 LOG_WARNING(Render_Vulkan, "A1B5G5R5 flushing is stubbed");
240 } 240 }
241 241
@@ -385,7 +385,7 @@ VkImageView CachedSurfaceView::GetImageView(SwizzleSource x_source, SwizzleSourc
385 385
386 std::array swizzle{MaxwellToVK::SwizzleSource(x_source), MaxwellToVK::SwizzleSource(y_source), 386 std::array swizzle{MaxwellToVK::SwizzleSource(x_source), MaxwellToVK::SwizzleSource(y_source),
387 MaxwellToVK::SwizzleSource(z_source), MaxwellToVK::SwizzleSource(w_source)}; 387 MaxwellToVK::SwizzleSource(z_source), MaxwellToVK::SwizzleSource(w_source)};
388 if (params.pixel_format == VideoCore::Surface::PixelFormat::A1B5G5R5U) { 388 if (params.pixel_format == VideoCore::Surface::PixelFormat::A1B5G5R5_UNORM) {
389 // A1B5G5R5 is implemented as A1R5G5B5, we have to change the swizzle here. 389 // A1B5G5R5 is implemented as A1R5G5B5, we have to change the swizzle here.
390 std::swap(swizzle[0], swizzle[2]); 390 std::swap(swizzle[0], swizzle[2]);
391 } 391 }
@@ -397,11 +397,11 @@ VkImageView CachedSurfaceView::GetImageView(SwizzleSource x_source, SwizzleSourc
397 UNIMPLEMENTED_IF(x_source != SwizzleSource::R && x_source != SwizzleSource::G); 397 UNIMPLEMENTED_IF(x_source != SwizzleSource::R && x_source != SwizzleSource::G);
398 const bool is_first = x_source == SwizzleSource::R; 398 const bool is_first = x_source == SwizzleSource::R;
399 switch (params.pixel_format) { 399 switch (params.pixel_format) {
400 case VideoCore::Surface::PixelFormat::Z24S8: 400 case VideoCore::Surface::PixelFormat::D24_UNORM_S8_UINT:
401 case VideoCore::Surface::PixelFormat::Z32FS8: 401 case VideoCore::Surface::PixelFormat::D32_FLOAT_S8_UINT:
402 aspect = is_first ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT; 402 aspect = is_first ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT;
403 break; 403 break;
404 case VideoCore::Surface::PixelFormat::S8Z24: 404 case VideoCore::Surface::PixelFormat::S8_UINT_D24_UNORM:
405 aspect = is_first ? VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_DEPTH_BIT; 405 aspect = is_first ? VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_DEPTH_BIT;
406 break; 406 break;
407 default: 407 default:
diff --git a/src/video_core/shader/decode/arithmetic_integer.cpp b/src/video_core/shader/decode/arithmetic_integer.cpp
index a041519b7..73155966f 100644
--- a/src/video_core/shader/decode/arithmetic_integer.cpp
+++ b/src/video_core/shader/decode/arithmetic_integer.cpp
@@ -98,12 +98,12 @@ u32 ShaderIR::DecodeArithmeticInteger(NodeBlock& bb, u32 pc) {
98 op_b = GetOperandAbsNegInteger(op_b, false, instr.iadd3.neg_b, true); 98 op_b = GetOperandAbsNegInteger(op_b, false, instr.iadd3.neg_b, true);
99 op_c = GetOperandAbsNegInteger(op_c, false, instr.iadd3.neg_c, true); 99 op_c = GetOperandAbsNegInteger(op_c, false, instr.iadd3.neg_c, true);
100 100
101 const Node value = [&]() { 101 const Node value = [&] {
102 const Node add_ab = Operation(OperationCode::IAdd, NO_PRECISE, op_a, op_b); 102 Node add_ab = Operation(OperationCode::IAdd, NO_PRECISE, op_a, op_b);
103 if (opcode->get().GetId() != OpCode::Id::IADD3_R) { 103 if (opcode->get().GetId() != OpCode::Id::IADD3_R) {
104 return Operation(OperationCode::IAdd, NO_PRECISE, add_ab, op_c); 104 return Operation(OperationCode::IAdd, NO_PRECISE, add_ab, op_c);
105 } 105 }
106 const Node shifted = [&]() { 106 const Node shifted = [&] {
107 switch (instr.iadd3.mode) { 107 switch (instr.iadd3.mode) {
108 case Tegra::Shader::IAdd3Mode::RightShift: 108 case Tegra::Shader::IAdd3Mode::RightShift:
109 // TODO(tech4me): According to 109 // TODO(tech4me): According to
diff --git a/src/video_core/shader/decode/image.cpp b/src/video_core/shader/decode/image.cpp
index 07778dc3e..e75ca4fdb 100644
--- a/src/video_core/shader/decode/image.cpp
+++ b/src/video_core/shader/decode/image.cpp
@@ -31,11 +31,11 @@ ComponentType GetComponentType(Tegra::Engines::SamplerDescriptor descriptor,
31 std::size_t component) { 31 std::size_t component) {
32 const TextureFormat format{descriptor.format}; 32 const TextureFormat format{descriptor.format};
33 switch (format) { 33 switch (format) {
34 case TextureFormat::R16_G16_B16_A16: 34 case TextureFormat::R16G16B16A16:
35 case TextureFormat::R32_G32_B32_A32: 35 case TextureFormat::R32G32B32A32:
36 case TextureFormat::R32_G32_B32: 36 case TextureFormat::R32G32B32:
37 case TextureFormat::R32_G32: 37 case TextureFormat::R32G32:
38 case TextureFormat::R16_G16: 38 case TextureFormat::R16G16:
39 case TextureFormat::R32: 39 case TextureFormat::R32:
40 case TextureFormat::R16: 40 case TextureFormat::R16:
41 case TextureFormat::R8: 41 case TextureFormat::R8:
@@ -97,7 +97,7 @@ ComponentType GetComponentType(Tegra::Engines::SamplerDescriptor descriptor,
97 break; 97 break;
98 case TextureFormat::B5G6R5: 98 case TextureFormat::B5G6R5:
99 case TextureFormat::B6G5R5: 99 case TextureFormat::B6G5R5:
100 case TextureFormat::BF10GF11RF11: 100 case TextureFormat::B10G11R11:
101 if (component == 0) { 101 if (component == 0) {
102 return descriptor.b_type; 102 return descriptor.b_type;
103 } 103 }
@@ -108,9 +108,9 @@ ComponentType GetComponentType(Tegra::Engines::SamplerDescriptor descriptor,
108 return descriptor.r_type; 108 return descriptor.r_type;
109 } 109 }
110 break; 110 break;
111 case TextureFormat::G8R24: 111 case TextureFormat::R24G8:
112 case TextureFormat::G24R8: 112 case TextureFormat::R8G24:
113 case TextureFormat::G8R8: 113 case TextureFormat::R8G8:
114 case TextureFormat::G4R4: 114 case TextureFormat::G4R4:
115 if (component == 0) { 115 if (component == 0) {
116 return descriptor.g_type; 116 return descriptor.g_type;
@@ -137,15 +137,15 @@ bool IsComponentEnabled(std::size_t component_mask, std::size_t component) {
137 137
138u32 GetComponentSize(TextureFormat format, std::size_t component) { 138u32 GetComponentSize(TextureFormat format, std::size_t component) {
139 switch (format) { 139 switch (format) {
140 case TextureFormat::R32_G32_B32_A32: 140 case TextureFormat::R32G32B32A32:
141 return 32; 141 return 32;
142 case TextureFormat::R16_G16_B16_A16: 142 case TextureFormat::R16G16B16A16:
143 return 16; 143 return 16;
144 case TextureFormat::R32_G32_B32: 144 case TextureFormat::R32G32B32:
145 return component <= 2 ? 32 : 0; 145 return component <= 2 ? 32 : 0;
146 case TextureFormat::R32_G32: 146 case TextureFormat::R32G32:
147 return component <= 1 ? 32 : 0; 147 return component <= 1 ? 32 : 0;
148 case TextureFormat::R16_G16: 148 case TextureFormat::R16G16:
149 return component <= 1 ? 16 : 0; 149 return component <= 1 ? 16 : 0;
150 case TextureFormat::R32: 150 case TextureFormat::R32:
151 return component == 0 ? 32 : 0; 151 return component == 0 ? 32 : 0;
@@ -192,7 +192,7 @@ u32 GetComponentSize(TextureFormat format, std::size_t component) {
192 return 6; 192 return 6;
193 } 193 }
194 return 0; 194 return 0;
195 case TextureFormat::BF10GF11RF11: 195 case TextureFormat::B10G11R11:
196 if (component == 1 || component == 2) { 196 if (component == 1 || component == 2) {
197 return 11; 197 return 11;
198 } 198 }
@@ -200,7 +200,7 @@ u32 GetComponentSize(TextureFormat format, std::size_t component) {
200 return 10; 200 return 10;
201 } 201 }
202 return 0; 202 return 0;
203 case TextureFormat::G8R24: 203 case TextureFormat::R24G8:
204 if (component == 0) { 204 if (component == 0) {
205 return 8; 205 return 8;
206 } 206 }
@@ -208,7 +208,7 @@ u32 GetComponentSize(TextureFormat format, std::size_t component) {
208 return 24; 208 return 24;
209 } 209 }
210 return 0; 210 return 0;
211 case TextureFormat::G24R8: 211 case TextureFormat::R8G24:
212 if (component == 0) { 212 if (component == 0) {
213 return 8; 213 return 8;
214 } 214 }
@@ -216,7 +216,7 @@ u32 GetComponentSize(TextureFormat format, std::size_t component) {
216 return 24; 216 return 24;
217 } 217 }
218 return 0; 218 return 0;
219 case TextureFormat::G8R8: 219 case TextureFormat::R8G8:
220 return (component == 0 || component == 1) ? 8 : 0; 220 return (component == 0 || component == 1) ? 8 : 0;
221 case TextureFormat::G4R4: 221 case TextureFormat::G4R4:
222 return (component == 0 || component == 1) ? 4 : 0; 222 return (component == 0 || component == 1) ? 4 : 0;
@@ -231,25 +231,25 @@ std::size_t GetImageComponentMask(TextureFormat format) {
231 constexpr u8 B = 0b0100; 231 constexpr u8 B = 0b0100;
232 constexpr u8 A = 0b1000; 232 constexpr u8 A = 0b1000;
233 switch (format) { 233 switch (format) {
234 case TextureFormat::R32_G32_B32_A32: 234 case TextureFormat::R32G32B32A32:
235 case TextureFormat::R16_G16_B16_A16: 235 case TextureFormat::R16G16B16A16:
236 case TextureFormat::A8R8G8B8: 236 case TextureFormat::A8R8G8B8:
237 case TextureFormat::A2B10G10R10: 237 case TextureFormat::A2B10G10R10:
238 case TextureFormat::A4B4G4R4: 238 case TextureFormat::A4B4G4R4:
239 case TextureFormat::A5B5G5R1: 239 case TextureFormat::A5B5G5R1:
240 case TextureFormat::A1B5G5R5: 240 case TextureFormat::A1B5G5R5:
241 return std::size_t{R | G | B | A}; 241 return std::size_t{R | G | B | A};
242 case TextureFormat::R32_G32_B32: 242 case TextureFormat::R32G32B32:
243 case TextureFormat::R32_B24G8: 243 case TextureFormat::R32_B24G8:
244 case TextureFormat::B5G6R5: 244 case TextureFormat::B5G6R5:
245 case TextureFormat::B6G5R5: 245 case TextureFormat::B6G5R5:
246 case TextureFormat::BF10GF11RF11: 246 case TextureFormat::B10G11R11:
247 return std::size_t{R | G | B}; 247 return std::size_t{R | G | B};
248 case TextureFormat::R32_G32: 248 case TextureFormat::R32G32:
249 case TextureFormat::R16_G16: 249 case TextureFormat::R16G16:
250 case TextureFormat::G8R24: 250 case TextureFormat::R24G8:
251 case TextureFormat::G24R8: 251 case TextureFormat::R8G24:
252 case TextureFormat::G8R8: 252 case TextureFormat::R8G8:
253 case TextureFormat::G4R4: 253 case TextureFormat::G4R4:
254 return std::size_t{R | G}; 254 return std::size_t{R | G};
255 case TextureFormat::R32: 255 case TextureFormat::R32:
diff --git a/src/video_core/shader/decode/other.cpp b/src/video_core/shader/decode/other.cpp
index c0a8f233f..29a7cfbfe 100644
--- a/src/video_core/shader/decode/other.cpp
+++ b/src/video_core/shader/decode/other.cpp
@@ -75,8 +75,7 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) {
75 const Node value = [this, instr] { 75 const Node value = [this, instr] {
76 switch (instr.sys20) { 76 switch (instr.sys20) {
77 case SystemVariable::LaneId: 77 case SystemVariable::LaneId:
78 LOG_WARNING(HW_GPU, "S2R instruction with LaneId is incomplete"); 78 return Operation(OperationCode::ThreadId);
79 return Immediate(0U);
80 case SystemVariable::InvocationId: 79 case SystemVariable::InvocationId:
81 return Operation(OperationCode::InvocationId); 80 return Operation(OperationCode::InvocationId);
82 case SystemVariable::Ydirection: 81 case SystemVariable::Ydirection:
diff --git a/src/video_core/shader/decode/video.cpp b/src/video_core/shader/decode/video.cpp
index 64ba60ea2..1c0957277 100644
--- a/src/video_core/shader/decode/video.cpp
+++ b/src/video_core/shader/decode/video.cpp
@@ -91,29 +91,28 @@ u32 ShaderIR::DecodeVideo(NodeBlock& bb, u32 pc) {
91 return pc; 91 return pc;
92} 92}
93 93
94Node ShaderIR::GetVideoOperand(Node op, bool is_chunk, bool is_signed, 94Node ShaderIR::GetVideoOperand(Node op, bool is_chunk, bool is_signed, VideoType type,
95 Tegra::Shader::VideoType type, u64 byte_height) { 95 u64 byte_height) {
96 if (!is_chunk) { 96 if (!is_chunk) {
97 return BitfieldExtract(op, static_cast<u32>(byte_height * 8), 8); 97 return BitfieldExtract(op, static_cast<u32>(byte_height * 8), 8);
98 } 98 }
99 const Node zero = Immediate(0);
100 99
101 switch (type) { 100 switch (type) {
102 case Tegra::Shader::VideoType::Size16_Low: 101 case VideoType::Size16_Low:
103 return BitfieldExtract(op, 0, 16); 102 return BitfieldExtract(op, 0, 16);
104 case Tegra::Shader::VideoType::Size16_High: 103 case VideoType::Size16_High:
105 return BitfieldExtract(op, 16, 16); 104 return BitfieldExtract(op, 16, 16);
106 case Tegra::Shader::VideoType::Size32: 105 case VideoType::Size32:
107 // TODO(Rodrigo): From my hardware tests it becomes a bit "mad" when this type is used 106 // TODO(Rodrigo): From my hardware tests it becomes a bit "mad" when this type is used
108 // (1 * 1 + 0 == 0x5b800000). Until a better explanation is found: abort. 107 // (1 * 1 + 0 == 0x5b800000). Until a better explanation is found: abort.
109 UNIMPLEMENTED(); 108 UNIMPLEMENTED();
110 return zero; 109 return Immediate(0);
111 case Tegra::Shader::VideoType::Invalid: 110 case VideoType::Invalid:
112 UNREACHABLE_MSG("Invalid instruction encoding"); 111 UNREACHABLE_MSG("Invalid instruction encoding");
113 return zero; 112 return Immediate(0);
114 default: 113 default:
115 UNREACHABLE(); 114 UNREACHABLE();
116 return zero; 115 return Immediate(0);
117 } 116 }
118} 117}
119 118
diff --git a/src/video_core/shader/decode/xmad.cpp b/src/video_core/shader/decode/xmad.cpp
index c83dc6615..233b8fa42 100644
--- a/src/video_core/shader/decode/xmad.cpp
+++ b/src/video_core/shader/decode/xmad.cpp
@@ -81,20 +81,21 @@ u32 ShaderIR::DecodeXmad(NodeBlock& bb, u32 pc) {
81 SetTemporary(bb, 0, product); 81 SetTemporary(bb, 0, product);
82 product = GetTemporary(0); 82 product = GetTemporary(0);
83 83
84 const Node original_c = op_c; 84 Node original_c = op_c;
85 const Tegra::Shader::XmadMode set_mode = mode; // Workaround to clang compile error 85 const Tegra::Shader::XmadMode set_mode = mode; // Workaround to clang compile error
86 op_c = [&]() { 86 op_c = [&] {
87 switch (set_mode) { 87 switch (set_mode) {
88 case Tegra::Shader::XmadMode::None: 88 case Tegra::Shader::XmadMode::None:
89 return original_c; 89 return original_c;
90 case Tegra::Shader::XmadMode::CLo: 90 case Tegra::Shader::XmadMode::CLo:
91 return BitfieldExtract(original_c, 0, 16); 91 return BitfieldExtract(std::move(original_c), 0, 16);
92 case Tegra::Shader::XmadMode::CHi: 92 case Tegra::Shader::XmadMode::CHi:
93 return BitfieldExtract(original_c, 16, 16); 93 return BitfieldExtract(std::move(original_c), 16, 16);
94 case Tegra::Shader::XmadMode::CBcc: { 94 case Tegra::Shader::XmadMode::CBcc: {
95 const Node shifted_b = SignedOperation(OperationCode::ILogicalShiftLeft, is_signed_b, 95 Node shifted_b = SignedOperation(OperationCode::ILogicalShiftLeft, is_signed_b,
96 original_b, Immediate(16)); 96 original_b, Immediate(16));
97 return SignedOperation(OperationCode::IAdd, is_signed_c, original_c, shifted_b); 97 return SignedOperation(OperationCode::IAdd, is_signed_c, std::move(original_c),
98 std::move(shifted_b));
98 } 99 }
99 case Tegra::Shader::XmadMode::CSfu: { 100 case Tegra::Shader::XmadMode::CSfu: {
100 const Node comp_a = 101 const Node comp_a =
diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp
index e322c3402..29d794b34 100644
--- a/src/video_core/shader/shader_ir.cpp
+++ b/src/video_core/shader/shader_ir.cpp
@@ -112,9 +112,9 @@ Node ShaderIR::GetOutputAttribute(Attribute::Index index, u64 element, Node buff
112} 112}
113 113
114Node ShaderIR::GetInternalFlag(InternalFlag flag, bool negated) const { 114Node ShaderIR::GetInternalFlag(InternalFlag flag, bool negated) const {
115 const Node node = MakeNode<InternalFlagNode>(flag); 115 Node node = MakeNode<InternalFlagNode>(flag);
116 if (negated) { 116 if (negated) {
117 return Operation(OperationCode::LogicalNegate, node); 117 return Operation(OperationCode::LogicalNegate, std::move(node));
118 } 118 }
119 return node; 119 return node;
120} 120}
diff --git a/src/video_core/surface.cpp b/src/video_core/surface.cpp
index bbe93903c..1688267bb 100644
--- a/src/video_core/surface.cpp
+++ b/src/video_core/surface.cpp
@@ -74,117 +74,131 @@ bool SurfaceTargetIsArray(SurfaceTarget target) {
74 74
75PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format) { 75PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format) {
76 switch (format) { 76 switch (format) {
77 case Tegra::DepthFormat::S8_Z24_UNORM: 77 case Tegra::DepthFormat::S8_UINT_Z24_UNORM:
78 return PixelFormat::S8Z24; 78 return PixelFormat::S8_UINT_D24_UNORM;
79 case Tegra::DepthFormat::Z24_S8_UNORM: 79 case Tegra::DepthFormat::D24S8_UNORM:
80 return PixelFormat::Z24S8; 80 return PixelFormat::D24_UNORM_S8_UINT;
81 case Tegra::DepthFormat::Z32_FLOAT: 81 case Tegra::DepthFormat::D32_FLOAT:
82 return PixelFormat::Z32F; 82 return PixelFormat::D32_FLOAT;
83 case Tegra::DepthFormat::Z16_UNORM: 83 case Tegra::DepthFormat::D16_UNORM:
84 return PixelFormat::Z16; 84 return PixelFormat::D16_UNORM;
85 case Tegra::DepthFormat::Z32_S8_X24_FLOAT: 85 case Tegra::DepthFormat::D32_FLOAT_S8X24_UINT:
86 return PixelFormat::Z32FS8; 86 return PixelFormat::D32_FLOAT_S8_UINT;
87 default: 87 default:
88 LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); 88 UNIMPLEMENTED_MSG("Unimplemented format={}", static_cast<u32>(format));
89 UNREACHABLE(); 89 return PixelFormat::S8_UINT_D24_UNORM;
90 return PixelFormat::S8Z24;
91 } 90 }
92} 91}
93 92
94PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format) { 93PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format) {
95 switch (format) { 94 switch (format) {
96 case Tegra::RenderTargetFormat::RGBA8_SRGB: 95 case Tegra::RenderTargetFormat::R32B32G32A32_FLOAT:
97 return PixelFormat::RGBA8_SRGB; 96 return PixelFormat::R32G32B32A32_FLOAT;
98 case Tegra::RenderTargetFormat::RGBA8_UNORM: 97 case Tegra::RenderTargetFormat::R32G32B32A32_SINT:
99 return PixelFormat::ABGR8U; 98 return PixelFormat::R32G32B32A32_SINT;
100 case Tegra::RenderTargetFormat::RGBA8_SNORM: 99 case Tegra::RenderTargetFormat::R32G32B32A32_UINT:
101 return PixelFormat::ABGR8S; 100 return PixelFormat::R32G32B32A32_UINT;
102 case Tegra::RenderTargetFormat::RGBA8_UINT: 101 case Tegra::RenderTargetFormat::R16G16B16A16_UNORM:
103 return PixelFormat::ABGR8UI; 102 return PixelFormat::R16G16B16A16_UNORM;
104 case Tegra::RenderTargetFormat::BGRA8_SRGB: 103 case Tegra::RenderTargetFormat::R16G16B16A16_SNORM:
105 return PixelFormat::BGRA8_SRGB; 104 return PixelFormat::R16G16B16A16_SNORM;
106 case Tegra::RenderTargetFormat::BGRA8_UNORM: 105 case Tegra::RenderTargetFormat::R16G16B16A16_SINT:
107 return PixelFormat::BGRA8; 106 return PixelFormat::R16G16B16A16_SINT;
108 case Tegra::RenderTargetFormat::RGB10_A2_UNORM: 107 case Tegra::RenderTargetFormat::R16G16B16A16_UINT:
109 return PixelFormat::A2B10G10R10U; 108 return PixelFormat::R16G16B16A16_UINT;
110 case Tegra::RenderTargetFormat::RGBA16_FLOAT: 109 case Tegra::RenderTargetFormat::R16G16B16A16_FLOAT:
111 return PixelFormat::RGBA16F; 110 return PixelFormat::R16G16B16A16_FLOAT;
112 case Tegra::RenderTargetFormat::RGBA16_UNORM: 111 case Tegra::RenderTargetFormat::R32G32_FLOAT:
113 return PixelFormat::RGBA16U; 112 return PixelFormat::R32G32_FLOAT;
114 case Tegra::RenderTargetFormat::RGBA16_SNORM: 113 case Tegra::RenderTargetFormat::R32G32_SINT:
115 return PixelFormat::RGBA16S; 114 return PixelFormat::R32G32_SINT;
116 case Tegra::RenderTargetFormat::RGBA16_UINT: 115 case Tegra::RenderTargetFormat::R32G32_UINT:
117 return PixelFormat::RGBA16UI; 116 return PixelFormat::R32G32_UINT;
118 case Tegra::RenderTargetFormat::RGBA32_FLOAT: 117 case Tegra::RenderTargetFormat::R16G16B16X16_FLOAT:
119 return PixelFormat::RGBA32F; 118 return PixelFormat::R16G16B16X16_FLOAT;
120 case Tegra::RenderTargetFormat::RG32_FLOAT: 119 case Tegra::RenderTargetFormat::B8G8R8A8_UNORM:
121 return PixelFormat::RG32F; 120 return PixelFormat::B8G8R8A8_UNORM;
122 case Tegra::RenderTargetFormat::R11G11B10_FLOAT: 121 case Tegra::RenderTargetFormat::B8G8R8A8_SRGB:
123 return PixelFormat::R11FG11FB10F; 122 return PixelFormat::B8G8R8A8_SRGB;
124 case Tegra::RenderTargetFormat::B5G6R5_UNORM: 123 case Tegra::RenderTargetFormat::A2B10G10R10_UNORM:
125 return PixelFormat::B5G6R5U; 124 return PixelFormat::A2B10G10R10_UNORM;
126 case Tegra::RenderTargetFormat::BGR5A1_UNORM: 125 case Tegra::RenderTargetFormat::A2B10G10R10_UINT:
127 return PixelFormat::A1B5G5R5U; 126 return PixelFormat::A2B10G10R10_UINT;
128 case Tegra::RenderTargetFormat::RGBA32_UINT: 127 case Tegra::RenderTargetFormat::A8B8G8R8_UNORM:
129 return PixelFormat::RGBA32UI; 128 return PixelFormat::A8B8G8R8_UNORM;
130 case Tegra::RenderTargetFormat::R8_UNORM: 129 case Tegra::RenderTargetFormat::A8B8G8R8_SRGB:
131 return PixelFormat::R8U; 130 return PixelFormat::A8B8G8R8_SRGB;
132 case Tegra::RenderTargetFormat::R8_UINT: 131 case Tegra::RenderTargetFormat::A8B8G8R8_SNORM:
133 return PixelFormat::R8UI; 132 return PixelFormat::A8B8G8R8_SNORM;
134 case Tegra::RenderTargetFormat::RG16_FLOAT: 133 case Tegra::RenderTargetFormat::A8B8G8R8_SINT:
135 return PixelFormat::RG16F; 134 return PixelFormat::A8B8G8R8_SINT;
136 case Tegra::RenderTargetFormat::RG16_UINT: 135 case Tegra::RenderTargetFormat::A8B8G8R8_UINT:
137 return PixelFormat::RG16UI; 136 return PixelFormat::A8B8G8R8_UINT;
138 case Tegra::RenderTargetFormat::RG16_SINT: 137 case Tegra::RenderTargetFormat::R16G16_UNORM:
139 return PixelFormat::RG16I; 138 return PixelFormat::R16G16_UNORM;
140 case Tegra::RenderTargetFormat::RG16_UNORM: 139 case Tegra::RenderTargetFormat::R16G16_SNORM:
141 return PixelFormat::RG16; 140 return PixelFormat::R16G16_SNORM;
142 case Tegra::RenderTargetFormat::RG16_SNORM: 141 case Tegra::RenderTargetFormat::R16G16_SINT:
143 return PixelFormat::RG16S; 142 return PixelFormat::R16G16_SINT;
144 case Tegra::RenderTargetFormat::RG8_UNORM: 143 case Tegra::RenderTargetFormat::R16G16_UINT:
145 return PixelFormat::RG8U; 144 return PixelFormat::R16G16_UINT;
146 case Tegra::RenderTargetFormat::RG8_SNORM: 145 case Tegra::RenderTargetFormat::R16G16_FLOAT:
147 return PixelFormat::RG8S; 146 return PixelFormat::R16G16_FLOAT;
148 case Tegra::RenderTargetFormat::RG8_UINT: 147 case Tegra::RenderTargetFormat::B10G11R11_FLOAT:
149 return PixelFormat::RG8UI; 148 return PixelFormat::B10G11R11_FLOAT;
150 case Tegra::RenderTargetFormat::R16_FLOAT: 149 case Tegra::RenderTargetFormat::R32_SINT:
151 return PixelFormat::R16F; 150 return PixelFormat::R32_SINT;
151 case Tegra::RenderTargetFormat::R32_UINT:
152 return PixelFormat::R32_UINT;
153 case Tegra::RenderTargetFormat::R32_FLOAT:
154 return PixelFormat::R32_FLOAT;
155 case Tegra::RenderTargetFormat::R5G6B5_UNORM:
156 return PixelFormat::R5G6B5_UNORM;
157 case Tegra::RenderTargetFormat::A1R5G5B5_UNORM:
158 return PixelFormat::A1R5G5B5_UNORM;
159 case Tegra::RenderTargetFormat::R8G8_UNORM:
160 return PixelFormat::R8G8_UNORM;
161 case Tegra::RenderTargetFormat::R8G8_SNORM:
162 return PixelFormat::R8G8_SNORM;
163 case Tegra::RenderTargetFormat::R8G8_SINT:
164 return PixelFormat::R8G8_SINT;
165 case Tegra::RenderTargetFormat::R8G8_UINT:
166 return PixelFormat::R8G8_UINT;
152 case Tegra::RenderTargetFormat::R16_UNORM: 167 case Tegra::RenderTargetFormat::R16_UNORM:
153 return PixelFormat::R16U; 168 return PixelFormat::R16_UNORM;
154 case Tegra::RenderTargetFormat::R16_SNORM: 169 case Tegra::RenderTargetFormat::R16_SNORM:
155 return PixelFormat::R16S; 170 return PixelFormat::R16_SNORM;
156 case Tegra::RenderTargetFormat::R16_UINT:
157 return PixelFormat::R16UI;
158 case Tegra::RenderTargetFormat::R16_SINT: 171 case Tegra::RenderTargetFormat::R16_SINT:
159 return PixelFormat::R16I; 172 return PixelFormat::R16_SINT;
160 case Tegra::RenderTargetFormat::R32_FLOAT: 173 case Tegra::RenderTargetFormat::R16_UINT:
161 return PixelFormat::R32F; 174 return PixelFormat::R16_UINT;
162 case Tegra::RenderTargetFormat::R32_SINT: 175 case Tegra::RenderTargetFormat::R16_FLOAT:
163 return PixelFormat::R32I; 176 return PixelFormat::R16_FLOAT;
164 case Tegra::RenderTargetFormat::R32_UINT: 177 case Tegra::RenderTargetFormat::R8_UNORM:
165 return PixelFormat::R32UI; 178 return PixelFormat::R8_UNORM;
166 case Tegra::RenderTargetFormat::RG32_UINT: 179 case Tegra::RenderTargetFormat::R8_SNORM:
167 return PixelFormat::RG32UI; 180 return PixelFormat::R8_SNORM;
168 case Tegra::RenderTargetFormat::RGBX16_FLOAT: 181 case Tegra::RenderTargetFormat::R8_SINT:
169 return PixelFormat::RGBX16F; 182 return PixelFormat::R8_SINT;
183 case Tegra::RenderTargetFormat::R8_UINT:
184 return PixelFormat::R8_UINT;
170 default: 185 default:
171 LOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format)); 186 UNIMPLEMENTED_MSG("Unimplemented format={}", static_cast<int>(format));
172 UNREACHABLE(); 187 return PixelFormat::A8B8G8R8_UNORM;
173 return PixelFormat::RGBA8_SRGB;
174 } 188 }
175} 189}
176 190
177PixelFormat PixelFormatFromGPUPixelFormat(Tegra::FramebufferConfig::PixelFormat format) { 191PixelFormat PixelFormatFromGPUPixelFormat(Tegra::FramebufferConfig::PixelFormat format) {
178 switch (format) { 192 switch (format) {
179 case Tegra::FramebufferConfig::PixelFormat::ABGR8: 193 case Tegra::FramebufferConfig::PixelFormat::A8B8G8R8_UNORM:
180 return PixelFormat::ABGR8U; 194 return PixelFormat::A8B8G8R8_UNORM;
181 case Tegra::FramebufferConfig::PixelFormat::RGB565: 195 case Tegra::FramebufferConfig::PixelFormat::RGB565_UNORM:
182 return PixelFormat::B5G6R5U; 196 return PixelFormat::R5G6B5_UNORM;
183 case Tegra::FramebufferConfig::PixelFormat::BGRA8: 197 case Tegra::FramebufferConfig::PixelFormat::B8G8R8A8_UNORM:
184 return PixelFormat::BGRA8; 198 return PixelFormat::B8G8R8A8_UNORM;
185 default: 199 default:
186 UNIMPLEMENTED_MSG("Unimplemented format={}", static_cast<u32>(format)); 200 UNIMPLEMENTED_MSG("Unimplemented format={}", static_cast<u32>(format));
187 return PixelFormat::ABGR8U; 201 return PixelFormat::A8B8G8R8_UNORM;
188 } 202 }
189} 203}
190 204
@@ -212,27 +226,27 @@ SurfaceType GetFormatType(PixelFormat pixel_format) {
212 226
213bool IsPixelFormatASTC(PixelFormat format) { 227bool IsPixelFormatASTC(PixelFormat format) {
214 switch (format) { 228 switch (format) {
215 case PixelFormat::ASTC_2D_4X4: 229 case PixelFormat::ASTC_2D_4X4_UNORM:
216 case PixelFormat::ASTC_2D_5X4: 230 case PixelFormat::ASTC_2D_5X4_UNORM:
217 case PixelFormat::ASTC_2D_5X5: 231 case PixelFormat::ASTC_2D_5X5_UNORM:
218 case PixelFormat::ASTC_2D_8X8: 232 case PixelFormat::ASTC_2D_8X8_UNORM:
219 case PixelFormat::ASTC_2D_8X5: 233 case PixelFormat::ASTC_2D_8X5_UNORM:
220 case PixelFormat::ASTC_2D_4X4_SRGB: 234 case PixelFormat::ASTC_2D_4X4_SRGB:
221 case PixelFormat::ASTC_2D_5X4_SRGB: 235 case PixelFormat::ASTC_2D_5X4_SRGB:
222 case PixelFormat::ASTC_2D_5X5_SRGB: 236 case PixelFormat::ASTC_2D_5X5_SRGB:
223 case PixelFormat::ASTC_2D_8X8_SRGB: 237 case PixelFormat::ASTC_2D_8X8_SRGB:
224 case PixelFormat::ASTC_2D_8X5_SRGB: 238 case PixelFormat::ASTC_2D_8X5_SRGB:
225 case PixelFormat::ASTC_2D_10X8: 239 case PixelFormat::ASTC_2D_10X8_UNORM:
226 case PixelFormat::ASTC_2D_10X8_SRGB: 240 case PixelFormat::ASTC_2D_10X8_SRGB:
227 case PixelFormat::ASTC_2D_6X6: 241 case PixelFormat::ASTC_2D_6X6_UNORM:
228 case PixelFormat::ASTC_2D_6X6_SRGB: 242 case PixelFormat::ASTC_2D_6X6_SRGB:
229 case PixelFormat::ASTC_2D_10X10: 243 case PixelFormat::ASTC_2D_10X10_UNORM:
230 case PixelFormat::ASTC_2D_10X10_SRGB: 244 case PixelFormat::ASTC_2D_10X10_SRGB:
231 case PixelFormat::ASTC_2D_12X12: 245 case PixelFormat::ASTC_2D_12X12_UNORM:
232 case PixelFormat::ASTC_2D_12X12_SRGB: 246 case PixelFormat::ASTC_2D_12X12_SRGB:
233 case PixelFormat::ASTC_2D_8X6: 247 case PixelFormat::ASTC_2D_8X6_UNORM:
234 case PixelFormat::ASTC_2D_8X6_SRGB: 248 case PixelFormat::ASTC_2D_8X6_SRGB:
235 case PixelFormat::ASTC_2D_6X5: 249 case PixelFormat::ASTC_2D_6X5_UNORM:
236 case PixelFormat::ASTC_2D_6X5_SRGB: 250 case PixelFormat::ASTC_2D_6X5_SRGB:
237 return true; 251 return true;
238 default: 252 default:
@@ -242,12 +256,12 @@ bool IsPixelFormatASTC(PixelFormat format) {
242 256
243bool IsPixelFormatSRGB(PixelFormat format) { 257bool IsPixelFormatSRGB(PixelFormat format) {
244 switch (format) { 258 switch (format) {
245 case PixelFormat::RGBA8_SRGB: 259 case PixelFormat::A8B8G8R8_SRGB:
246 case PixelFormat::BGRA8_SRGB: 260 case PixelFormat::B8G8R8A8_SRGB:
247 case PixelFormat::DXT1_SRGB: 261 case PixelFormat::BC1_RGBA_SRGB:
248 case PixelFormat::DXT23_SRGB: 262 case PixelFormat::BC2_SRGB:
249 case PixelFormat::DXT45_SRGB: 263 case PixelFormat::BC3_SRGB:
250 case PixelFormat::BC7U_SRGB: 264 case PixelFormat::BC7_SRGB:
251 case PixelFormat::ASTC_2D_4X4_SRGB: 265 case PixelFormat::ASTC_2D_4X4_SRGB:
252 case PixelFormat::ASTC_2D_8X8_SRGB: 266 case PixelFormat::ASTC_2D_8X8_SRGB:
253 case PixelFormat::ASTC_2D_8X5_SRGB: 267 case PixelFormat::ASTC_2D_8X5_SRGB:
@@ -269,25 +283,4 @@ std::pair<u32, u32> GetASTCBlockSize(PixelFormat format) {
269 return {GetDefaultBlockWidth(format), GetDefaultBlockHeight(format)}; 283 return {GetDefaultBlockWidth(format), GetDefaultBlockHeight(format)};
270} 284}
271 285
272bool IsFormatBCn(PixelFormat format) {
273 switch (format) {
274 case PixelFormat::DXT1:
275 case PixelFormat::DXT23:
276 case PixelFormat::DXT45:
277 case PixelFormat::DXN1:
278 case PixelFormat::DXN2SNORM:
279 case PixelFormat::DXN2UNORM:
280 case PixelFormat::BC7U:
281 case PixelFormat::BC6H_UF16:
282 case PixelFormat::BC6H_SF16:
283 case PixelFormat::DXT1_SRGB:
284 case PixelFormat::DXT23_SRGB:
285 case PixelFormat::DXT45_SRGB:
286 case PixelFormat::BC7U_SRGB:
287 return true;
288 default:
289 return false;
290 }
291}
292
293} // namespace VideoCore::Surface 286} // namespace VideoCore::Surface
diff --git a/src/video_core/surface.h b/src/video_core/surface.h
index 6da6a1b97..cfd12fa61 100644
--- a/src/video_core/surface.h
+++ b/src/video_core/surface.h
@@ -15,94 +15,105 @@
15namespace VideoCore::Surface { 15namespace VideoCore::Surface {
16 16
17enum class PixelFormat { 17enum class PixelFormat {
18 ABGR8U = 0, 18 A8B8G8R8_UNORM,
19 ABGR8S = 1, 19 A8B8G8R8_SNORM,
20 ABGR8UI = 2, 20 A8B8G8R8_SINT,
21 B5G6R5U = 3, 21 A8B8G8R8_UINT,
22 A2B10G10R10U = 4, 22 R5G6B5_UNORM,
23 A1B5G5R5U = 5, 23 B5G6R5_UNORM,
24 R8U = 6, 24 A1R5G5B5_UNORM,
25 R8UI = 7, 25 A2B10G10R10_UNORM,
26 RGBA16F = 8, 26 A2B10G10R10_UINT,
27 RGBA16U = 9, 27 A1B5G5R5_UNORM,
28 RGBA16S = 10, 28 R8_UNORM,
29 RGBA16UI = 11, 29 R8_SNORM,
30 R11FG11FB10F = 12, 30 R8_SINT,
31 RGBA32UI = 13, 31 R8_UINT,
32 DXT1 = 14, 32 R16G16B16A16_FLOAT,
33 DXT23 = 15, 33 R16G16B16A16_UNORM,
34 DXT45 = 16, 34 R16G16B16A16_SNORM,
35 DXN1 = 17, // This is also known as BC4 35 R16G16B16A16_SINT,
36 DXN2UNORM = 18, 36 R16G16B16A16_UINT,
37 DXN2SNORM = 19, 37 B10G11R11_FLOAT,
38 BC7U = 20, 38 R32G32B32A32_UINT,
39 BC6H_UF16 = 21, 39 BC1_RGBA_UNORM,
40 BC6H_SF16 = 22, 40 BC2_UNORM,
41 ASTC_2D_4X4 = 23, 41 BC3_UNORM,
42 BGRA8 = 24, 42 BC4_UNORM,
43 RGBA32F = 25, 43 BC4_SNORM,
44 RG32F = 26, 44 BC5_UNORM,
45 R32F = 27, 45 BC5_SNORM,
46 R16F = 28, 46 BC7_UNORM,
47 R16U = 29, 47 BC6H_UFLOAT,
48 R16S = 30, 48 BC6H_SFLOAT,
49 R16UI = 31, 49 ASTC_2D_4X4_UNORM,
50 R16I = 32, 50 B8G8R8A8_UNORM,
51 RG16 = 33, 51 R32G32B32A32_FLOAT,
52 RG16F = 34, 52 R32G32B32A32_SINT,
53 RG16UI = 35, 53 R32G32_FLOAT,
54 RG16I = 36, 54 R32G32_SINT,
55 RG16S = 37, 55 R32_FLOAT,
56 RGB32F = 38, 56 R16_FLOAT,
57 RGBA8_SRGB = 39, 57 R16_UNORM,
58 RG8U = 40, 58 R16_SNORM,
59 RG8S = 41, 59 R16_UINT,
60 RG8UI = 42, 60 R16_SINT,
61 RG32UI = 43, 61 R16G16_UNORM,
62 RGBX16F = 44, 62 R16G16_FLOAT,
63 R32UI = 45, 63 R16G16_UINT,
64 R32I = 46, 64 R16G16_SINT,
65 ASTC_2D_8X8 = 47, 65 R16G16_SNORM,
66 ASTC_2D_8X5 = 48, 66 R32G32B32_FLOAT,
67 ASTC_2D_5X4 = 49, 67 A8B8G8R8_SRGB,
68 BGRA8_SRGB = 50, 68 R8G8_UNORM,
69 DXT1_SRGB = 51, 69 R8G8_SNORM,
70 DXT23_SRGB = 52, 70 R8G8_SINT,
71 DXT45_SRGB = 53, 71 R8G8_UINT,
72 BC7U_SRGB = 54, 72 R32G32_UINT,
73 R4G4B4A4U = 55, 73 R16G16B16X16_FLOAT,
74 ASTC_2D_4X4_SRGB = 56, 74 R32_UINT,
75 ASTC_2D_8X8_SRGB = 57, 75 R32_SINT,
76 ASTC_2D_8X5_SRGB = 58, 76 ASTC_2D_8X8_UNORM,
77 ASTC_2D_5X4_SRGB = 59, 77 ASTC_2D_8X5_UNORM,
78 ASTC_2D_5X5 = 60, 78 ASTC_2D_5X4_UNORM,
79 ASTC_2D_5X5_SRGB = 61, 79 B8G8R8A8_SRGB,
80 ASTC_2D_10X8 = 62, 80 BC1_RGBA_SRGB,
81 ASTC_2D_10X8_SRGB = 63, 81 BC2_SRGB,
82 ASTC_2D_6X6 = 64, 82 BC3_SRGB,
83 ASTC_2D_6X6_SRGB = 65, 83 BC7_SRGB,
84 ASTC_2D_10X10 = 66, 84 A4B4G4R4_UNORM,
85 ASTC_2D_10X10_SRGB = 67, 85 ASTC_2D_4X4_SRGB,
86 ASTC_2D_12X12 = 68, 86 ASTC_2D_8X8_SRGB,
87 ASTC_2D_12X12_SRGB = 69, 87 ASTC_2D_8X5_SRGB,
88 ASTC_2D_8X6 = 70, 88 ASTC_2D_5X4_SRGB,
89 ASTC_2D_8X6_SRGB = 71, 89 ASTC_2D_5X5_UNORM,
90 ASTC_2D_6X5 = 72, 90 ASTC_2D_5X5_SRGB,
91 ASTC_2D_6X5_SRGB = 73, 91 ASTC_2D_10X8_UNORM,
92 E5B9G9R9F = 74, 92 ASTC_2D_10X8_SRGB,
93 ASTC_2D_6X6_UNORM,
94 ASTC_2D_6X6_SRGB,
95 ASTC_2D_10X10_UNORM,
96 ASTC_2D_10X10_SRGB,
97 ASTC_2D_12X12_UNORM,
98 ASTC_2D_12X12_SRGB,
99 ASTC_2D_8X6_UNORM,
100 ASTC_2D_8X6_SRGB,
101 ASTC_2D_6X5_UNORM,
102 ASTC_2D_6X5_SRGB,
103 E5B9G9R9_FLOAT,
93 104
94 MaxColorFormat, 105 MaxColorFormat,
95 106
96 // Depth formats 107 // Depth formats
97 Z32F = 75, 108 D32_FLOAT = MaxColorFormat,
98 Z16 = 76, 109 D16_UNORM,
99 110
100 MaxDepthFormat, 111 MaxDepthFormat,
101 112
102 // DepthStencil formats 113 // DepthStencil formats
103 Z24S8 = 77, 114 D24_UNORM_S8_UINT = MaxDepthFormat,
104 S8Z24 = 78, 115 S8_UINT_D24_UNORM,
105 Z32FS8 = 79, 116 D32_FLOAT_S8_UINT,
106 117
107 MaxDepthStencilFormat, 118 MaxDepthStencilFormat,
108 119
@@ -130,86 +141,97 @@ enum class SurfaceTarget {
130}; 141};
131 142
132constexpr std::array<u32, MaxPixelFormat> compression_factor_shift_table = {{ 143constexpr std::array<u32, MaxPixelFormat> compression_factor_shift_table = {{
133 0, // ABGR8U 144 0, // A8B8G8R8_UNORM
134 0, // ABGR8S 145 0, // A8B8G8R8_SNORM
135 0, // ABGR8UI 146 0, // A8B8G8R8_SINT
136 0, // B5G6R5U 147 0, // A8B8G8R8_UINT
137 0, // A2B10G10R10U 148 0, // R5G6B5_UNORM
138 0, // A1B5G5R5U 149 0, // B5G6R5_UNORM
139 0, // R8U 150 0, // A1R5G5B5_UNORM
140 0, // R8UI 151 0, // A2B10G10R10_UNORM
141 0, // RGBA16F 152 0, // A2B10G10R10_UINT
142 0, // RGBA16U 153 0, // A1B5G5R5_UNORM
143 0, // RGBA16S 154 0, // R8_UNORM
144 0, // RGBA16UI 155 0, // R8_SNORM
145 0, // R11FG11FB10F 156 0, // R8_SINT
146 0, // RGBA32UI 157 0, // R8_UINT
147 2, // DXT1 158 0, // R16G16B16A16_FLOAT
148 2, // DXT23 159 0, // R16G16B16A16_UNORM
149 2, // DXT45 160 0, // R16G16B16A16_SNORM
150 2, // DXN1 161 0, // R16G16B16A16_SINT
151 2, // DXN2UNORM 162 0, // R16G16B16A16_UINT
152 2, // DXN2SNORM 163 0, // B10G11R11_FLOAT
153 2, // BC7U 164 0, // R32G32B32A32_UINT
154 2, // BC6H_UF16 165 2, // BC1_RGBA_UNORM
155 2, // BC6H_SF16 166 2, // BC2_UNORM
156 2, // ASTC_2D_4X4 167 2, // BC3_UNORM
157 0, // BGRA8 168 2, // BC4_UNORM
158 0, // RGBA32F 169 2, // BC4_SNORM
159 0, // RG32F 170 2, // BC5_UNORM
160 0, // R32F 171 2, // BC5_SNORM
161 0, // R16F 172 2, // BC7_UNORM
162 0, // R16U 173 2, // BC6H_UFLOAT
163 0, // R16S 174 2, // BC6H_SFLOAT
164 0, // R16UI 175 2, // ASTC_2D_4X4_UNORM
165 0, // R16I 176 0, // B8G8R8A8_UNORM
166 0, // RG16 177 0, // R32G32B32A32_FLOAT
167 0, // RG16F 178 0, // R32G32B32A32_SINT
168 0, // RG16UI 179 0, // R32G32_FLOAT
169 0, // RG16I 180 0, // R32G32_SINT
170 0, // RG16S 181 0, // R32_FLOAT
171 0, // RGB32F 182 0, // R16_FLOAT
172 0, // RGBA8_SRGB 183 0, // R16_UNORM
173 0, // RG8U 184 0, // R16_SNORM
174 0, // RG8S 185 0, // R16_UINT
175 0, // RG8UI 186 0, // R16_SINT
176 0, // RG32UI 187 0, // R16G16_UNORM
177 0, // RGBX16F 188 0, // R16G16_FLOAT
178 0, // R32UI 189 0, // R16G16_UINT
179 0, // R32I 190 0, // R16G16_SINT
180 2, // ASTC_2D_8X8 191 0, // R16G16_SNORM
181 2, // ASTC_2D_8X5 192 0, // R32G32B32_FLOAT
182 2, // ASTC_2D_5X4 193 0, // A8B8G8R8_SRGB
183 0, // BGRA8_SRGB 194 0, // R8G8_UNORM
184 2, // DXT1_SRGB 195 0, // R8G8_SNORM
185 2, // DXT23_SRGB 196 0, // R8G8_SINT
186 2, // DXT45_SRGB 197 0, // R8G8_UINT
187 2, // BC7U_SRGB 198 0, // R32G32_UINT
188 0, // R4G4B4A4U 199 0, // R16G16B16X16_FLOAT
200 0, // R32_UINT
201 0, // R32_SINT
202 2, // ASTC_2D_8X8_UNORM
203 2, // ASTC_2D_8X5_UNORM
204 2, // ASTC_2D_5X4_UNORM
205 0, // B8G8R8A8_SRGB
206 2, // BC1_RGBA_SRGB
207 2, // BC2_SRGB
208 2, // BC3_SRGB
209 2, // BC7_SRGB
210 0, // A4B4G4R4_UNORM
189 2, // ASTC_2D_4X4_SRGB 211 2, // ASTC_2D_4X4_SRGB
190 2, // ASTC_2D_8X8_SRGB 212 2, // ASTC_2D_8X8_SRGB
191 2, // ASTC_2D_8X5_SRGB 213 2, // ASTC_2D_8X5_SRGB
192 2, // ASTC_2D_5X4_SRGB 214 2, // ASTC_2D_5X4_SRGB
193 2, // ASTC_2D_5X5 215 2, // ASTC_2D_5X5_UNORM
194 2, // ASTC_2D_5X5_SRGB 216 2, // ASTC_2D_5X5_SRGB
195 2, // ASTC_2D_10X8 217 2, // ASTC_2D_10X8_UNORM
196 2, // ASTC_2D_10X8_SRGB 218 2, // ASTC_2D_10X8_SRGB
197 2, // ASTC_2D_6X6 219 2, // ASTC_2D_6X6_UNORM
198 2, // ASTC_2D_6X6_SRGB 220 2, // ASTC_2D_6X6_SRGB
199 2, // ASTC_2D_10X10 221 2, // ASTC_2D_10X10_UNORM
200 2, // ASTC_2D_10X10_SRGB 222 2, // ASTC_2D_10X10_SRGB
201 2, // ASTC_2D_12X12 223 2, // ASTC_2D_12X12_UNORM
202 2, // ASTC_2D_12X12_SRGB 224 2, // ASTC_2D_12X12_SRGB
203 2, // ASTC_2D_8X6 225 2, // ASTC_2D_8X6_UNORM
204 2, // ASTC_2D_8X6_SRGB 226 2, // ASTC_2D_8X6_SRGB
205 2, // ASTC_2D_6X5 227 2, // ASTC_2D_6X5_UNORM
206 2, // ASTC_2D_6X5_SRGB 228 2, // ASTC_2D_6X5_SRGB
207 0, // E5B9G9R9F 229 0, // E5B9G9R9_FLOAT
208 0, // Z32F 230 0, // D32_FLOAT
209 0, // Z16 231 0, // D16_UNORM
210 0, // Z24S8 232 0, // D24_UNORM_S8_UINT
211 0, // S8Z24 233 0, // S8_UINT_D24_UNORM
212 0, // Z32FS8 234 0, // D32_FLOAT_S8_UINT
213}}; 235}};
214 236
215/** 237/**
@@ -229,86 +251,97 @@ inline constexpr u32 GetCompressionFactor(PixelFormat format) {
229} 251}
230 252
231constexpr std::array<u32, MaxPixelFormat> block_width_table = {{ 253constexpr std::array<u32, MaxPixelFormat> block_width_table = {{
232 1, // ABGR8U 254 1, // A8B8G8R8_UNORM
233 1, // ABGR8S 255 1, // A8B8G8R8_SNORM
234 1, // ABGR8UI 256 1, // A8B8G8R8_SINT
235 1, // B5G6R5U 257 1, // A8B8G8R8_UINT
236 1, // A2B10G10R10U 258 1, // R5G6B5_UNORM
237 1, // A1B5G5R5U 259 1, // B5G6R5_UNORM
238 1, // R8U 260 1, // A1R5G5B5_UNORM
239 1, // R8UI 261 1, // A2B10G10R10_UNORM
240 1, // RGBA16F 262 1, // A2B10G10R10_UINT
241 1, // RGBA16U 263 1, // A1B5G5R5_UNORM
242 1, // RGBA16S 264 1, // R8_UNORM
243 1, // RGBA16UI 265 1, // R8_SNORM
244 1, // R11FG11FB10F 266 1, // R8_SINT
245 1, // RGBA32UI 267 1, // R8_UINT
246 4, // DXT1 268 1, // R16G16B16A16_FLOAT
247 4, // DXT23 269 1, // R16G16B16A16_UNORM
248 4, // DXT45 270 1, // R16G16B16A16_SNORM
249 4, // DXN1 271 1, // R16G16B16A16_SINT
250 4, // DXN2UNORM 272 1, // R16G16B16A16_UINT
251 4, // DXN2SNORM 273 1, // B10G11R11_FLOAT
252 4, // BC7U 274 1, // R32G32B32A32_UINT
253 4, // BC6H_UF16 275 4, // BC1_RGBA_UNORM
254 4, // BC6H_SF16 276 4, // BC2_UNORM
255 4, // ASTC_2D_4X4 277 4, // BC3_UNORM
256 1, // BGRA8 278 4, // BC4_UNORM
257 1, // RGBA32F 279 4, // BC4_SNORM
258 1, // RG32F 280 4, // BC5_UNORM
259 1, // R32F 281 4, // BC5_SNORM
260 1, // R16F 282 4, // BC7_UNORM
261 1, // R16U 283 4, // BC6H_UFLOAT
262 1, // R16S 284 4, // BC6H_SFLOAT
263 1, // R16UI 285 4, // ASTC_2D_4X4_UNORM
264 1, // R16I 286 1, // B8G8R8A8_UNORM
265 1, // RG16 287 1, // R32G32B32A32_FLOAT
266 1, // RG16F 288 1, // R32G32B32A32_SINT
267 1, // RG16UI 289 1, // R32G32_FLOAT
268 1, // RG16I 290 1, // R32G32_SINT
269 1, // RG16S 291 1, // R32_FLOAT
270 1, // RGB32F 292 1, // R16_FLOAT
271 1, // RGBA8_SRGB 293 1, // R16_UNORM
272 1, // RG8U 294 1, // R16_SNORM
273 1, // RG8S 295 1, // R16_UINT
274 1, // RG8UI 296 1, // R16_SINT
275 1, // RG32UI 297 1, // R16G16_UNORM
276 1, // RGBX16F 298 1, // R16G16_FLOAT
277 1, // R32UI 299 1, // R16G16_UINT
278 1, // R32I 300 1, // R16G16_SINT
279 8, // ASTC_2D_8X8 301 1, // R16G16_SNORM
280 8, // ASTC_2D_8X5 302 1, // R32G32B32_FLOAT
281 5, // ASTC_2D_5X4 303 1, // A8B8G8R8_SRGB
282 1, // BGRA8_SRGB 304 1, // R8G8_UNORM
283 4, // DXT1_SRGB 305 1, // R8G8_SNORM
284 4, // DXT23_SRGB 306 1, // R8G8_SINT
285 4, // DXT45_SRGB 307 1, // R8G8_UINT
286 4, // BC7U_SRGB 308 1, // R32G32_UINT
287 1, // R4G4B4A4U 309 1, // R16G16B16X16_FLOAT
310 1, // R32_UINT
311 1, // R32_SINT
312 8, // ASTC_2D_8X8_UNORM
313 8, // ASTC_2D_8X5_UNORM
314 5, // ASTC_2D_5X4_UNORM
315 1, // B8G8R8A8_SRGB
316 4, // BC1_RGBA_SRGB
317 4, // BC2_SRGB
318 4, // BC3_SRGB
319 4, // BC7_SRGB
320 1, // A4B4G4R4_UNORM
288 4, // ASTC_2D_4X4_SRGB 321 4, // ASTC_2D_4X4_SRGB
289 8, // ASTC_2D_8X8_SRGB 322 8, // ASTC_2D_8X8_SRGB
290 8, // ASTC_2D_8X5_SRGB 323 8, // ASTC_2D_8X5_SRGB
291 5, // ASTC_2D_5X4_SRGB 324 5, // ASTC_2D_5X4_SRGB
292 5, // ASTC_2D_5X5 325 5, // ASTC_2D_5X5_UNORM
293 5, // ASTC_2D_5X5_SRGB 326 5, // ASTC_2D_5X5_SRGB
294 10, // ASTC_2D_10X8 327 10, // ASTC_2D_10X8_UNORM
295 10, // ASTC_2D_10X8_SRGB 328 10, // ASTC_2D_10X8_SRGB
296 6, // ASTC_2D_6X6 329 6, // ASTC_2D_6X6_UNORM
297 6, // ASTC_2D_6X6_SRGB 330 6, // ASTC_2D_6X6_SRGB
298 10, // ASTC_2D_10X10 331 10, // ASTC_2D_10X10_UNORM
299 10, // ASTC_2D_10X10_SRGB 332 10, // ASTC_2D_10X10_SRGB
300 12, // ASTC_2D_12X12 333 12, // ASTC_2D_12X12_UNORM
301 12, // ASTC_2D_12X12_SRGB 334 12, // ASTC_2D_12X12_SRGB
302 8, // ASTC_2D_8X6 335 8, // ASTC_2D_8X6_UNORM
303 8, // ASTC_2D_8X6_SRGB 336 8, // ASTC_2D_8X6_SRGB
304 6, // ASTC_2D_6X5 337 6, // ASTC_2D_6X5_UNORM
305 6, // ASTC_2D_6X5_SRGB 338 6, // ASTC_2D_6X5_SRGB
306 1, // E5B9G9R9F 339 1, // E5B9G9R9_FLOAT
307 1, // Z32F 340 1, // D32_FLOAT
308 1, // Z16 341 1, // D16_UNORM
309 1, // Z24S8 342 1, // D24_UNORM_S8_UINT
310 1, // S8Z24 343 1, // S8_UINT_D24_UNORM
311 1, // Z32FS8 344 1, // D32_FLOAT_S8_UINT
312}}; 345}};
313 346
314static constexpr u32 GetDefaultBlockWidth(PixelFormat format) { 347static constexpr u32 GetDefaultBlockWidth(PixelFormat format) {
@@ -320,86 +353,97 @@ static constexpr u32 GetDefaultBlockWidth(PixelFormat format) {
320} 353}
321 354
322constexpr std::array<u32, MaxPixelFormat> block_height_table = {{ 355constexpr std::array<u32, MaxPixelFormat> block_height_table = {{
323 1, // ABGR8U 356 1, // A8B8G8R8_UNORM
324 1, // ABGR8S 357 1, // A8B8G8R8_SNORM
325 1, // ABGR8UI 358 1, // A8B8G8R8_SINT
326 1, // B5G6R5U 359 1, // A8B8G8R8_UINT
327 1, // A2B10G10R10U 360 1, // R5G6B5_UNORM
328 1, // A1B5G5R5U 361 1, // B5G6R5_UNORM
329 1, // R8U 362 1, // A1R5G5B5_UNORM
330 1, // R8UI 363 1, // A2B10G10R10_UNORM
331 1, // RGBA16F 364 1, // A2B10G10R10_UINT
332 1, // RGBA16U 365 1, // A1B5G5R5_UNORM
333 1, // RGBA16S 366 1, // R8_UNORM
334 1, // RGBA16UI 367 1, // R8_SNORM
335 1, // R11FG11FB10F 368 1, // R8_SINT
336 1, // RGBA32UI 369 1, // R8_UINT
337 4, // DXT1 370 1, // R16G16B16A16_FLOAT
338 4, // DXT23 371 1, // R16G16B16A16_UNORM
339 4, // DXT45 372 1, // R16G16B16A16_SNORM
340 4, // DXN1 373 1, // R16G16B16A16_SINT
341 4, // DXN2UNORM 374 1, // R16G16B16A16_UINT
342 4, // DXN2SNORM 375 1, // B10G11R11_FLOAT
343 4, // BC7U 376 1, // R32G32B32A32_UINT
344 4, // BC6H_UF16 377 4, // BC1_RGBA_UNORM
345 4, // BC6H_SF16 378 4, // BC2_UNORM
346 4, // ASTC_2D_4X4 379 4, // BC3_UNORM
347 1, // BGRA8 380 4, // BC4_UNORM
348 1, // RGBA32F 381 4, // BC4_SNORM
349 1, // RG32F 382 4, // BC5_UNORM
350 1, // R32F 383 4, // BC5_SNORM
351 1, // R16F 384 4, // BC7_UNORM
352 1, // R16U 385 4, // BC6H_UFLOAT
353 1, // R16S 386 4, // BC6H_SFLOAT
354 1, // R16UI 387 4, // ASTC_2D_4X4_UNORM
355 1, // R16I 388 1, // B8G8R8A8_UNORM
356 1, // RG16 389 1, // R32G32B32A32_FLOAT
357 1, // RG16F 390 1, // R32G32B32A32_SINT
358 1, // RG16UI 391 1, // R32G32_FLOAT
359 1, // RG16I 392 1, // R32G32_SINT
360 1, // RG16S 393 1, // R32_FLOAT
361 1, // RGB32F 394 1, // R16_FLOAT
362 1, // RGBA8_SRGB 395 1, // R16_UNORM
363 1, // RG8U 396 1, // R16_SNORM
364 1, // RG8S 397 1, // R16_UINT
365 1, // RG8UI 398 1, // R16_SINT
366 1, // RG32UI 399 1, // R16G16_UNORM
367 1, // RGBX16F 400 1, // R16G16_FLOAT
368 1, // R32UI 401 1, // R16G16_UINT
369 1, // R32I 402 1, // R16G16_SINT
370 8, // ASTC_2D_8X8 403 1, // R16G16_SNORM
371 5, // ASTC_2D_8X5 404 1, // R32G32B32_FLOAT
372 4, // ASTC_2D_5X4 405 1, // A8B8G8R8_SRGB
373 1, // BGRA8_SRGB 406 1, // R8G8_UNORM
374 4, // DXT1_SRGB 407 1, // R8G8_SNORM
375 4, // DXT23_SRGB 408 1, // R8G8_SINT
376 4, // DXT45_SRGB 409 1, // R8G8_UINT
377 4, // BC7U_SRGB 410 1, // R32G32_UINT
378 1, // R4G4B4A4U 411 1, // R16G16B16X16_FLOAT
412 1, // R32_UINT
413 1, // R32_SINT
414 8, // ASTC_2D_8X8_UNORM
415 5, // ASTC_2D_8X5_UNORM
416 4, // ASTC_2D_5X4_UNORM
417 1, // B8G8R8A8_SRGB
418 4, // BC1_RGBA_SRGB
419 4, // BC2_SRGB
420 4, // BC3_SRGB
421 4, // BC7_SRGB
422 1, // A4B4G4R4_UNORM
379 4, // ASTC_2D_4X4_SRGB 423 4, // ASTC_2D_4X4_SRGB
380 8, // ASTC_2D_8X8_SRGB 424 8, // ASTC_2D_8X8_SRGB
381 5, // ASTC_2D_8X5_SRGB 425 5, // ASTC_2D_8X5_SRGB
382 4, // ASTC_2D_5X4_SRGB 426 4, // ASTC_2D_5X4_SRGB
383 5, // ASTC_2D_5X5 427 5, // ASTC_2D_5X5_UNORM
384 5, // ASTC_2D_5X5_SRGB 428 5, // ASTC_2D_5X5_SRGB
385 8, // ASTC_2D_10X8 429 8, // ASTC_2D_10X8_UNORM
386 8, // ASTC_2D_10X8_SRGB 430 8, // ASTC_2D_10X8_SRGB
387 6, // ASTC_2D_6X6 431 6, // ASTC_2D_6X6_UNORM
388 6, // ASTC_2D_6X6_SRGB 432 6, // ASTC_2D_6X6_SRGB
389 10, // ASTC_2D_10X10 433 10, // ASTC_2D_10X10_UNORM
390 10, // ASTC_2D_10X10_SRGB 434 10, // ASTC_2D_10X10_SRGB
391 12, // ASTC_2D_12X12 435 12, // ASTC_2D_12X12_UNORM
392 12, // ASTC_2D_12X12_SRGB 436 12, // ASTC_2D_12X12_SRGB
393 6, // ASTC_2D_8X6 437 6, // ASTC_2D_8X6_UNORM
394 6, // ASTC_2D_8X6_SRGB 438 6, // ASTC_2D_8X6_SRGB
395 5, // ASTC_2D_6X5 439 5, // ASTC_2D_6X5_UNORM
396 5, // ASTC_2D_6X5_SRGB 440 5, // ASTC_2D_6X5_SRGB
397 1, // E5B9G9R9F 441 1, // E5B9G9R9_FLOAT
398 1, // Z32F 442 1, // D32_FLOAT
399 1, // Z16 443 1, // D16_UNORM
400 1, // Z24S8 444 1, // D24_UNORM_S8_UINT
401 1, // S8Z24 445 1, // S8_UINT_D24_UNORM
402 1, // Z32FS8 446 1, // D32_FLOAT_S8_UINT
403}}; 447}};
404 448
405static constexpr u32 GetDefaultBlockHeight(PixelFormat format) { 449static constexpr u32 GetDefaultBlockHeight(PixelFormat format) {
@@ -411,86 +455,97 @@ static constexpr u32 GetDefaultBlockHeight(PixelFormat format) {
411} 455}
412 456
413constexpr std::array<u32, MaxPixelFormat> bpp_table = {{ 457constexpr std::array<u32, MaxPixelFormat> bpp_table = {{
414 32, // ABGR8U 458 32, // A8B8G8R8_UNORM
415 32, // ABGR8S 459 32, // A8B8G8R8_SNORM
416 32, // ABGR8UI 460 32, // A8B8G8R8_SINT
417 16, // B5G6R5U 461 32, // A8B8G8R8_UINT
418 32, // A2B10G10R10U 462 16, // R5G6B5_UNORM
419 16, // A1B5G5R5U 463 16, // B5G6R5_UNORM
420 8, // R8U 464 16, // A1R5G5B5_UNORM
421 8, // R8UI 465 32, // A2B10G10R10_UNORM
422 64, // RGBA16F 466 32, // A2B10G10R10_UINT
423 64, // RGBA16U 467 16, // A1B5G5R5_UNORM
424 64, // RGBA16S 468 8, // R8_UNORM
425 64, // RGBA16UI 469 8, // R8_SNORM
426 32, // R11FG11FB10F 470 8, // R8_SINT
427 128, // RGBA32UI 471 8, // R8_UINT
428 64, // DXT1 472 64, // R16G16B16A16_FLOAT
429 128, // DXT23 473 64, // R16G16B16A16_UNORM
430 128, // DXT45 474 64, // R16G16B16A16_SNORM
431 64, // DXN1 475 64, // R16G16B16A16_SINT
432 128, // DXN2UNORM 476 64, // R16G16B16A16_UINT
433 128, // DXN2SNORM 477 32, // B10G11R11_FLOAT
434 128, // BC7U 478 128, // R32G32B32A32_UINT
435 128, // BC6H_UF16 479 64, // BC1_RGBA_UNORM
436 128, // BC6H_SF16 480 128, // BC2_UNORM
437 128, // ASTC_2D_4X4 481 128, // BC3_UNORM
438 32, // BGRA8 482 64, // BC4_UNORM
439 128, // RGBA32F 483 64, // BC4_SNORM
440 64, // RG32F 484 128, // BC5_UNORM
441 32, // R32F 485 128, // BC5_SNORM
442 16, // R16F 486 128, // BC7_UNORM
443 16, // R16U 487 128, // BC6H_UFLOAT
444 16, // R16S 488 128, // BC6H_SFLOAT
445 16, // R16UI 489 128, // ASTC_2D_4X4_UNORM
446 16, // R16I 490 32, // B8G8R8A8_UNORM
447 32, // RG16 491 128, // R32G32B32A32_FLOAT
448 32, // RG16F 492 128, // R32G32B32A32_SINT
449 32, // RG16UI 493 64, // R32G32_FLOAT
450 32, // RG16I 494 64, // R32G32_SINT
451 32, // RG16S 495 32, // R32_FLOAT
452 96, // RGB32F 496 16, // R16_FLOAT
453 32, // RGBA8_SRGB 497 16, // R16_UNORM
454 16, // RG8U 498 16, // R16_SNORM
455 16, // RG8S 499 16, // R16_UINT
456 16, // RG8UI 500 16, // R16_SINT
457 64, // RG32UI 501 32, // R16G16_UNORM
458 64, // RGBX16F 502 32, // R16G16_FLOAT
459 32, // R32UI 503 32, // R16G16_UINT
460 32, // R32I 504 32, // R16G16_SINT
461 128, // ASTC_2D_8X8 505 32, // R16G16_SNORM
462 128, // ASTC_2D_8X5 506 96, // R32G32B32_FLOAT
463 128, // ASTC_2D_5X4 507 32, // A8B8G8R8_SRGB
464 32, // BGRA8_SRGB 508 16, // R8G8_UNORM
465 64, // DXT1_SRGB 509 16, // R8G8_SNORM
466 128, // DXT23_SRGB 510 16, // R8G8_SINT
467 128, // DXT45_SRGB 511 16, // R8G8_UINT
468 128, // BC7U 512 64, // R32G32_UINT
469 16, // R4G4B4A4U 513 64, // R16G16B16X16_FLOAT
514 32, // R32_UINT
515 32, // R32_SINT
516 128, // ASTC_2D_8X8_UNORM
517 128, // ASTC_2D_8X5_UNORM
518 128, // ASTC_2D_5X4_UNORM
519 32, // B8G8R8A8_SRGB
520 64, // BC1_RGBA_SRGB
521 128, // BC2_SRGB
522 128, // BC3_SRGB
523 128, // BC7_UNORM
524 16, // A4B4G4R4_UNORM
470 128, // ASTC_2D_4X4_SRGB 525 128, // ASTC_2D_4X4_SRGB
471 128, // ASTC_2D_8X8_SRGB 526 128, // ASTC_2D_8X8_SRGB
472 128, // ASTC_2D_8X5_SRGB 527 128, // ASTC_2D_8X5_SRGB
473 128, // ASTC_2D_5X4_SRGB 528 128, // ASTC_2D_5X4_SRGB
474 128, // ASTC_2D_5X5 529 128, // ASTC_2D_5X5_UNORM
475 128, // ASTC_2D_5X5_SRGB 530 128, // ASTC_2D_5X5_SRGB
476 128, // ASTC_2D_10X8 531 128, // ASTC_2D_10X8_UNORM
477 128, // ASTC_2D_10X8_SRGB 532 128, // ASTC_2D_10X8_SRGB
478 128, // ASTC_2D_6X6 533 128, // ASTC_2D_6X6_UNORM
479 128, // ASTC_2D_6X6_SRGB 534 128, // ASTC_2D_6X6_SRGB
480 128, // ASTC_2D_10X10 535 128, // ASTC_2D_10X10_UNORM
481 128, // ASTC_2D_10X10_SRGB 536 128, // ASTC_2D_10X10_SRGB
482 128, // ASTC_2D_12X12 537 128, // ASTC_2D_12X12_UNORM
483 128, // ASTC_2D_12X12_SRGB 538 128, // ASTC_2D_12X12_SRGB
484 128, // ASTC_2D_8X6 539 128, // ASTC_2D_8X6_UNORM
485 128, // ASTC_2D_8X6_SRGB 540 128, // ASTC_2D_8X6_SRGB
486 128, // ASTC_2D_6X5 541 128, // ASTC_2D_6X5_UNORM
487 128, // ASTC_2D_6X5_SRGB 542 128, // ASTC_2D_6X5_SRGB
488 32, // E5B9G9R9F 543 32, // E5B9G9R9_FLOAT
489 32, // Z32F 544 32, // D32_FLOAT
490 16, // Z16 545 16, // D16_UNORM
491 32, // Z24S8 546 32, // D24_UNORM_S8_UINT
492 32, // S8Z24 547 32, // S8_UINT_D24_UNORM
493 64, // Z32FS8 548 64, // D32_FLOAT_S8_UINT
494}}; 549}};
495 550
496static constexpr u32 GetFormatBpp(PixelFormat format) { 551static constexpr u32 GetFormatBpp(PixelFormat format) {
@@ -529,7 +584,4 @@ bool IsPixelFormatSRGB(PixelFormat format);
529 584
530std::pair<u32, u32> GetASTCBlockSize(PixelFormat format); 585std::pair<u32, u32> GetASTCBlockSize(PixelFormat format);
531 586
532/// Returns true if the specified PixelFormat is a BCn format, e.g. DXT or DXN
533bool IsFormatBCn(PixelFormat format);
534
535} // namespace VideoCore::Surface 587} // namespace VideoCore::Surface
diff --git a/src/video_core/texture_cache/format_lookup_table.cpp b/src/video_core/texture_cache/format_lookup_table.cpp
index f476f03b0..7d5a75648 100644
--- a/src/video_core/texture_cache/format_lookup_table.cpp
+++ b/src/video_core/texture_cache/format_lookup_table.cpp
@@ -19,8 +19,6 @@ constexpr auto SNORM = ComponentType::SNORM;
19constexpr auto UNORM = ComponentType::UNORM; 19constexpr auto UNORM = ComponentType::UNORM;
20constexpr auto SINT = ComponentType::SINT; 20constexpr auto SINT = ComponentType::SINT;
21constexpr auto UINT = ComponentType::UINT; 21constexpr auto UINT = ComponentType::UINT;
22constexpr auto SNORM_FORCE_FP16 = ComponentType::SNORM_FORCE_FP16;
23constexpr auto UNORM_FORCE_FP16 = ComponentType::UNORM_FORCE_FP16;
24constexpr auto FLOAT = ComponentType::FLOAT; 22constexpr auto FLOAT = ComponentType::FLOAT;
25constexpr bool C = false; // Normal color 23constexpr bool C = false; // Normal color
26constexpr bool S = true; // Srgb 24constexpr bool S = true; // Srgb
@@ -41,119 +39,126 @@ struct Table {
41 ComponentType alpha_component; 39 ComponentType alpha_component;
42 bool is_srgb; 40 bool is_srgb;
43}; 41};
44constexpr std::array<Table, 78> DefinitionTable = {{ 42constexpr std::array<Table, 86> DefinitionTable = {{
45 {TextureFormat::A8R8G8B8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ABGR8U}, 43 {TextureFormat::A8R8G8B8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::A8B8G8R8_UNORM},
46 {TextureFormat::A8R8G8B8, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::ABGR8S}, 44 {TextureFormat::A8R8G8B8, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::A8B8G8R8_SNORM},
47 {TextureFormat::A8R8G8B8, C, UINT, UINT, UINT, UINT, PixelFormat::ABGR8UI}, 45 {TextureFormat::A8R8G8B8, C, UINT, UINT, UINT, UINT, PixelFormat::A8B8G8R8_UINT},
48 {TextureFormat::A8R8G8B8, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::RGBA8_SRGB}, 46 {TextureFormat::A8R8G8B8, C, SINT, SINT, SINT, SINT, PixelFormat::A8B8G8R8_SINT},
47 {TextureFormat::A8R8G8B8, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::A8B8G8R8_SRGB},
49 48
50 {TextureFormat::B5G6R5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::B5G6R5U}, 49 {TextureFormat::B5G6R5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::B5G6R5_UNORM},
51 50
52 {TextureFormat::A2B10G10R10, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::A2B10G10R10U}, 51 {TextureFormat::A2B10G10R10, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::A2B10G10R10_UNORM},
52 {TextureFormat::A2B10G10R10, C, UINT, UINT, UINT, UINT, PixelFormat::A2B10G10R10_UINT},
53 53
54 {TextureFormat::A1B5G5R5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::A1B5G5R5U}, 54 {TextureFormat::A1B5G5R5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::A1B5G5R5_UNORM},
55 55
56 {TextureFormat::A4B4G4R4, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::R4G4B4A4U}, 56 {TextureFormat::A4B4G4R4, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::A4B4G4R4_UNORM},
57 57
58 {TextureFormat::R8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::R8U}, 58 {TextureFormat::R8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::R8_UNORM},
59 {TextureFormat::R8, C, UINT, UINT, UINT, UINT, PixelFormat::R8UI}, 59 {TextureFormat::R8, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::R8_SNORM},
60 {TextureFormat::R8, C, UINT, UINT, UINT, UINT, PixelFormat::R8_UINT},
61 {TextureFormat::R8, C, SINT, SINT, SINT, SINT, PixelFormat::R8_SINT},
60 62
61 {TextureFormat::G8R8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::RG8U}, 63 {TextureFormat::R8G8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::R8G8_UNORM},
62 {TextureFormat::G8R8, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::RG8S}, 64 {TextureFormat::R8G8, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::R8G8_SNORM},
63 {TextureFormat::G8R8, C, UINT, UINT, UINT, UINT, PixelFormat::RG8UI}, 65 {TextureFormat::R8G8, C, UINT, UINT, UINT, UINT, PixelFormat::R8G8_UINT},
66 {TextureFormat::R8G8, C, SINT, SINT, SINT, SINT, PixelFormat::R8G8_SINT},
64 67
65 {TextureFormat::R16_G16_B16_A16, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::RGBA16S}, 68 {TextureFormat::R16G16B16A16, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::R16G16B16A16_SNORM},
66 {TextureFormat::R16_G16_B16_A16, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::RGBA16U}, 69 {TextureFormat::R16G16B16A16, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::R16G16B16A16_UNORM},
67 {TextureFormat::R16_G16_B16_A16, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::RGBA16F}, 70 {TextureFormat::R16G16B16A16, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::R16G16B16A16_FLOAT},
68 {TextureFormat::R16_G16_B16_A16, C, UINT, UINT, UINT, UINT, PixelFormat::RGBA16UI}, 71 {TextureFormat::R16G16B16A16, C, UINT, UINT, UINT, UINT, PixelFormat::R16G16B16A16_UINT},
72 {TextureFormat::R16G16B16A16, C, SINT, SINT, SINT, SINT, PixelFormat::R16G16B16A16_SINT},
69 73
70 {TextureFormat::R16_G16, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::RG16F}, 74 {TextureFormat::R16G16, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::R16G16_FLOAT},
71 {TextureFormat::R16_G16, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::RG16}, 75 {TextureFormat::R16G16, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::R16G16_UNORM},
72 {TextureFormat::R16_G16, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::RG16S}, 76 {TextureFormat::R16G16, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::R16G16_SNORM},
73 {TextureFormat::R16_G16, C, UINT, UINT, UINT, UINT, PixelFormat::RG16UI}, 77 {TextureFormat::R16G16, C, UINT, UINT, UINT, UINT, PixelFormat::R16G16_UINT},
74 {TextureFormat::R16_G16, C, SINT, SINT, SINT, SINT, PixelFormat::RG16I}, 78 {TextureFormat::R16G16, C, SINT, SINT, SINT, SINT, PixelFormat::R16G16_SINT},
75 79
76 {TextureFormat::R16, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::R16F}, 80 {TextureFormat::R16, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::R16_FLOAT},
77 {TextureFormat::R16, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::R16U}, 81 {TextureFormat::R16, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::R16_UNORM},
78 {TextureFormat::R16, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::R16S}, 82 {TextureFormat::R16, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::R16_SNORM},
79 {TextureFormat::R16, C, UINT, UINT, UINT, UINT, PixelFormat::R16UI}, 83 {TextureFormat::R16, C, UINT, UINT, UINT, UINT, PixelFormat::R16_UINT},
80 {TextureFormat::R16, C, SINT, SINT, SINT, SINT, PixelFormat::R16I}, 84 {TextureFormat::R16, C, SINT, SINT, SINT, SINT, PixelFormat::R16_SINT},
81 85
82 {TextureFormat::BF10GF11RF11, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::R11FG11FB10F}, 86 {TextureFormat::B10G11R11, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::B10G11R11_FLOAT},
83 87
84 {TextureFormat::R32_G32_B32_A32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::RGBA32F}, 88 {TextureFormat::R32G32B32A32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::R32G32B32A32_FLOAT},
85 {TextureFormat::R32_G32_B32_A32, C, UINT, UINT, UINT, UINT, PixelFormat::RGBA32UI}, 89 {TextureFormat::R32G32B32A32, C, UINT, UINT, UINT, UINT, PixelFormat::R32G32B32A32_UINT},
90 {TextureFormat::R32G32B32A32, C, SINT, SINT, SINT, SINT, PixelFormat::R32G32B32A32_SINT},
86 91
87 {TextureFormat::R32_G32_B32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::RGB32F}, 92 {TextureFormat::R32G32B32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::R32G32B32_FLOAT},
88 93
89 {TextureFormat::R32_G32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::RG32F}, 94 {TextureFormat::R32G32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::R32G32_FLOAT},
90 {TextureFormat::R32_G32, C, UINT, UINT, UINT, UINT, PixelFormat::RG32UI}, 95 {TextureFormat::R32G32, C, UINT, UINT, UINT, UINT, PixelFormat::R32G32_UINT},
96 {TextureFormat::R32G32, C, SINT, SINT, SINT, SINT, PixelFormat::R32G32_SINT},
91 97
92 {TextureFormat::R32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::R32F}, 98 {TextureFormat::R32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::R32_FLOAT},
93 {TextureFormat::R32, C, UINT, UINT, UINT, UINT, PixelFormat::R32UI}, 99 {TextureFormat::R32, C, UINT, UINT, UINT, UINT, PixelFormat::R32_UINT},
94 {TextureFormat::R32, C, SINT, SINT, SINT, SINT, PixelFormat::R32I}, 100 {TextureFormat::R32, C, SINT, SINT, SINT, SINT, PixelFormat::R32_SINT},
95 101
96 {TextureFormat::E5B9G9R9_SHAREDEXP, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::E5B9G9R9F}, 102 {TextureFormat::E5B9G9R9, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::E5B9G9R9_FLOAT},
97 103
98 {TextureFormat::ZF32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::Z32F}, 104 {TextureFormat::D32, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::D32_FLOAT},
99 {TextureFormat::Z16, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::Z16}, 105 {TextureFormat::D16, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::D16_UNORM},
100 {TextureFormat::S8Z24, C, UINT, UNORM, UNORM, UNORM, PixelFormat::S8Z24}, 106 {TextureFormat::S8D24, C, UINT, UNORM, UNORM, UNORM, PixelFormat::S8_UINT_D24_UNORM},
101 {TextureFormat::G24R8, C, UINT, UNORM, UNORM, UNORM, PixelFormat::S8Z24}, 107 {TextureFormat::R8G24, C, UINT, UNORM, UNORM, UNORM, PixelFormat::S8_UINT_D24_UNORM},
102 {TextureFormat::ZF32_X24S8, C, FLOAT, UINT, UNORM, UNORM, PixelFormat::Z32FS8}, 108 {TextureFormat::D32S8, C, FLOAT, UINT, UNORM, UNORM, PixelFormat::D32_FLOAT_S8_UINT},
103 109
104 {TextureFormat::DXT1, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::DXT1}, 110 {TextureFormat::BC1_RGBA, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC1_RGBA_UNORM},
105 {TextureFormat::DXT1, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::DXT1_SRGB}, 111 {TextureFormat::BC1_RGBA, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC1_RGBA_SRGB},
106 112
107 {TextureFormat::DXT23, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::DXT23}, 113 {TextureFormat::BC2, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC2_UNORM},
108 {TextureFormat::DXT23, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::DXT23_SRGB}, 114 {TextureFormat::BC2, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC2_SRGB},
109 115
110 {TextureFormat::DXT45, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::DXT45}, 116 {TextureFormat::BC3, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC3_UNORM},
111 {TextureFormat::DXT45, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::DXT45_SRGB}, 117 {TextureFormat::BC3, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC3_SRGB},
112 118
113 // TODO: Use a different pixel format for SNORM 119 {TextureFormat::BC4, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC4_UNORM},
114 {TextureFormat::DXN1, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::DXN1}, 120 {TextureFormat::BC4, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::BC4_SNORM},
115 {TextureFormat::DXN1, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::DXN1},
116 121
117 {TextureFormat::DXN2, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::DXN2UNORM}, 122 {TextureFormat::BC5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC5_UNORM},
118 {TextureFormat::DXN2, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::DXN2SNORM}, 123 {TextureFormat::BC5, C, SNORM, SNORM, SNORM, SNORM, PixelFormat::BC5_SNORM},
119 124
120 {TextureFormat::BC7U, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC7U}, 125 {TextureFormat::BC7, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC7_UNORM},
121 {TextureFormat::BC7U, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC7U_SRGB}, 126 {TextureFormat::BC7, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::BC7_SRGB},
122 127
123 {TextureFormat::BC6H_SF16, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::BC6H_SF16}, 128 {TextureFormat::BC6H_SFLOAT, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::BC6H_SFLOAT},
124 {TextureFormat::BC6H_UF16, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::BC6H_UF16}, 129 {TextureFormat::BC6H_UFLOAT, C, FLOAT, FLOAT, FLOAT, FLOAT, PixelFormat::BC6H_UFLOAT},
125 130
126 {TextureFormat::ASTC_2D_4X4, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_4X4}, 131 {TextureFormat::ASTC_2D_4X4, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_4X4_UNORM},
127 {TextureFormat::ASTC_2D_4X4, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_4X4_SRGB}, 132 {TextureFormat::ASTC_2D_4X4, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_4X4_SRGB},
128 133
129 {TextureFormat::ASTC_2D_5X4, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_5X4}, 134 {TextureFormat::ASTC_2D_5X4, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_5X4_UNORM},
130 {TextureFormat::ASTC_2D_5X4, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_5X4_SRGB}, 135 {TextureFormat::ASTC_2D_5X4, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_5X4_SRGB},
131 136
132 {TextureFormat::ASTC_2D_5X5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_5X5}, 137 {TextureFormat::ASTC_2D_5X5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_5X5_UNORM},
133 {TextureFormat::ASTC_2D_5X5, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_5X5_SRGB}, 138 {TextureFormat::ASTC_2D_5X5, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_5X5_SRGB},
134 139
135 {TextureFormat::ASTC_2D_8X8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X8}, 140 {TextureFormat::ASTC_2D_8X8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X8_UNORM},
136 {TextureFormat::ASTC_2D_8X8, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X8_SRGB}, 141 {TextureFormat::ASTC_2D_8X8, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X8_SRGB},
137 142
138 {TextureFormat::ASTC_2D_8X5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X5}, 143 {TextureFormat::ASTC_2D_8X5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X5_UNORM},
139 {TextureFormat::ASTC_2D_8X5, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X5_SRGB}, 144 {TextureFormat::ASTC_2D_8X5, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X5_SRGB},
140 145
141 {TextureFormat::ASTC_2D_10X8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_10X8}, 146 {TextureFormat::ASTC_2D_10X8, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_10X8_UNORM},
142 {TextureFormat::ASTC_2D_10X8, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_10X8_SRGB}, 147 {TextureFormat::ASTC_2D_10X8, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_10X8_SRGB},
143 148
144 {TextureFormat::ASTC_2D_6X6, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_6X6}, 149 {TextureFormat::ASTC_2D_6X6, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_6X6_UNORM},
145 {TextureFormat::ASTC_2D_6X6, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_6X6_SRGB}, 150 {TextureFormat::ASTC_2D_6X6, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_6X6_SRGB},
146 151
147 {TextureFormat::ASTC_2D_10X10, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_10X10}, 152 {TextureFormat::ASTC_2D_10X10, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_10X10_UNORM},
148 {TextureFormat::ASTC_2D_10X10, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_10X10_SRGB}, 153 {TextureFormat::ASTC_2D_10X10, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_10X10_SRGB},
149 154
150 {TextureFormat::ASTC_2D_12X12, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_12X12}, 155 {TextureFormat::ASTC_2D_12X12, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_12X12_UNORM},
151 {TextureFormat::ASTC_2D_12X12, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_12X12_SRGB}, 156 {TextureFormat::ASTC_2D_12X12, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_12X12_SRGB},
152 157
153 {TextureFormat::ASTC_2D_8X6, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X6}, 158 {TextureFormat::ASTC_2D_8X6, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X6_UNORM},
154 {TextureFormat::ASTC_2D_8X6, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X6_SRGB}, 159 {TextureFormat::ASTC_2D_8X6, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_8X6_SRGB},
155 160
156 {TextureFormat::ASTC_2D_6X5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_6X5}, 161 {TextureFormat::ASTC_2D_6X5, C, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_6X5_UNORM},
157 {TextureFormat::ASTC_2D_6X5, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_6X5_SRGB}, 162 {TextureFormat::ASTC_2D_6X5, S, UNORM, UNORM, UNORM, UNORM, PixelFormat::ASTC_2D_6X5_SRGB},
158}}; 163}};
159 164
@@ -184,7 +189,7 @@ PixelFormat FormatLookupTable::GetPixelFormat(TextureFormat format, bool is_srgb
184 static_cast<int>(format), is_srgb, static_cast<int>(red_component), 189 static_cast<int>(format), is_srgb, static_cast<int>(red_component),
185 static_cast<int>(green_component), static_cast<int>(blue_component), 190 static_cast<int>(green_component), static_cast<int>(blue_component),
186 static_cast<int>(alpha_component)); 191 static_cast<int>(alpha_component));
187 return PixelFormat::ABGR8U; 192 return PixelFormat::A8B8G8R8_UNORM;
188} 193}
189 194
190void FormatLookupTable::Set(TextureFormat format, bool is_srgb, ComponentType red_component, 195void FormatLookupTable::Set(TextureFormat format, bool is_srgb, ComponentType red_component,
diff --git a/src/video_core/texture_cache/surface_base.cpp b/src/video_core/texture_cache/surface_base.cpp
index 0caf3b4f0..dfcf36e0b 100644
--- a/src/video_core/texture_cache/surface_base.cpp
+++ b/src/video_core/texture_cache/surface_base.cpp
@@ -228,7 +228,7 @@ void SurfaceBaseImpl::LoadBuffer(Tegra::MemoryManager& memory_manager,
228 } 228 }
229 } 229 }
230 230
231 if (!is_converted && params.pixel_format != PixelFormat::S8Z24) { 231 if (!is_converted && params.pixel_format != PixelFormat::S8_UINT_D24_UNORM) {
232 return; 232 return;
233 } 233 }
234 234
diff --git a/src/video_core/texture_cache/surface_params.cpp b/src/video_core/texture_cache/surface_params.cpp
index 921562c1f..9e5fe2374 100644
--- a/src/video_core/texture_cache/surface_params.cpp
+++ b/src/video_core/texture_cache/surface_params.cpp
@@ -83,12 +83,12 @@ SurfaceParams SurfaceParams::CreateForTexture(const FormatLookupTable& lookup_ta
83 params.type = GetFormatType(params.pixel_format); 83 params.type = GetFormatType(params.pixel_format);
84 if (entry.is_shadow && params.type == SurfaceType::ColorTexture) { 84 if (entry.is_shadow && params.type == SurfaceType::ColorTexture) {
85 switch (params.pixel_format) { 85 switch (params.pixel_format) {
86 case PixelFormat::R16U: 86 case PixelFormat::R16_UNORM:
87 case PixelFormat::R16F: 87 case PixelFormat::R16_FLOAT:
88 params.pixel_format = PixelFormat::Z16; 88 params.pixel_format = PixelFormat::D16_UNORM;
89 break; 89 break;
90 case PixelFormat::R32F: 90 case PixelFormat::R32_FLOAT:
91 params.pixel_format = PixelFormat::Z32F; 91 params.pixel_format = PixelFormat::D32_FLOAT;
92 break; 92 break;
93 default: 93 default:
94 UNIMPLEMENTED_MSG("Unimplemented shadow convert format: {}", 94 UNIMPLEMENTED_MSG("Unimplemented shadow convert format: {}",
@@ -195,8 +195,8 @@ SurfaceParams SurfaceParams::CreateForFramebuffer(Core::System& system, std::siz
195 SurfaceParams params; 195 SurfaceParams params;
196 params.is_tiled = 196 params.is_tiled =
197 config.memory_layout.type == Tegra::Engines::Maxwell3D::Regs::InvMemoryLayout::BlockLinear; 197 config.memory_layout.type == Tegra::Engines::Maxwell3D::Regs::InvMemoryLayout::BlockLinear;
198 params.srgb_conversion = config.format == Tegra::RenderTargetFormat::BGRA8_SRGB || 198 params.srgb_conversion = config.format == Tegra::RenderTargetFormat::B8G8R8A8_SRGB ||
199 config.format == Tegra::RenderTargetFormat::RGBA8_SRGB; 199 config.format == Tegra::RenderTargetFormat::A8B8G8R8_SRGB;
200 params.block_width = config.memory_layout.block_width; 200 params.block_width = config.memory_layout.block_width;
201 params.block_height = config.memory_layout.block_height; 201 params.block_height = config.memory_layout.block_height;
202 params.block_depth = config.memory_layout.block_depth; 202 params.block_depth = config.memory_layout.block_depth;
@@ -235,8 +235,8 @@ SurfaceParams SurfaceParams::CreateForFermiCopySurface(
235 const Tegra::Engines::Fermi2D::Regs::Surface& config) { 235 const Tegra::Engines::Fermi2D::Regs::Surface& config) {
236 SurfaceParams params{}; 236 SurfaceParams params{};
237 params.is_tiled = !config.linear; 237 params.is_tiled = !config.linear;
238 params.srgb_conversion = config.format == Tegra::RenderTargetFormat::BGRA8_SRGB || 238 params.srgb_conversion = config.format == Tegra::RenderTargetFormat::B8G8R8A8_SRGB ||
239 config.format == Tegra::RenderTargetFormat::RGBA8_SRGB; 239 config.format == Tegra::RenderTargetFormat::A8B8G8R8_SRGB;
240 params.block_width = params.is_tiled ? std::min(config.BlockWidth(), 5U) : 0, 240 params.block_width = params.is_tiled ? std::min(config.BlockWidth(), 5U) : 0,
241 params.block_height = params.is_tiled ? std::min(config.BlockHeight(), 5U) : 0, 241 params.block_height = params.is_tiled ? std::min(config.BlockHeight(), 5U) : 0,
242 params.block_depth = params.is_tiled ? std::min(config.BlockDepth(), 5U) : 0, 242 params.block_depth = params.is_tiled ? std::min(config.BlockDepth(), 5U) : 0,
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index cdcddb225..96c4e4cc2 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -373,9 +373,9 @@ protected:
373 siblings_table[static_cast<std::size_t>(b)] = a; 373 siblings_table[static_cast<std::size_t>(b)] = a;
374 }; 374 };
375 std::fill(siblings_table.begin(), siblings_table.end(), PixelFormat::Invalid); 375 std::fill(siblings_table.begin(), siblings_table.end(), PixelFormat::Invalid);
376 make_siblings(PixelFormat::Z16, PixelFormat::R16U); 376 make_siblings(PixelFormat::D16_UNORM, PixelFormat::R16_UNORM);
377 make_siblings(PixelFormat::Z32F, PixelFormat::R32F); 377 make_siblings(PixelFormat::D32_FLOAT, PixelFormat::R32_FLOAT);
378 make_siblings(PixelFormat::Z32FS8, PixelFormat::RG32F); 378 make_siblings(PixelFormat::D32_FLOAT_S8_UINT, PixelFormat::R32G32_FLOAT);
379 379
380 sampled_textures.reserve(64); 380 sampled_textures.reserve(64);
381 } 381 }
@@ -1031,7 +1031,7 @@ private:
1031 params.pitch = 4; 1031 params.pitch = 4;
1032 params.num_levels = 1; 1032 params.num_levels = 1;
1033 params.emulated_levels = 1; 1033 params.emulated_levels = 1;
1034 params.pixel_format = VideoCore::Surface::PixelFormat::R8U; 1034 params.pixel_format = VideoCore::Surface::PixelFormat::R8_UNORM;
1035 params.type = VideoCore::Surface::SurfaceType::ColorTexture; 1035 params.type = VideoCore::Surface::SurfaceType::ColorTexture;
1036 auto surface = CreateSurface(0ULL, params); 1036 auto surface = CreateSurface(0ULL, params);
1037 invalid_memory.resize(surface->GetHostSizeInBytes(), 0U); 1037 invalid_memory.resize(surface->GetHostSizeInBytes(), 0U);
diff --git a/src/video_core/textures/convert.cpp b/src/video_core/textures/convert.cpp
index f3efa7eb0..962921483 100644
--- a/src/video_core/textures/convert.cpp
+++ b/src/video_core/textures/convert.cpp
@@ -35,7 +35,7 @@ void SwapS8Z24ToZ24S8(u8* data, u32 width, u32 height) {
35 S8Z24 s8z24_pixel{}; 35 S8Z24 s8z24_pixel{};
36 Z24S8 z24s8_pixel{}; 36 Z24S8 z24s8_pixel{};
37 constexpr auto bpp{ 37 constexpr auto bpp{
38 VideoCore::Surface::GetBytesPerPixel(VideoCore::Surface::PixelFormat::S8Z24)}; 38 VideoCore::Surface::GetBytesPerPixel(VideoCore::Surface::PixelFormat::S8_UINT_D24_UNORM)};
39 for (std::size_t y = 0; y < height; ++y) { 39 for (std::size_t y = 0; y < height; ++y) {
40 for (std::size_t x = 0; x < width; ++x) { 40 for (std::size_t x = 0; x < width; ++x) {
41 const std::size_t offset{bpp * (y * width + x)}; 41 const std::size_t offset{bpp * (y * width + x)};
@@ -73,7 +73,7 @@ void ConvertFromGuestToHost(u8* in_data, u8* out_data, PixelFormat pixel_format,
73 in_data, width, height, depth, block_width, block_height); 73 in_data, width, height, depth, block_width, block_height);
74 std::copy(rgba8_data.begin(), rgba8_data.end(), out_data); 74 std::copy(rgba8_data.begin(), rgba8_data.end(), out_data);
75 75
76 } else if (convert_s8z24 && pixel_format == PixelFormat::S8Z24) { 76 } else if (convert_s8z24 && pixel_format == PixelFormat::S8_UINT_D24_UNORM) {
77 Tegra::Texture::ConvertS8Z24ToZ24S8(in_data, width, height); 77 Tegra::Texture::ConvertS8Z24ToZ24S8(in_data, width, height);
78 } 78 }
79} 79}
@@ -85,7 +85,7 @@ void ConvertFromHostToGuest(u8* data, PixelFormat pixel_format, u32 width, u32 h
85 static_cast<u32>(pixel_format)); 85 static_cast<u32>(pixel_format));
86 UNREACHABLE(); 86 UNREACHABLE();
87 87
88 } else if (convert_s8z24 && pixel_format == PixelFormat::S8Z24) { 88 } else if (convert_s8z24 && pixel_format == PixelFormat::S8_UINT_D24_UNORM) {
89 Tegra::Texture::ConvertZ24S8ToS8Z24(data, width, height); 89 Tegra::Texture::ConvertZ24S8ToS8Z24(data, width, height);
90 } 90 }
91} 91}
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp
index 98beabef1..474ae620a 100644
--- a/src/video_core/textures/decoders.cpp
+++ b/src/video_core/textures/decoders.cpp
@@ -184,53 +184,6 @@ void CopySwizzledData(u32 width, u32 height, u32 depth, u32 bytes_per_pixel,
184 } 184 }
185} 185}
186 186
187u32 BytesPerPixel(TextureFormat format) {
188 switch (format) {
189 case TextureFormat::DXT1:
190 case TextureFormat::DXN1:
191 // In this case a 'pixel' actually refers to a 4x4 tile.
192 return 8;
193 case TextureFormat::DXT23:
194 case TextureFormat::DXT45:
195 case TextureFormat::DXN2:
196 case TextureFormat::BC7U:
197 case TextureFormat::BC6H_UF16:
198 case TextureFormat::BC6H_SF16:
199 // In this case a 'pixel' actually refers to a 4x4 tile.
200 return 16;
201 case TextureFormat::R32_G32_B32:
202 return 12;
203 case TextureFormat::ASTC_2D_4X4:
204 case TextureFormat::ASTC_2D_5X4:
205 case TextureFormat::ASTC_2D_8X8:
206 case TextureFormat::ASTC_2D_8X5:
207 case TextureFormat::ASTC_2D_10X8:
208 case TextureFormat::ASTC_2D_5X5:
209 case TextureFormat::A8R8G8B8:
210 case TextureFormat::A2B10G10R10:
211 case TextureFormat::BF10GF11RF11:
212 case TextureFormat::R32:
213 case TextureFormat::R16_G16:
214 return 4;
215 case TextureFormat::A1B5G5R5:
216 case TextureFormat::B5G6R5:
217 case TextureFormat::G8R8:
218 case TextureFormat::R16:
219 return 2;
220 case TextureFormat::R8:
221 return 1;
222 case TextureFormat::R16_G16_B16_A16:
223 return 8;
224 case TextureFormat::R32_G32_B32_A32:
225 return 16;
226 case TextureFormat::R32_G32:
227 return 8;
228 default:
229 UNIMPLEMENTED_MSG("Format not implemented");
230 return 1;
231 }
232}
233
234void UnswizzleTexture(u8* const unswizzled_data, u8* address, u32 tile_size_x, u32 tile_size_y, 187void UnswizzleTexture(u8* const unswizzled_data, u8* address, u32 tile_size_x, u32 tile_size_y,
235 u32 bytes_per_pixel, u32 width, u32 height, u32 depth, u32 block_height, 188 u32 bytes_per_pixel, u32 width, u32 height, u32 depth, u32 block_height,
236 u32 block_depth, u32 width_spacing) { 189 u32 block_depth, u32 width_spacing) {
@@ -348,48 +301,6 @@ void SwizzleKepler(const u32 width, const u32 height, const u32 dst_x, const u32
348 } 301 }
349} 302}
350 303
351std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat format, u32 width,
352 u32 height) {
353 std::vector<u8> rgba_data;
354
355 // TODO(Subv): Implement.
356 switch (format) {
357 case TextureFormat::DXT1:
358 case TextureFormat::DXT23:
359 case TextureFormat::DXT45:
360 case TextureFormat::DXN1:
361 case TextureFormat::DXN2:
362 case TextureFormat::BC7U:
363 case TextureFormat::BC6H_UF16:
364 case TextureFormat::BC6H_SF16:
365 case TextureFormat::ASTC_2D_4X4:
366 case TextureFormat::ASTC_2D_8X8:
367 case TextureFormat::ASTC_2D_5X5:
368 case TextureFormat::ASTC_2D_10X8:
369 case TextureFormat::A8R8G8B8:
370 case TextureFormat::A2B10G10R10:
371 case TextureFormat::A1B5G5R5:
372 case TextureFormat::B5G6R5:
373 case TextureFormat::R8:
374 case TextureFormat::G8R8:
375 case TextureFormat::BF10GF11RF11:
376 case TextureFormat::R32_G32_B32_A32:
377 case TextureFormat::R32_G32:
378 case TextureFormat::R32:
379 case TextureFormat::R16:
380 case TextureFormat::R16_G16:
381 case TextureFormat::R32_G32_B32:
382 // TODO(Subv): For the time being just forward the same data without any decoding.
383 rgba_data = texture_data;
384 break;
385 default:
386 UNIMPLEMENTED_MSG("Format not implemented");
387 break;
388 }
389
390 return rgba_data;
391}
392
393std::size_t CalculateSize(bool tiled, u32 bytes_per_pixel, u32 width, u32 height, u32 depth, 304std::size_t CalculateSize(bool tiled, u32 bytes_per_pixel, u32 width, u32 height, u32 depth,
394 u32 block_height, u32 block_depth) { 305 u32 block_height, u32 block_depth) {
395 if (tiled) { 306 if (tiled) {
diff --git a/src/video_core/textures/decoders.h b/src/video_core/textures/decoders.h
index 232b696b3..d6fe35d37 100644
--- a/src/video_core/textures/decoders.h
+++ b/src/video_core/textures/decoders.h
@@ -38,10 +38,6 @@ void CopySwizzledData(u32 width, u32 height, u32 depth, u32 bytes_per_pixel,
38 u32 out_bytes_per_pixel, u8* swizzled_data, u8* unswizzled_data, 38 u32 out_bytes_per_pixel, u8* swizzled_data, u8* unswizzled_data,
39 bool unswizzle, u32 block_height, u32 block_depth, u32 width_spacing); 39 bool unswizzle, u32 block_height, u32 block_depth, u32 width_spacing);
40 40
41/// Decodes an unswizzled texture into a A8R8G8B8 texture.
42std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat format, u32 width,
43 u32 height);
44
45/// This function calculates the correct size of a texture depending if it's tiled or not. 41/// This function calculates the correct size of a texture depending if it's tiled or not.
46std::size_t CalculateSize(bool tiled, u32 bytes_per_pixel, u32 width, u32 height, u32 depth, 42std::size_t CalculateSize(bool tiled, u32 bytes_per_pixel, u32 width, u32 height, u32 depth,
47 u32 block_height, u32 block_depth); 43 u32 block_height, u32 block_depth);
diff --git a/src/video_core/textures/texture.h b/src/video_core/textures/texture.h
index eba05aced..0574fef12 100644
--- a/src/video_core/textures/texture.h
+++ b/src/video_core/textures/texture.h
@@ -12,10 +12,10 @@
12namespace Tegra::Texture { 12namespace Tegra::Texture {
13 13
14enum class TextureFormat : u32 { 14enum class TextureFormat : u32 {
15 R32_G32_B32_A32 = 0x01, 15 R32G32B32A32 = 0x01,
16 R32_G32_B32 = 0x02, 16 R32G32B32 = 0x02,
17 R16_G16_B16_A16 = 0x03, 17 R16G16B16A16 = 0x03,
18 R32_G32 = 0x04, 18 R32G32 = 0x04,
19 R32_B24G8 = 0x05, 19 R32_B24G8 = 0x05,
20 ETC2_RGB = 0x06, 20 ETC2_RGB = 0x06,
21 X8B8G8R8 = 0x07, 21 X8B8G8R8 = 0x07,
@@ -23,19 +23,19 @@ enum class TextureFormat : u32 {
23 A2B10G10R10 = 0x09, 23 A2B10G10R10 = 0x09,
24 ETC2_RGB_PTA = 0x0a, 24 ETC2_RGB_PTA = 0x0a,
25 ETC2_RGBA = 0x0b, 25 ETC2_RGBA = 0x0b,
26 R16_G16 = 0x0c, 26 R16G16 = 0x0c,
27 G8R24 = 0x0d, 27 R24G8 = 0x0d,
28 G24R8 = 0x0e, 28 R8G24 = 0x0e,
29 R32 = 0x0f, 29 R32 = 0x0f,
30 BC6H_SF16 = 0x10, 30 BC6H_SFLOAT = 0x10,
31 BC6H_UF16 = 0x11, 31 BC6H_UFLOAT = 0x11,
32 A4B4G4R4 = 0x12, 32 A4B4G4R4 = 0x12,
33 A5B5G5R1 = 0x13, 33 A5B5G5R1 = 0x13,
34 A1B5G5R5 = 0x14, 34 A1B5G5R5 = 0x14,
35 B5G6R5 = 0x15, 35 B5G6R5 = 0x15,
36 B6G5R5 = 0x16, 36 B6G5R5 = 0x16,
37 BC7U = 0x17, 37 BC7 = 0x17,
38 G8R8 = 0x18, 38 R8G8 = 0x18,
39 EAC = 0x19, 39 EAC = 0x19,
40 EACX2 = 0x1a, 40 EACX2 = 0x1a,
41 R16 = 0x1b, 41 R16 = 0x1b,
@@ -43,23 +43,23 @@ enum class TextureFormat : u32 {
43 R8 = 0x1d, 43 R8 = 0x1d,
44 G4R4 = 0x1e, 44 G4R4 = 0x1e,
45 R1 = 0x1f, 45 R1 = 0x1f,
46 E5B9G9R9_SHAREDEXP = 0x20, 46 E5B9G9R9 = 0x20,
47 BF10GF11RF11 = 0x21, 47 B10G11R11 = 0x21,
48 G8B8G8R8 = 0x22, 48 G8B8G8R8 = 0x22,
49 B8G8R8G8 = 0x23, 49 B8G8R8G8 = 0x23,
50 DXT1 = 0x24, 50 BC1_RGBA = 0x24,
51 DXT23 = 0x25, 51 BC2 = 0x25,
52 DXT45 = 0x26, 52 BC3 = 0x26,
53 DXN1 = 0x27, 53 BC4 = 0x27,
54 DXN2 = 0x28, 54 BC5 = 0x28,
55 S8Z24 = 0x29, 55 S8D24 = 0x29,
56 X8Z24 = 0x2a, 56 X8Z24 = 0x2a,
57 Z24S8 = 0x2b, 57 D24S8 = 0x2b,
58 X4V4Z24__COV4R4V = 0x2c, 58 X4V4Z24__COV4R4V = 0x2c,
59 X4V4Z24__COV8R8V = 0x2d, 59 X4V4Z24__COV8R8V = 0x2d,
60 V8Z24__COV4R12V = 0x2e, 60 V8Z24__COV4R12V = 0x2e,
61 ZF32 = 0x2f, 61 D32 = 0x2f,
62 ZF32_X24S8 = 0x30, 62 D32S8 = 0x30,
63 X8Z24_X20V4S8__COV4R4V = 0x31, 63 X8Z24_X20V4S8__COV4R4V = 0x31,
64 X8Z24_X20V4S8__COV8R8V = 0x32, 64 X8Z24_X20V4S8__COV8R8V = 0x32,
65 ZF32_X20V4X8__COV4R4V = 0x33, 65 ZF32_X20V4X8__COV4R4V = 0x33,
@@ -69,7 +69,7 @@ enum class TextureFormat : u32 {
69 X8Z24_X16V8S8__COV4R12V = 0x37, 69 X8Z24_X16V8S8__COV4R12V = 0x37,
70 ZF32_X16V8X8__COV4R12V = 0x38, 70 ZF32_X16V8X8__COV4R12V = 0x38,
71 ZF32_X16V8S8__COV4R12V = 0x39, 71 ZF32_X16V8S8__COV4R12V = 0x39,
72 Z16 = 0x3a, 72 D16 = 0x3a,
73 V8Z24__COV8R24V = 0x3b, 73 V8Z24__COV8R24V = 0x3b,
74 X8Z24_X16V8S8__COV8R24V = 0x3c, 74 X8Z24_X16V8S8__COV8R24V = 0x3c,
75 ZF32_X16V8X8__COV8R24V = 0x3d, 75 ZF32_X16V8X8__COV8R24V = 0x3d,
@@ -375,7 +375,4 @@ struct FullTextureInfo {
375 TSCEntry tsc; 375 TSCEntry tsc;
376}; 376};
377 377
378/// Returns the number of bytes per pixel of the input texture format.
379u32 BytesPerPixel(TextureFormat format);
380
381} // namespace Tegra::Texture 378} // namespace Tegra::Texture
diff --git a/src/yuzu/configuration/configuration_shared.cpp b/src/yuzu/configuration/configuration_shared.cpp
index bb47c3933..f9becab6e 100644
--- a/src/yuzu/configuration/configuration_shared.cpp
+++ b/src/yuzu/configuration/configuration_shared.cpp
@@ -4,17 +4,20 @@
4 4
5#include <QCheckBox> 5#include <QCheckBox>
6#include <QComboBox> 6#include <QComboBox>
7#include <QObject>
8#include <QString>
7#include "core/settings.h" 9#include "core/settings.h"
8#include "yuzu/configuration/configuration_shared.h" 10#include "yuzu/configuration/configuration_shared.h"
9#include "yuzu/configuration/configure_per_game.h" 11#include "yuzu/configuration/configure_per_game.h"
10 12
11void ConfigurationShared::ApplyPerGameSetting(Settings::Setting<bool>* setting, 13void ConfigurationShared::ApplyPerGameSetting(Settings::Setting<bool>* setting,
12 const QCheckBox* checkbox) { 14 const QCheckBox* checkbox,
13 if (checkbox->checkState() == Qt::PartiallyChecked) { 15 const CheckState& tracker) {
16 if (tracker == CheckState::Global) {
14 setting->SetGlobal(true); 17 setting->SetGlobal(true);
15 } else { 18 } else {
16 setting->SetGlobal(false); 19 setting->SetGlobal(false);
17 setting->SetValue(checkbox->checkState() == Qt::Checked); 20 setting->SetValue(checkbox->checkState());
18 } 21 }
19} 22}
20 23
@@ -69,8 +72,69 @@ void ConfigurationShared::SetPerGameSetting(
69 ConfigurationShared::USE_GLOBAL_OFFSET); 72 ConfigurationShared::USE_GLOBAL_OFFSET);
70} 73}
71 74
72void ConfigurationShared::InsertGlobalItem(QComboBox* combobox) { 75void ConfigurationShared::SetHighlight(QWidget* widget, const std::string& name, bool highlighted) {
73 const QString use_global_text = ConfigurePerGame::tr("Use global configuration"); 76 if (highlighted) {
77 widget->setStyleSheet(QStringLiteral("QWidget#%1 { background-color:rgba(0,203,255,0.5) }")
78 .arg(QString::fromStdString(name)));
79 } else {
80 widget->setStyleSheet(QStringLiteral("QWidget#%1 { background-color:rgba(0,0,0,0) }")
81 .arg(QString::fromStdString(name)));
82 }
83 widget->show();
84}
85
86void ConfigurationShared::SetColoredTristate(QCheckBox* checkbox, const std::string& name,
87 const Settings::Setting<bool>& setting,
88 CheckState& tracker) {
89 if (setting.UsingGlobal()) {
90 tracker = CheckState::Global;
91 } else {
92 tracker = (setting.GetValue() == setting.GetValue(true)) ? CheckState::On : CheckState::Off;
93 }
94 SetHighlight(checkbox, name, tracker != CheckState::Global);
95 QObject::connect(checkbox, &QCheckBox::clicked, checkbox,
96 [checkbox, name, setting, &tracker]() {
97 tracker = static_cast<CheckState>((static_cast<int>(tracker) + 1) %
98 static_cast<int>(CheckState::Count));
99 if (tracker == CheckState::Global) {
100 checkbox->setChecked(setting.GetValue(true));
101 }
102 SetHighlight(checkbox, name, tracker != CheckState::Global);
103 });
104}
105
106void ConfigurationShared::SetColoredTristate(QCheckBox* checkbox, const std::string& name,
107 bool global, bool state, bool global_state,
108 CheckState& tracker) {
109 if (global) {
110 tracker = CheckState::Global;
111 } else {
112 tracker = (state == global_state) ? CheckState::On : CheckState::Off;
113 }
114 SetHighlight(checkbox, name, tracker != CheckState::Global);
115 QObject::connect(checkbox, &QCheckBox::clicked, checkbox,
116 [checkbox, name, global_state, &tracker]() {
117 tracker = static_cast<CheckState>((static_cast<int>(tracker) + 1) %
118 static_cast<int>(CheckState::Count));
119 if (tracker == CheckState::Global) {
120 checkbox->setChecked(global_state);
121 }
122 SetHighlight(checkbox, name, tracker != CheckState::Global);
123 });
124}
125
126void ConfigurationShared::SetColoredComboBox(QComboBox* combobox, QWidget* target,
127 const std::string& target_name, int global) {
128 InsertGlobalItem(combobox, global);
129 QObject::connect(combobox, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), target,
130 [target, target_name](int index) {
131 ConfigurationShared::SetHighlight(target, target_name, index != 0);
132 });
133}
134
135void ConfigurationShared::InsertGlobalItem(QComboBox* combobox, int global_index) {
136 const QString use_global_text =
137 ConfigurePerGame::tr("Use global configuration (%1)").arg(combobox->itemText(global_index));
74 combobox->insertItem(ConfigurationShared::USE_GLOBAL_INDEX, use_global_text); 138 combobox->insertItem(ConfigurationShared::USE_GLOBAL_INDEX, use_global_text);
75 combobox->insertSeparator(ConfigurationShared::USE_GLOBAL_SEPARATOR_INDEX); 139 combobox->insertSeparator(ConfigurationShared::USE_GLOBAL_SEPARATOR_INDEX);
76} 140}
diff --git a/src/yuzu/configuration/configuration_shared.h b/src/yuzu/configuration/configuration_shared.h
index b11b1b950..003148c68 100644
--- a/src/yuzu/configuration/configuration_shared.h
+++ b/src/yuzu/configuration/configuration_shared.h
@@ -15,9 +15,17 @@ constexpr int USE_GLOBAL_INDEX = 0;
15constexpr int USE_GLOBAL_SEPARATOR_INDEX = 1; 15constexpr int USE_GLOBAL_SEPARATOR_INDEX = 1;
16constexpr int USE_GLOBAL_OFFSET = 2; 16constexpr int USE_GLOBAL_OFFSET = 2;
17 17
18enum class CheckState {
19 Off,
20 On,
21 Global,
22 Count,
23};
24
18// Global-aware apply and set functions 25// Global-aware apply and set functions
19 26
20void ApplyPerGameSetting(Settings::Setting<bool>* setting, const QCheckBox* checkbox); 27void ApplyPerGameSetting(Settings::Setting<bool>* setting, const QCheckBox* checkbox,
28 const CheckState& tracker);
21void ApplyPerGameSetting(Settings::Setting<int>* setting, const QComboBox* combobox); 29void ApplyPerGameSetting(Settings::Setting<int>* setting, const QComboBox* combobox);
22void ApplyPerGameSetting(Settings::Setting<Settings::RendererBackend>* setting, 30void ApplyPerGameSetting(Settings::Setting<Settings::RendererBackend>* setting,
23 const QComboBox* combobox); 31 const QComboBox* combobox);
@@ -31,6 +39,14 @@ void SetPerGameSetting(QComboBox* combobox,
31void SetPerGameSetting(QComboBox* combobox, 39void SetPerGameSetting(QComboBox* combobox,
32 const Settings::Setting<Settings::GPUAccuracy>* setting); 40 const Settings::Setting<Settings::GPUAccuracy>* setting);
33 41
34void InsertGlobalItem(QComboBox* combobox); 42void SetHighlight(QWidget* widget, const std::string& name, bool highlighted);
43void SetColoredTristate(QCheckBox* checkbox, const std::string& name,
44 const Settings::Setting<bool>& setting, CheckState& tracker);
45void SetColoredTristate(QCheckBox* checkbox, const std::string& name, bool global, bool state,
46 bool global_state, CheckState& tracker);
47void SetColoredComboBox(QComboBox* combobox, QWidget* target, const std::string& target_name,
48 int global);
49
50void InsertGlobalItem(QComboBox* combobox, int global_index);
35 51
36} // namespace ConfigurationShared 52} // namespace ConfigurationShared
diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp
index cc021beec..fea632531 100644
--- a/src/yuzu/configuration/configure_audio.cpp
+++ b/src/yuzu/configuration/configure_audio.cpp
@@ -49,12 +49,9 @@ void ConfigureAudio::SetConfiguration() {
49 49
50 ui->volume_slider->setValue(Settings::values.volume.GetValue() * ui->volume_slider->maximum()); 50 ui->volume_slider->setValue(Settings::values.volume.GetValue() * ui->volume_slider->maximum());
51 51
52 if (Settings::configuring_global) { 52 ui->toggle_audio_stretching->setChecked(Settings::values.enable_audio_stretching.GetValue());
53 ui->toggle_audio_stretching->setChecked( 53
54 Settings::values.enable_audio_stretching.GetValue()); 54 if (!Settings::configuring_global) {
55 } else {
56 ConfigurationShared::SetPerGameSetting(ui->toggle_audio_stretching,
57 &Settings::values.enable_audio_stretching);
58 if (Settings::values.volume.UsingGlobal()) { 55 if (Settings::values.volume.UsingGlobal()) {
59 ui->volume_combo_box->setCurrentIndex(0); 56 ui->volume_combo_box->setCurrentIndex(0);
60 ui->volume_slider->setEnabled(false); 57 ui->volume_slider->setEnabled(false);
@@ -62,6 +59,8 @@ void ConfigureAudio::SetConfiguration() {
62 ui->volume_combo_box->setCurrentIndex(1); 59 ui->volume_combo_box->setCurrentIndex(1);
63 ui->volume_slider->setEnabled(true); 60 ui->volume_slider->setEnabled(true);
64 } 61 }
62 ConfigurationShared::SetHighlight(ui->volume_layout, "volume_layout",
63 !Settings::values.volume.UsingGlobal());
65 } 64 }
66 SetVolumeIndicatorText(ui->volume_slider->sliderPosition()); 65 SetVolumeIndicatorText(ui->volume_slider->sliderPosition());
67} 66}
@@ -120,7 +119,8 @@ void ConfigureAudio::ApplyConfiguration() {
120 } 119 }
121 } else { 120 } else {
122 ConfigurationShared::ApplyPerGameSetting(&Settings::values.enable_audio_stretching, 121 ConfigurationShared::ApplyPerGameSetting(&Settings::values.enable_audio_stretching,
123 ui->toggle_audio_stretching); 122 ui->toggle_audio_stretching,
123 enable_audio_stretching);
124 if (ui->volume_combo_box->currentIndex() == 0) { 124 if (ui->volume_combo_box->currentIndex() == 0) {
125 Settings::values.volume.SetGlobal(true); 125 Settings::values.volume.SetGlobal(true);
126 } else { 126 } else {
@@ -173,9 +173,14 @@ void ConfigureAudio::SetupPerGameUI() {
173 return; 173 return;
174 } 174 }
175 175
176 ui->toggle_audio_stretching->setTristate(true); 176 ConfigurationShared::SetColoredTristate(ui->toggle_audio_stretching, "toggle_audio_stretching",
177 Settings::values.enable_audio_stretching,
178 enable_audio_stretching);
177 connect(ui->volume_combo_box, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), 179 connect(ui->volume_combo_box, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
178 this, [this](int index) { ui->volume_slider->setEnabled(index == 1); }); 180 this, [this](int index) {
181 ui->volume_slider->setEnabled(index == 1);
182 ConfigurationShared::SetHighlight(ui->volume_layout, "volume_layout", index == 1);
183 });
179 184
180 ui->output_sink_combo_box->setVisible(false); 185 ui->output_sink_combo_box->setVisible(false);
181 ui->output_sink_label->setVisible(false); 186 ui->output_sink_label->setVisible(false);
diff --git a/src/yuzu/configuration/configure_audio.h b/src/yuzu/configuration/configure_audio.h
index d84f4a682..9dbd3d93e 100644
--- a/src/yuzu/configuration/configure_audio.h
+++ b/src/yuzu/configuration/configure_audio.h
@@ -7,6 +7,10 @@
7#include <memory> 7#include <memory>
8#include <QWidget> 8#include <QWidget>
9 9
10namespace ConfigurationShared {
11enum class CheckState;
12}
13
10namespace Ui { 14namespace Ui {
11class ConfigureAudio; 15class ConfigureAudio;
12} 16}
@@ -37,4 +41,6 @@ private:
37 void SetupPerGameUI(); 41 void SetupPerGameUI();
38 42
39 std::unique_ptr<Ui::ConfigureAudio> ui; 43 std::unique_ptr<Ui::ConfigureAudio> ui;
44
45 ConfigurationShared::CheckState enable_audio_stretching;
40}; 46};
diff --git a/src/yuzu/configuration/configure_audio.ui b/src/yuzu/configuration/configure_audio.ui
index 862ccb988..9bd0cca96 100644
--- a/src/yuzu/configuration/configure_audio.ui
+++ b/src/yuzu/configuration/configure_audio.ui
@@ -56,80 +56,91 @@
56 </layout> 56 </layout>
57 </item> 57 </item>
58 <item> 58 <item>
59 <layout class="QHBoxLayout" name="horizontalLayout_2"> 59 <widget class="QWidget" name="volume_layout" native="true">
60 <property name="topMargin"> 60 <layout class="QHBoxLayout" name="horizontalLayout_2">
61 <number>0</number> 61 <property name="leftMargin">
62 </property> 62 <number>0</number>
63 <item> 63 </property>
64 <widget class="QComboBox" name="volume_combo_box"> 64 <property name="topMargin">
65 <item> 65 <number>0</number>
66 </property>
67 <property name="rightMargin">
68 <number>0</number>
69 </property>
70 <property name="bottomMargin">
71 <number>0</number>
72 </property>
73 <item>
74 <widget class="QComboBox" name="volume_combo_box">
75 <item>
76 <property name="text">
77 <string>Use global volume</string>
78 </property>
79 </item>
80 <item>
81 <property name="text">
82 <string>Set volume:</string>
83 </property>
84 </item>
85 </widget>
86 </item>
87 <item>
88 <widget class="QLabel" name="volume_label">
66 <property name="text"> 89 <property name="text">
67 <string>Use global volume</string> 90 <string>Volume:</string>
91 </property>
92 </widget>
93 </item>
94 <item>
95 <spacer name="horizontalSpacer">
96 <property name="orientation">
97 <enum>Qt::Horizontal</enum>
98 </property>
99 <property name="sizeHint" stdset="0">
100 <size>
101 <width>30</width>
102 <height>20</height>
103 </size>
104 </property>
105 </spacer>
106 </item>
107 <item>
108 <widget class="QSlider" name="volume_slider">
109 <property name="sizePolicy">
110 <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
111 <horstretch>0</horstretch>
112 <verstretch>0</verstretch>
113 </sizepolicy>
114 </property>
115 <property name="maximum">
116 <number>100</number>
117 </property>
118 <property name="pageStep">
119 <number>10</number>
120 </property>
121 <property name="orientation">
122 <enum>Qt::Horizontal</enum>
123 </property>
124 </widget>
125 </item>
126 <item>
127 <widget class="QLabel" name="volume_indicator">
128 <property name="minimumSize">
129 <size>
130 <width>32</width>
131 <height>0</height>
132 </size>
68 </property> 133 </property>
69 </item>
70 <item>
71 <property name="text"> 134 <property name="text">
72 <string>Set volume:</string> 135 <string>0 %</string>
73 </property> 136 </property>
74 </item> 137 <property name="alignment">
75 </widget> 138 <set>Qt::AlignCenter</set>
76 </item> 139 </property>
77 <item> 140 </widget>
78 <widget class="QLabel" name="volume_label"> 141 </item>
79 <property name="text"> 142 </layout>
80 <string>Volume:</string> 143 </widget>
81 </property>
82 </widget>
83 </item>
84 <item>
85 <spacer name="horizontalSpacer">
86 <property name="orientation">
87 <enum>Qt::Horizontal</enum>
88 </property>
89 <property name="sizeHint" stdset="0">
90 <size>
91 <width>30</width>
92 <height>20</height>
93 </size>
94 </property>
95 </spacer>
96 </item>
97 <item>
98 <widget class="QSlider" name="volume_slider">
99 <property name="sizePolicy">
100 <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
101 <horstretch>0</horstretch>
102 <verstretch>0</verstretch>
103 </sizepolicy>
104 </property>
105 <property name="maximum">
106 <number>100</number>
107 </property>
108 <property name="pageStep">
109 <number>10</number>
110 </property>
111 <property name="orientation">
112 <enum>Qt::Horizontal</enum>
113 </property>
114 </widget>
115 </item>
116 <item>
117 <widget class="QLabel" name="volume_indicator">
118 <property name="minimumSize">
119 <size>
120 <width>32</width>
121 <height>0</height>
122 </size>
123 </property>
124 <property name="text">
125 <string>0 %</string>
126 </property>
127 <property name="alignment">
128 <set>Qt::AlignCenter</set>
129 </property>
130 </widget>
131 </item>
132 </layout>
133 </item> 144 </item>
134 </layout> 145 </layout>
135 </widget> 146 </widget>
diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp
index 20316c9cc..c0dbd9855 100644
--- a/src/yuzu/configuration/configure_general.cpp
+++ b/src/yuzu/configuration/configure_general.cpp
@@ -19,9 +19,10 @@ ConfigureGeneral::ConfigureGeneral(QWidget* parent)
19 19
20 SetConfiguration(); 20 SetConfiguration();
21 21
22 connect(ui->toggle_frame_limit, &QCheckBox::stateChanged, ui->frame_limit, [this]() { 22 if (Settings::configuring_global) {
23 ui->frame_limit->setEnabled(ui->toggle_frame_limit->checkState() == Qt::Checked); 23 connect(ui->toggle_frame_limit, &QCheckBox::clicked, ui->frame_limit,
24 }); 24 [this]() { ui->frame_limit->setEnabled(ui->toggle_frame_limit->isChecked()); });
25 }
25} 26}
26 27
27ConfigureGeneral::~ConfigureGeneral() = default; 28ConfigureGeneral::~ConfigureGeneral() = default;
@@ -40,17 +41,12 @@ void ConfigureGeneral::SetConfiguration() {
40 ui->toggle_frame_limit->setChecked(Settings::values.use_frame_limit.GetValue()); 41 ui->toggle_frame_limit->setChecked(Settings::values.use_frame_limit.GetValue());
41 ui->frame_limit->setValue(Settings::values.frame_limit.GetValue()); 42 ui->frame_limit->setValue(Settings::values.frame_limit.GetValue());
42 43
43 if (!Settings::configuring_global) { 44 if (Settings::configuring_global) {
44 if (Settings::values.use_multi_core.UsingGlobal()) { 45 ui->frame_limit->setEnabled(Settings::values.use_frame_limit.GetValue());
45 ui->use_multi_core->setCheckState(Qt::PartiallyChecked); 46 } else {
46 } 47 ui->frame_limit->setEnabled(Settings::values.use_frame_limit.GetValue() &&
47 if (Settings::values.use_frame_limit.UsingGlobal()) { 48 use_frame_limit != ConfigurationShared::CheckState::Global);
48 ui->toggle_frame_limit->setCheckState(Qt::PartiallyChecked);
49 }
50 } 49 }
51
52 ui->frame_limit->setEnabled(ui->toggle_frame_limit->checkState() == Qt::Checked &&
53 ui->toggle_frame_limit->isEnabled());
54} 50}
55 51
56void ConfigureGeneral::ApplyConfiguration() { 52void ConfigureGeneral::ApplyConfiguration() {
@@ -71,9 +67,9 @@ void ConfigureGeneral::ApplyConfiguration() {
71 } 67 }
72 } else { 68 } else {
73 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_multi_core, 69 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_multi_core,
74 ui->use_multi_core); 70 ui->use_multi_core, use_multi_core);
75 71
76 bool global_frame_limit = ui->toggle_frame_limit->checkState() == Qt::PartiallyChecked; 72 bool global_frame_limit = use_frame_limit == ConfigurationShared::CheckState::Global;
77 Settings::values.use_frame_limit.SetGlobal(global_frame_limit); 73 Settings::values.use_frame_limit.SetGlobal(global_frame_limit);
78 Settings::values.frame_limit.SetGlobal(global_frame_limit); 74 Settings::values.frame_limit.SetGlobal(global_frame_limit);
79 if (!global_frame_limit) { 75 if (!global_frame_limit) {
@@ -109,6 +105,13 @@ void ConfigureGeneral::SetupPerGameUI() {
109 ui->toggle_background_pause->setVisible(false); 105 ui->toggle_background_pause->setVisible(false);
110 ui->toggle_hide_mouse->setVisible(false); 106 ui->toggle_hide_mouse->setVisible(false);
111 107
112 ui->toggle_frame_limit->setTristate(true); 108 ConfigurationShared::SetColoredTristate(ui->toggle_frame_limit, "toggle_frame_limit",
113 ui->use_multi_core->setTristate(true); 109 Settings::values.use_frame_limit, use_frame_limit);
110 ConfigurationShared::SetColoredTristate(ui->use_multi_core, "use_multi_core",
111 Settings::values.use_multi_core, use_multi_core);
112
113 connect(ui->toggle_frame_limit, &QCheckBox::clicked, ui->frame_limit, [this]() {
114 ui->frame_limit->setEnabled(ui->toggle_frame_limit->isChecked() &&
115 (use_frame_limit != ConfigurationShared::CheckState::Global));
116 });
114} 117}
diff --git a/src/yuzu/configuration/configure_general.h b/src/yuzu/configuration/configure_general.h
index 9c785c22e..323ffbd8f 100644
--- a/src/yuzu/configuration/configure_general.h
+++ b/src/yuzu/configuration/configure_general.h
@@ -7,6 +7,10 @@
7#include <memory> 7#include <memory>
8#include <QWidget> 8#include <QWidget>
9 9
10namespace ConfigurationShared {
11enum class CheckState;
12}
13
10class HotkeyRegistry; 14class HotkeyRegistry;
11 15
12namespace Ui { 16namespace Ui {
@@ -31,4 +35,7 @@ private:
31 void SetupPerGameUI(); 35 void SetupPerGameUI();
32 36
33 std::unique_ptr<Ui::ConfigureGeneral> ui; 37 std::unique_ptr<Ui::ConfigureGeneral> ui;
38
39 ConfigurationShared::CheckState use_frame_limit;
40 ConfigurationShared::CheckState use_multi_core;
34}; 41};
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp
index cb4706bd6..3e42531c3 100644
--- a/src/yuzu/configuration/configure_graphics.cpp
+++ b/src/yuzu/configuration/configure_graphics.cpp
@@ -31,8 +31,14 @@ ConfigureGraphics::ConfigureGraphics(QWidget* parent)
31 31
32 SetConfiguration(); 32 SetConfiguration();
33 33
34 connect(ui->api, qOverload<int>(&QComboBox::currentIndexChanged), this, 34 connect(ui->api, qOverload<int>(&QComboBox::currentIndexChanged), this, [this] {
35 [this] { UpdateDeviceComboBox(); }); 35 UpdateDeviceComboBox();
36 if (!Settings::configuring_global) {
37 ConfigurationShared::SetHighlight(ui->api_layout, "api_layout",
38 ui->api->currentIndex() !=
39 ConfigurationShared::USE_GLOBAL_INDEX);
40 }
41 });
36 connect(ui->device, qOverload<int>(&QComboBox::activated), this, 42 connect(ui->device, qOverload<int>(&QComboBox::activated), this,
37 [this](int device) { UpdateDeviceSelection(device); }); 43 [this](int device) { UpdateDeviceSelection(device); });
38 44
@@ -65,25 +71,26 @@ void ConfigureGraphics::SetConfiguration() {
65 ui->api->setEnabled(runtime_lock); 71 ui->api->setEnabled(runtime_lock);
66 ui->use_asynchronous_gpu_emulation->setEnabled(runtime_lock); 72 ui->use_asynchronous_gpu_emulation->setEnabled(runtime_lock);
67 ui->use_disk_shader_cache->setEnabled(runtime_lock); 73 ui->use_disk_shader_cache->setEnabled(runtime_lock);
74 ui->use_disk_shader_cache->setChecked(Settings::values.use_disk_shader_cache.GetValue());
75 ui->use_asynchronous_gpu_emulation->setChecked(
76 Settings::values.use_asynchronous_gpu_emulation.GetValue());
68 77
69 if (Settings::configuring_global) { 78 if (Settings::configuring_global) {
70 ui->api->setCurrentIndex(static_cast<int>(Settings::values.renderer_backend.GetValue())); 79 ui->api->setCurrentIndex(static_cast<int>(Settings::values.renderer_backend.GetValue()));
71 ui->aspect_ratio_combobox->setCurrentIndex(Settings::values.aspect_ratio.GetValue()); 80 ui->aspect_ratio_combobox->setCurrentIndex(Settings::values.aspect_ratio.GetValue());
72 ui->use_disk_shader_cache->setChecked(Settings::values.use_disk_shader_cache.GetValue());
73 ui->use_asynchronous_gpu_emulation->setChecked(
74 Settings::values.use_asynchronous_gpu_emulation.GetValue());
75 } else { 81 } else {
76 ConfigurationShared::SetPerGameSetting(ui->use_disk_shader_cache,
77 &Settings::values.use_disk_shader_cache);
78 ConfigurationShared::SetPerGameSetting(ui->use_asynchronous_gpu_emulation,
79 &Settings::values.use_asynchronous_gpu_emulation);
80
81 ConfigurationShared::SetPerGameSetting(ui->api, &Settings::values.renderer_backend); 82 ConfigurationShared::SetPerGameSetting(ui->api, &Settings::values.renderer_backend);
83 ConfigurationShared::SetHighlight(ui->api_layout, "api_layout",
84 !Settings::values.renderer_backend.UsingGlobal());
82 ConfigurationShared::SetPerGameSetting(ui->aspect_ratio_combobox, 85 ConfigurationShared::SetPerGameSetting(ui->aspect_ratio_combobox,
83 &Settings::values.aspect_ratio); 86 &Settings::values.aspect_ratio);
84 87
85 ui->bg_combobox->setCurrentIndex(Settings::values.bg_red.UsingGlobal() ? 0 : 1); 88 ui->bg_combobox->setCurrentIndex(Settings::values.bg_red.UsingGlobal() ? 0 : 1);
86 ui->bg_button->setEnabled(!Settings::values.bg_red.UsingGlobal()); 89 ui->bg_button->setEnabled(!Settings::values.bg_red.UsingGlobal());
90 ConfigurationShared::SetHighlight(ui->ar_label, "ar_label",
91 !Settings::values.aspect_ratio.UsingGlobal());
92 ConfigurationShared::SetHighlight(ui->bg_layout, "bg_layout",
93 !Settings::values.bg_red.UsingGlobal());
87 } 94 }
88 95
89 UpdateBackgroundColorButton(QColor::fromRgbF(Settings::values.bg_red.GetValue(), 96 UpdateBackgroundColorButton(QColor::fromRgbF(Settings::values.bg_red.GetValue(),
@@ -135,9 +142,10 @@ void ConfigureGraphics::ApplyConfiguration() {
135 ui->aspect_ratio_combobox); 142 ui->aspect_ratio_combobox);
136 143
137 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_disk_shader_cache, 144 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_disk_shader_cache,
138 ui->use_disk_shader_cache); 145 ui->use_disk_shader_cache, use_disk_shader_cache);
139 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_gpu_emulation, 146 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_gpu_emulation,
140 ui->use_asynchronous_gpu_emulation); 147 ui->use_asynchronous_gpu_emulation,
148 use_asynchronous_gpu_emulation);
141 149
142 if (ui->bg_combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { 150 if (ui->bg_combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) {
143 Settings::values.bg_red.SetGlobal(true); 151 Settings::values.bg_red.SetGlobal(true);
@@ -241,10 +249,20 @@ void ConfigureGraphics::SetupPerGameUI() {
241 } 249 }
242 250
243 connect(ui->bg_combobox, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, 251 connect(ui->bg_combobox, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this,
244 [this](int index) { ui->bg_button->setEnabled(index == 1); }); 252 [this](int index) {
245 253 ui->bg_button->setEnabled(index == 1);
246 ui->use_disk_shader_cache->setTristate(true); 254 ConfigurationShared::SetHighlight(ui->bg_layout, "bg_layout", index == 1);
247 ui->use_asynchronous_gpu_emulation->setTristate(true); 255 });
248 ConfigurationShared::InsertGlobalItem(ui->aspect_ratio_combobox); 256
249 ConfigurationShared::InsertGlobalItem(ui->api); 257 ConfigurationShared::SetColoredTristate(ui->use_disk_shader_cache, "use_disk_shader_cache",
258 Settings::values.use_disk_shader_cache,
259 use_disk_shader_cache);
260 ConfigurationShared::SetColoredTristate(
261 ui->use_asynchronous_gpu_emulation, "use_asynchronous_gpu_emulation",
262 Settings::values.use_asynchronous_gpu_emulation, use_asynchronous_gpu_emulation);
263
264 ConfigurationShared::SetColoredComboBox(ui->aspect_ratio_combobox, ui->ar_label, "ar_label",
265 Settings::values.aspect_ratio.GetValue(true));
266 ConfigurationShared::InsertGlobalItem(
267 ui->api, static_cast<int>(Settings::values.renderer_backend.GetValue(true)));
250} 268}
diff --git a/src/yuzu/configuration/configure_graphics.h b/src/yuzu/configuration/configure_graphics.h
index 24f01c739..b4961f719 100644
--- a/src/yuzu/configuration/configure_graphics.h
+++ b/src/yuzu/configuration/configure_graphics.h
@@ -10,6 +10,10 @@
10#include <QWidget> 10#include <QWidget>
11#include "core/settings.h" 11#include "core/settings.h"
12 12
13namespace ConfigurationShared {
14enum class CheckState;
15}
16
13namespace Ui { 17namespace Ui {
14class ConfigureGraphics; 18class ConfigureGraphics;
15} 19}
@@ -42,6 +46,9 @@ private:
42 std::unique_ptr<Ui::ConfigureGraphics> ui; 46 std::unique_ptr<Ui::ConfigureGraphics> ui;
43 QColor bg_color; 47 QColor bg_color;
44 48
49 ConfigurationShared::CheckState use_disk_shader_cache;
50 ConfigurationShared::CheckState use_asynchronous_gpu_emulation;
51
45 std::vector<QString> vulkan_devices; 52 std::vector<QString> vulkan_devices;
46 u32 vulkan_device{}; 53 u32 vulkan_device{};
47}; 54};
diff --git a/src/yuzu/configuration/configure_graphics.ui b/src/yuzu/configuration/configure_graphics.ui
index 62418fc14..62aa337e7 100644
--- a/src/yuzu/configuration/configure_graphics.ui
+++ b/src/yuzu/configuration/configure_graphics.ui
@@ -6,7 +6,7 @@
6 <rect> 6 <rect>
7 <x>0</x> 7 <x>0</x>
8 <y>0</y> 8 <y>0</y>
9 <width>400</width> 9 <width>437</width>
10 <height>321</height> 10 <height>321</height>
11 </rect> 11 </rect>
12 </property> 12 </property>
@@ -23,43 +23,56 @@
23 </property> 23 </property>
24 <layout class="QVBoxLayout" name="verticalLayout_3"> 24 <layout class="QVBoxLayout" name="verticalLayout_3">
25 <item> 25 <item>
26 <layout class="QHBoxLayout" name="horizontalLayout_4"> 26 <widget class="QWidget" name="api_layout" native="true">
27 <item> 27 <layout class="QGridLayout" name="gridLayout">
28 <widget class="QLabel" name="label_2"> 28 <property name="leftMargin">
29 <property name="text"> 29 <number>0</number>
30 <string>API:</string> 30 </property>
31 </property> 31 <property name="topMargin">
32 </widget> 32 <number>0</number>
33 </item> 33 </property>
34 <item> 34 <property name="rightMargin">
35 <widget class="QComboBox" name="api"> 35 <number>0</number>
36 <item> 36 </property>
37 <property name="bottomMargin">
38 <number>0</number>
39 </property>
40 <property name="horizontalSpacing">
41 <number>6</number>
42 </property>
43 <item row="0" column="0">
44 <widget class="QLabel" name="api_label">
37 <property name="text"> 45 <property name="text">
38 <string notr="true">OpenGL</string> 46 <string>API:</string>
39 </property> 47 </property>
40 </item> 48 </widget>
41 <item> 49 </item>
50 <item row="0" column="1">
51 <widget class="QComboBox" name="api">
52 <item>
53 <property name="text">
54 <string notr="true">OpenGL</string>
55 </property>
56 </item>
57 <item>
58 <property name="text">
59 <string notr="true">Vulkan</string>
60 </property>
61 </item>
62 </widget>
63 </item>
64 <item row="1" column="0">
65 <widget class="QLabel" name="device_label">
42 <property name="text"> 66 <property name="text">
43 <string notr="true">Vulkan</string> 67 <string>Device:</string>
44 </property> 68 </property>
45 </item> 69 </widget>
46 </widget> 70 </item>
47 </item> 71 <item row="1" column="1">
48 </layout> 72 <widget class="QComboBox" name="device"/>
49 </item> 73 </item>
50 <item> 74 </layout>
51 <layout class="QHBoxLayout" name="horizontalLayout_5"> 75 </widget>
52 <item>
53 <widget class="QLabel" name="label_3">
54 <property name="text">
55 <string>Device:</string>
56 </property>
57 </widget>
58 </item>
59 <item>
60 <widget class="QComboBox" name="device"/>
61 </item>
62 </layout>
63 </item> 76 </item>
64 </layout> 77 </layout>
65 </widget> 78 </widget>
@@ -85,96 +98,133 @@
85 </widget> 98 </widget>
86 </item> 99 </item>
87 <item> 100 <item>
88 <layout class="QHBoxLayout" name="horizontalLayout_6"> 101 <widget class="QWidget" name="aspect_ratio_layout" native="true">
89 <item> 102 <layout class="QHBoxLayout" name="horizontalLayout_6">
90 <widget class="QLabel" name="ar_label"> 103 <property name="leftMargin">
91 <property name="text"> 104 <number>0</number>
92 <string>Aspect Ratio:</string> 105 </property>
93 </property> 106 <property name="topMargin">
94 </widget> 107 <number>0</number>
95 </item> 108 </property>
96 <item> 109 <property name="rightMargin">
97 <widget class="QComboBox" name="aspect_ratio_combobox"> 110 <number>0</number>
98 <item> 111 </property>
99 <property name="text"> 112 <property name="bottomMargin">
100 <string>Default (16:9)</string> 113 <number>0</number>
101 </property> 114 </property>
102 </item> 115 <item>
103 <item> 116 <widget class="QLabel" name="ar_label">
104 <property name="text">
105 <string>Force 4:3</string>
106 </property>
107 </item>
108 <item>
109 <property name="text">
110 <string>Force 21:9</string>
111 </property>
112 </item>
113 <item>
114 <property name="text"> 117 <property name="text">
115 <string>Stretch to Window</string> 118 <string>Aspect Ratio:</string>
116 </property> 119 </property>
117 </item> 120 </widget>
118 </widget> 121 </item>
119 </item> 122 <item>
120 </layout> 123 <widget class="QComboBox" name="aspect_ratio_combobox">
124 <item>
125 <property name="text">
126 <string>Default (16:9)</string>
127 </property>
128 </item>
129 <item>
130 <property name="text">
131 <string>Force 4:3</string>
132 </property>
133 </item>
134 <item>
135 <property name="text">
136 <string>Force 21:9</string>
137 </property>
138 </item>
139 <item>
140 <property name="text">
141 <string>Stretch to Window</string>
142 </property>
143 </item>
144 </widget>
145 </item>
146 </layout>
147 </widget>
121 </item> 148 </item>
122 <item> 149 <item>
123 <layout class="QHBoxLayout" name="horizontalLayout_3"> 150 <widget class="QWidget" name="bg_layout" native="true">
124 <item> 151 <property name="sizePolicy">
125 <widget class="QComboBox" name="bg_combobox"> 152 <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
126 <property name="currentText"> 153 <horstretch>0</horstretch>
127 <string>Use global background color</string> 154 <verstretch>0</verstretch>
128 </property> 155 </sizepolicy>
129 <property name="currentIndex"> 156 </property>
130 <number>0</number> 157 <layout class="QHBoxLayout" name="horizontalLayout_3">
131 </property> 158 <property name="spacing">
132 <property name="maxVisibleItems"> 159 <number>6</number>
133 <number>10</number> 160 </property>
134 </property> 161 <property name="leftMargin">
135 <item> 162 <number>0</number>
136 <property name="text"> 163 </property>
164 <property name="topMargin">
165 <number>0</number>
166 </property>
167 <property name="rightMargin">
168 <number>0</number>
169 </property>
170 <property name="bottomMargin">
171 <number>0</number>
172 </property>
173 <item>
174 <widget class="QComboBox" name="bg_combobox">
175 <property name="currentText">
137 <string>Use global background color</string> 176 <string>Use global background color</string>
138 </property> 177 </property>
139 </item> 178 <property name="currentIndex">
140 <item> 179 <number>0</number>
180 </property>
181 <property name="maxVisibleItems">
182 <number>10</number>
183 </property>
184 <item>
185 <property name="text">
186 <string>Use global background color</string>
187 </property>
188 </item>
189 <item>
190 <property name="text">
191 <string>Set background color:</string>
192 </property>
193 </item>
194 </widget>
195 </item>
196 <item>
197 <widget class="QLabel" name="bg_label">
141 <property name="text"> 198 <property name="text">
142 <string>Set background color:</string> 199 <string>Background Color:</string>
143 </property> 200 </property>
144 </item> 201 </widget>
145 </widget> 202 </item>
146 </item> 203 <item>
147 <item> 204 <spacer name="horizontalSpacer">
148 <widget class="QLabel" name="bg_label"> 205 <property name="orientation">
149 <property name="text"> 206 <enum>Qt::Horizontal</enum>
150 <string>Background Color:</string> 207 </property>
151 </property> 208 <property name="sizeHint" stdset="0">
152 </widget> 209 <size>
153 </item> 210 <width>40</width>
154 <item> 211 <height>20</height>
155 <spacer name="horizontalSpacer"> 212 </size>
156 <property name="orientation"> 213 </property>
157 <enum>Qt::Horizontal</enum> 214 </spacer>
158 </property> 215 </item>
159 <property name="sizeHint" stdset="0"> 216 <item>
160 <size> 217 <widget class="QPushButton" name="bg_button">
161 <width>40</width> 218 <property name="maximumSize">
162 <height>20</height> 219 <size>
163 </size> 220 <width>40</width>
164 </property> 221 <height>16777215</height>
165 </spacer> 222 </size>
166 </item> 223 </property>
167 <item> 224 </widget>
168 <widget class="QPushButton" name="bg_button"> 225 </item>
169 <property name="maximumSize"> 226 </layout>
170 <size> 227 </widget>
171 <width>40</width>
172 <height>16777215</height>
173 </size>
174 </property>
175 </widget>
176 </item>
177 </layout>
178 </item> 228 </item>
179 </layout> 229 </layout>
180 </widget> 230 </widget>
diff --git a/src/yuzu/configuration/configure_graphics_advanced.cpp b/src/yuzu/configuration/configure_graphics_advanced.cpp
index ce30188cd..8b9180811 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.cpp
+++ b/src/yuzu/configuration/configure_graphics_advanced.cpp
@@ -28,32 +28,25 @@ void ConfigureGraphicsAdvanced::SetConfiguration() {
28 ui->force_30fps_mode->setEnabled(runtime_lock); 28 ui->force_30fps_mode->setEnabled(runtime_lock);
29 ui->anisotropic_filtering_combobox->setEnabled(runtime_lock); 29 ui->anisotropic_filtering_combobox->setEnabled(runtime_lock);
30 30
31 ui->use_vsync->setChecked(Settings::values.use_vsync.GetValue());
32 ui->use_assembly_shaders->setChecked(Settings::values.use_assembly_shaders.GetValue());
33 ui->use_asynchronous_shaders->setChecked(Settings::values.use_asynchronous_shaders.GetValue());
34 ui->use_fast_gpu_time->setChecked(Settings::values.use_fast_gpu_time.GetValue());
35 ui->force_30fps_mode->setChecked(Settings::values.force_30fps_mode.GetValue());
36
31 if (Settings::configuring_global) { 37 if (Settings::configuring_global) {
32 ui->gpu_accuracy->setCurrentIndex( 38 ui->gpu_accuracy->setCurrentIndex(
33 static_cast<int>(Settings::values.gpu_accuracy.GetValue())); 39 static_cast<int>(Settings::values.gpu_accuracy.GetValue()));
34 ui->use_vsync->setChecked(Settings::values.use_vsync.GetValue());
35 ui->use_assembly_shaders->setChecked(Settings::values.use_assembly_shaders.GetValue());
36 ui->use_asynchronous_shaders->setChecked(
37 Settings::values.use_asynchronous_shaders.GetValue());
38 ui->use_fast_gpu_time->setChecked(Settings::values.use_fast_gpu_time.GetValue());
39 ui->force_30fps_mode->setChecked(Settings::values.force_30fps_mode.GetValue());
40 ui->anisotropic_filtering_combobox->setCurrentIndex( 40 ui->anisotropic_filtering_combobox->setCurrentIndex(
41 Settings::values.max_anisotropy.GetValue()); 41 Settings::values.max_anisotropy.GetValue());
42 } else { 42 } else {
43 ConfigurationShared::SetPerGameSetting(ui->gpu_accuracy, &Settings::values.gpu_accuracy); 43 ConfigurationShared::SetPerGameSetting(ui->gpu_accuracy, &Settings::values.gpu_accuracy);
44 ConfigurationShared::SetPerGameSetting(ui->use_vsync, &Settings::values.use_vsync);
45 ConfigurationShared::SetPerGameSetting(ui->use_assembly_shaders,
46 &Settings::values.use_assembly_shaders);
47 ConfigurationShared::SetPerGameSetting(ui->use_asynchronous_shaders,
48 &Settings::values.use_asynchronous_shaders);
49 ConfigurationShared::SetPerGameSetting(ui->use_asynchronous_shaders,
50 &Settings::values.use_asynchronous_shaders);
51 ConfigurationShared::SetPerGameSetting(ui->use_fast_gpu_time,
52 &Settings::values.use_fast_gpu_time);
53 ConfigurationShared::SetPerGameSetting(ui->force_30fps_mode,
54 &Settings::values.force_30fps_mode);
55 ConfigurationShared::SetPerGameSetting(ui->anisotropic_filtering_combobox, 44 ConfigurationShared::SetPerGameSetting(ui->anisotropic_filtering_combobox,
56 &Settings::values.max_anisotropy); 45 &Settings::values.max_anisotropy);
46 ConfigurationShared::SetHighlight(ui->label_gpu_accuracy, "label_gpu_accuracy",
47 !Settings::values.gpu_accuracy.UsingGlobal());
48 ConfigurationShared::SetHighlight(ui->af_label, "af_label",
49 !Settings::values.max_anisotropy.UsingGlobal());
57 } 50 }
58} 51}
59 52
@@ -95,17 +88,17 @@ void ConfigureGraphicsAdvanced::ApplyConfiguration() {
95 } else { 88 } else {
96 ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy, 89 ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy,
97 ui->anisotropic_filtering_combobox); 90 ui->anisotropic_filtering_combobox);
98 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync, ui->use_vsync); 91 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync, ui->use_vsync,
92 use_vsync);
99 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_assembly_shaders, 93 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_assembly_shaders,
100 ui->use_assembly_shaders); 94 ui->use_assembly_shaders, use_assembly_shaders);
101 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_shaders,
102 ui->use_asynchronous_shaders);
103 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_shaders, 95 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_shaders,
104 ui->use_asynchronous_shaders); 96 ui->use_asynchronous_shaders,
97 use_asynchronous_shaders);
105 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_fast_gpu_time, 98 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_fast_gpu_time,
106 ui->use_fast_gpu_time); 99 ui->use_fast_gpu_time, use_fast_gpu_time);
107 ConfigurationShared::ApplyPerGameSetting(&Settings::values.force_30fps_mode, 100 ConfigurationShared::ApplyPerGameSetting(&Settings::values.force_30fps_mode,
108 ui->force_30fps_mode); 101 ui->force_30fps_mode, force_30fps_mode);
109 ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy, 102 ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy,
110 ui->anisotropic_filtering_combobox); 103 ui->anisotropic_filtering_combobox);
111 104
@@ -146,11 +139,22 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() {
146 return; 139 return;
147 } 140 }
148 141
149 ConfigurationShared::InsertGlobalItem(ui->gpu_accuracy); 142 ConfigurationShared::SetColoredTristate(ui->use_vsync, "use_vsync", Settings::values.use_vsync,
150 ui->use_vsync->setTristate(true); 143 use_vsync);
151 ui->use_assembly_shaders->setTristate(true); 144 ConfigurationShared::SetColoredTristate(ui->use_assembly_shaders, "use_assembly_shaders",
152 ui->use_asynchronous_shaders->setTristate(true); 145 Settings::values.use_assembly_shaders,
153 ui->use_fast_gpu_time->setTristate(true); 146 use_assembly_shaders);
154 ui->force_30fps_mode->setTristate(true); 147 ConfigurationShared::SetColoredTristate(
155 ConfigurationShared::InsertGlobalItem(ui->anisotropic_filtering_combobox); 148 ui->use_asynchronous_shaders, "use_asynchronous_shaders",
149 Settings::values.use_asynchronous_shaders, use_asynchronous_shaders);
150 ConfigurationShared::SetColoredTristate(ui->use_fast_gpu_time, "use_fast_gpu_time",
151 Settings::values.use_fast_gpu_time, use_fast_gpu_time);
152 ConfigurationShared::SetColoredTristate(ui->force_30fps_mode, "force_30fps_mode",
153 Settings::values.force_30fps_mode, force_30fps_mode);
154 ConfigurationShared::SetColoredComboBox(
155 ui->gpu_accuracy, ui->label_gpu_accuracy, "label_gpu_accuracy",
156 static_cast<int>(Settings::values.gpu_accuracy.GetValue(true)));
157 ConfigurationShared::SetColoredComboBox(
158 ui->anisotropic_filtering_combobox, ui->af_label, "af_label",
159 static_cast<int>(Settings::values.max_anisotropy.GetValue(true)));
156} 160}
diff --git a/src/yuzu/configuration/configure_graphics_advanced.h b/src/yuzu/configuration/configure_graphics_advanced.h
index c043588ff..3c4f6f7bb 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.h
+++ b/src/yuzu/configuration/configure_graphics_advanced.h
@@ -7,6 +7,10 @@
7#include <memory> 7#include <memory>
8#include <QWidget> 8#include <QWidget>
9 9
10namespace ConfigurationShared {
11enum class CheckState;
12}
13
10namespace Ui { 14namespace Ui {
11class ConfigureGraphicsAdvanced; 15class ConfigureGraphicsAdvanced;
12} 16}
@@ -29,4 +33,10 @@ private:
29 void SetupPerGameUI(); 33 void SetupPerGameUI();
30 34
31 std::unique_ptr<Ui::ConfigureGraphicsAdvanced> ui; 35 std::unique_ptr<Ui::ConfigureGraphicsAdvanced> ui;
36
37 ConfigurationShared::CheckState use_vsync;
38 ConfigurationShared::CheckState use_assembly_shaders;
39 ConfigurationShared::CheckState use_asynchronous_shaders;
40 ConfigurationShared::CheckState use_fast_gpu_time;
41 ConfigurationShared::CheckState force_30fps_mode;
32}; 42};
diff --git a/src/yuzu/configuration/configure_graphics_advanced.ui b/src/yuzu/configuration/configure_graphics_advanced.ui
index 71e7dfe5e..6a0d29c27 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.ui
+++ b/src/yuzu/configuration/configure_graphics_advanced.ui
@@ -6,7 +6,7 @@
6 <rect> 6 <rect>
7 <x>0</x> 7 <x>0</x>
8 <y>0</y> 8 <y>0</y>
9 <width>400</width> 9 <width>404</width>
10 <height>321</height> 10 <height>321</height>
11 </rect> 11 </rect>
12 </property> 12 </property>
@@ -23,34 +23,48 @@
23 </property> 23 </property>
24 <layout class="QVBoxLayout" name="verticalLayout_3"> 24 <layout class="QVBoxLayout" name="verticalLayout_3">
25 <item> 25 <item>
26 <layout class="QHBoxLayout" name="horizontalLayout_2"> 26 <widget class="QWidget" name="gpu_accuracy_layout" native="true">
27 <item> 27 <layout class="QHBoxLayout" name="horizontalLayout_2">
28 <widget class="QLabel" name="label_gpu_accuracy"> 28 <property name="leftMargin">
29 <property name="text"> 29 <number>0</number>
30 <string>Accuracy Level:</string> 30 </property>
31 </property> 31 <property name="topMargin">
32 </widget> 32 <number>0</number>
33 </item> 33 </property>
34 <item> 34 <property name="rightMargin">
35 <widget class="QComboBox" name="gpu_accuracy"> 35 <number>0</number>
36 <item> 36 </property>
37 <property name="bottomMargin">
38 <number>0</number>
39 </property>
40 <item>
41 <widget class="QLabel" name="label_gpu_accuracy">
37 <property name="text"> 42 <property name="text">
38 <string notr="true">Normal</string> 43 <string>Accuracy Level:</string>
39 </property> 44 </property>
40 </item> 45 </widget>
41 <item> 46 </item>
42 <property name="text"> 47 <item>
43 <string notr="true">High</string> 48 <widget class="QComboBox" name="gpu_accuracy">
44 </property> 49 <item>
45 </item> 50 <property name="text">
46 <item> 51 <string notr="true">Normal</string>
47 <property name="text"> 52 </property>
48 <string notr="true">Extreme(very slow)</string> 53 </item>
49 </property> 54 <item>
50 </item> 55 <property name="text">
51 </widget> 56 <string notr="true">High</string>
52 </item> 57 </property>
53 </layout> 58 </item>
59 <item>
60 <property name="text">
61 <string notr="true">Extreme(very slow)</string>
62 </property>
63 </item>
64 </widget>
65 </item>
66 </layout>
67 </widget>
54 </item> 68 </item>
55 <item> 69 <item>
56 <widget class="QCheckBox" name="use_vsync"> 70 <widget class="QCheckBox" name="use_vsync">
@@ -97,44 +111,58 @@
97 </widget> 111 </widget>
98 </item> 112 </item>
99 <item> 113 <item>
100 <layout class="QHBoxLayout" name="horizontalLayout_1"> 114 <widget class="QWidget" name="af_layout" native="true">
101 <item> 115 <layout class="QHBoxLayout" name="horizontalLayout_1">
102 <widget class="QLabel" name="af_label"> 116 <property name="leftMargin">
103 <property name="text"> 117 <number>0</number>
104 <string>Anisotropic Filtering:</string> 118 </property>
105 </property> 119 <property name="topMargin">
106 </widget> 120 <number>0</number>
107 </item> 121 </property>
108 <item> 122 <property name="rightMargin">
109 <widget class="QComboBox" name="anisotropic_filtering_combobox"> 123 <number>0</number>
110 <item> 124 </property>
111 <property name="text"> 125 <property name="bottomMargin">
112 <string>Default</string> 126 <number>0</number>
113 </property> 127 </property>
114 </item> 128 <item>
115 <item> 129 <widget class="QLabel" name="af_label">
116 <property name="text"> 130 <property name="text">
117 <string>2x</string> 131 <string>Anisotropic Filtering:</string>
118 </property> 132 </property>
119 </item> 133 </widget>
120 <item> 134 </item>
121 <property name="text"> 135 <item>
122 <string>4x</string> 136 <widget class="QComboBox" name="anisotropic_filtering_combobox">
123 </property> 137 <item>
124 </item> 138 <property name="text">
125 <item> 139 <string>Default</string>
126 <property name="text"> 140 </property>
127 <string>8x</string> 141 </item>
128 </property> 142 <item>
129 </item> 143 <property name="text">
130 <item> 144 <string>2x</string>
131 <property name="text"> 145 </property>
132 <string>16x</string> 146 </item>
133 </property> 147 <item>
134 </item> 148 <property name="text">
135 </widget> 149 <string>4x</string>
136 </item> 150 </property>
137 </layout> 151 </item>
152 <item>
153 <property name="text">
154 <string>8x</string>
155 </property>
156 </item>
157 <item>
158 <property name="text">
159 <string>16x</string>
160 </property>
161 </item>
162 </widget>
163 </item>
164 </layout>
165 </widget>
138 </item> 166 </item>
139 </layout> 167 </layout>
140 </widget> 168 </widget>
diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp
index 68e02738b..0c4daf147 100644
--- a/src/yuzu/configuration/configure_system.cpp
+++ b/src/yuzu/configuration/configure_system.cpp
@@ -67,21 +67,21 @@ void ConfigureSystem::SetConfiguration() {
67 const auto rtc_time = Settings::values.custom_rtc.GetValue().value_or( 67 const auto rtc_time = Settings::values.custom_rtc.GetValue().value_or(
68 std::chrono::seconds(QDateTime::currentSecsSinceEpoch())); 68 std::chrono::seconds(QDateTime::currentSecsSinceEpoch()));
69 69
70 ui->rng_seed_checkbox->setChecked(Settings::values.rng_seed.GetValue().has_value());
71 ui->rng_seed_edit->setEnabled(Settings::values.rng_seed.GetValue().has_value() &&
72 Settings::values.rng_seed.UsingGlobal());
73 ui->rng_seed_edit->setText(rng_seed);
74
75 ui->custom_rtc_checkbox->setChecked(Settings::values.custom_rtc.GetValue().has_value());
76 ui->custom_rtc_edit->setEnabled(Settings::values.custom_rtc.GetValue().has_value() &&
77 Settings::values.rng_seed.UsingGlobal());
78 ui->custom_rtc_edit->setDateTime(QDateTime::fromSecsSinceEpoch(rtc_time.count()));
79
70 if (Settings::configuring_global) { 80 if (Settings::configuring_global) {
71 ui->combo_language->setCurrentIndex(Settings::values.language_index.GetValue()); 81 ui->combo_language->setCurrentIndex(Settings::values.language_index.GetValue());
72 ui->combo_region->setCurrentIndex(Settings::values.region_index.GetValue()); 82 ui->combo_region->setCurrentIndex(Settings::values.region_index.GetValue());
73 ui->combo_time_zone->setCurrentIndex(Settings::values.time_zone_index.GetValue()); 83 ui->combo_time_zone->setCurrentIndex(Settings::values.time_zone_index.GetValue());
74 ui->combo_sound->setCurrentIndex(Settings::values.sound_index.GetValue()); 84 ui->combo_sound->setCurrentIndex(Settings::values.sound_index.GetValue());
75
76 ui->rng_seed_checkbox->setChecked(Settings::values.rng_seed.GetValue().has_value());
77 ui->rng_seed_edit->setEnabled(Settings::values.rng_seed.GetValue().has_value() &&
78 Settings::values.rng_seed.UsingGlobal());
79 ui->rng_seed_edit->setText(rng_seed);
80
81 ui->custom_rtc_checkbox->setChecked(Settings::values.custom_rtc.GetValue().has_value());
82 ui->custom_rtc_edit->setEnabled(Settings::values.custom_rtc.GetValue().has_value() &&
83 Settings::values.rng_seed.UsingGlobal());
84 ui->custom_rtc_edit->setDateTime(QDateTime::fromSecsSinceEpoch(rtc_time.count()));
85 } else { 85 } else {
86 ConfigurationShared::SetPerGameSetting(ui->combo_language, 86 ConfigurationShared::SetPerGameSetting(ui->combo_language,
87 &Settings::values.language_index); 87 &Settings::values.language_index);
@@ -90,27 +90,14 @@ void ConfigureSystem::SetConfiguration() {
90 &Settings::values.time_zone_index); 90 &Settings::values.time_zone_index);
91 ConfigurationShared::SetPerGameSetting(ui->combo_sound, &Settings::values.sound_index); 91 ConfigurationShared::SetPerGameSetting(ui->combo_sound, &Settings::values.sound_index);
92 92
93 if (Settings::values.rng_seed.UsingGlobal()) { 93 ConfigurationShared::SetHighlight(ui->label_language, "label_language",
94 ui->rng_seed_checkbox->setCheckState(Qt::PartiallyChecked); 94 !Settings::values.language_index.UsingGlobal());
95 } else { 95 ConfigurationShared::SetHighlight(ui->label_region, "label_region",
96 ui->rng_seed_checkbox->setCheckState( 96 !Settings::values.region_index.UsingGlobal());
97 Settings::values.rng_seed.GetValue().has_value() ? Qt::Checked : Qt::Unchecked); 97 ConfigurationShared::SetHighlight(ui->label_timezone, "label_timezone",
98 ui->rng_seed_edit->setEnabled(Settings::values.rng_seed.GetValue().has_value()); 98 !Settings::values.time_zone_index.UsingGlobal());
99 if (Settings::values.rng_seed.GetValue().has_value()) { 99 ConfigurationShared::SetHighlight(ui->label_sound, "label_sound",
100 ui->rng_seed_edit->setText(rng_seed); 100 !Settings::values.sound_index.UsingGlobal());
101 }
102 }
103
104 if (Settings::values.custom_rtc.UsingGlobal()) {
105 ui->custom_rtc_checkbox->setCheckState(Qt::PartiallyChecked);
106 } else {
107 ui->custom_rtc_checkbox->setCheckState(
108 Settings::values.custom_rtc.GetValue().has_value() ? Qt::Checked : Qt::Unchecked);
109 ui->custom_rtc_edit->setEnabled(Settings::values.custom_rtc.GetValue().has_value());
110 if (Settings::values.custom_rtc.GetValue().has_value()) {
111 ui->custom_rtc_edit->setDateTime(QDateTime::fromSecsSinceEpoch(rtc_time.count()));
112 }
113 }
114 } 101 }
115} 102}
116 103
@@ -161,37 +148,44 @@ void ConfigureSystem::ApplyConfiguration() {
161 ui->combo_time_zone); 148 ui->combo_time_zone);
162 ConfigurationShared::ApplyPerGameSetting(&Settings::values.sound_index, ui->combo_sound); 149 ConfigurationShared::ApplyPerGameSetting(&Settings::values.sound_index, ui->combo_sound);
163 150
164 switch (ui->rng_seed_checkbox->checkState()) { 151 switch (use_rng_seed) {
165 case Qt::Checked: 152 case ConfigurationShared::CheckState::On:
166 Settings::values.rng_seed.SetGlobal(false); 153 case ConfigurationShared::CheckState::Off:
167 Settings::values.rng_seed.SetValue(ui->rng_seed_edit->text().toULongLong(nullptr, 16));
168 break;
169 case Qt::Unchecked:
170 Settings::values.rng_seed.SetGlobal(false); 154 Settings::values.rng_seed.SetGlobal(false);
171 Settings::values.rng_seed.SetValue(std::nullopt); 155 if (ui->rng_seed_checkbox->isChecked()) {
156 Settings::values.rng_seed.SetValue(
157 ui->rng_seed_edit->text().toULongLong(nullptr, 16));
158 } else {
159 Settings::values.rng_seed.SetValue(std::nullopt);
160 }
172 break; 161 break;
173 case Qt::PartiallyChecked: 162 case ConfigurationShared::CheckState::Global:
174 Settings::values.rng_seed.SetGlobal(false); 163 Settings::values.rng_seed.SetGlobal(false);
175 Settings::values.rng_seed.SetValue(std::nullopt); 164 Settings::values.rng_seed.SetValue(std::nullopt);
176 Settings::values.rng_seed.SetGlobal(true); 165 Settings::values.rng_seed.SetGlobal(true);
177 break; 166 break;
167 case ConfigurationShared::CheckState::Count:
168 break;
178 } 169 }
179 170
180 switch (ui->custom_rtc_checkbox->checkState()) { 171 switch (use_custom_rtc) {
181 case Qt::Checked: 172 case ConfigurationShared::CheckState::On:
182 Settings::values.custom_rtc.SetGlobal(false); 173 case ConfigurationShared::CheckState::Off:
183 Settings::values.custom_rtc.SetValue(
184 std::chrono::seconds(ui->custom_rtc_edit->dateTime().toSecsSinceEpoch()));
185 break;
186 case Qt::Unchecked:
187 Settings::values.custom_rtc.SetGlobal(false); 174 Settings::values.custom_rtc.SetGlobal(false);
188 Settings::values.custom_rtc.SetValue(std::nullopt); 175 if (ui->custom_rtc_checkbox->isChecked()) {
176 Settings::values.custom_rtc.SetValue(
177 std::chrono::seconds(ui->custom_rtc_edit->dateTime().toSecsSinceEpoch()));
178 } else {
179 Settings::values.custom_rtc.SetValue(std::nullopt);
180 }
189 break; 181 break;
190 case Qt::PartiallyChecked: 182 case ConfigurationShared::CheckState::Global:
191 Settings::values.custom_rtc.SetGlobal(false); 183 Settings::values.custom_rtc.SetGlobal(false);
192 Settings::values.custom_rtc.SetValue(std::nullopt); 184 Settings::values.custom_rtc.SetValue(std::nullopt);
193 Settings::values.custom_rtc.SetGlobal(true); 185 Settings::values.custom_rtc.SetGlobal(true);
194 break; 186 break;
187 case ConfigurationShared::CheckState::Count:
188 break;
195 } 189 }
196 } 190 }
197 191
@@ -229,10 +223,23 @@ void ConfigureSystem::SetupPerGameUI() {
229 return; 223 return;
230 } 224 }
231 225
232 ConfigurationShared::InsertGlobalItem(ui->combo_language); 226 ConfigurationShared::SetColoredComboBox(ui->combo_language, ui->label_language,
233 ConfigurationShared::InsertGlobalItem(ui->combo_region); 227 "label_language",
234 ConfigurationShared::InsertGlobalItem(ui->combo_time_zone); 228 Settings::values.language_index.GetValue(true));
235 ConfigurationShared::InsertGlobalItem(ui->combo_sound); 229 ConfigurationShared::SetColoredComboBox(ui->combo_region, ui->label_region, "label_region",
236 ui->rng_seed_checkbox->setTristate(true); 230 Settings::values.region_index.GetValue(true));
237 ui->custom_rtc_checkbox->setTristate(true); 231 ConfigurationShared::SetColoredComboBox(ui->combo_time_zone, ui->label_timezone,
232 "label_timezone",
233 Settings::values.time_zone_index.GetValue(true));
234 ConfigurationShared::SetColoredComboBox(ui->combo_sound, ui->label_sound, "label_sound",
235 Settings::values.sound_index.GetValue(true));
236
237 ConfigurationShared::SetColoredTristate(
238 ui->rng_seed_checkbox, "rng_seed_checkbox", Settings::values.rng_seed.UsingGlobal(),
239 Settings::values.rng_seed.GetValue().has_value(),
240 Settings::values.rng_seed.GetValue(true).has_value(), use_rng_seed);
241 ConfigurationShared::SetColoredTristate(
242 ui->custom_rtc_checkbox, "custom_rtc_checkbox", Settings::values.custom_rtc.UsingGlobal(),
243 Settings::values.custom_rtc.GetValue().has_value(),
244 Settings::values.custom_rtc.GetValue(true).has_value(), use_custom_rtc);
238} 245}
diff --git a/src/yuzu/configuration/configure_system.h b/src/yuzu/configuration/configure_system.h
index f317ef8b5..fc5cd2945 100644
--- a/src/yuzu/configuration/configure_system.h
+++ b/src/yuzu/configuration/configure_system.h
@@ -9,6 +9,10 @@
9#include <QList> 9#include <QList>
10#include <QWidget> 10#include <QWidget>
11 11
12namespace ConfigurationShared {
13enum class CheckState;
14}
15
12namespace Ui { 16namespace Ui {
13class ConfigureSystem; 17class ConfigureSystem;
14} 18}
@@ -41,4 +45,7 @@ private:
41 int region_index = 0; 45 int region_index = 0;
42 int time_zone_index = 0; 46 int time_zone_index = 0;
43 int sound_index = 0; 47 int sound_index = 0;
48
49 ConfigurationShared::CheckState use_rng_seed;
50 ConfigurationShared::CheckState use_custom_rtc;
44}; 51};
diff --git a/src/yuzu/configuration/configure_system.ui b/src/yuzu/configuration/configure_system.ui
index 9c8cca6dc..53b95658b 100644
--- a/src/yuzu/configuration/configure_system.ui
+++ b/src/yuzu/configuration/configure_system.ui
@@ -21,490 +21,494 @@
21 <property name="title"> 21 <property name="title">
22 <string>System Settings</string> 22 <string>System Settings</string>
23 </property> 23 </property>
24 <layout class="QGridLayout" name="gridLayout"> 24 <layout class="QVBoxLayout" name="verticalLayout_2">
25 <item row="3" column="0"> 25 <item>
26 <widget class="QLabel" name="label_sound"> 26 <layout class="QGridLayout" name="gridLayout_2">
27 <property name="text"> 27 <item row="1" column="0">
28 <string>Sound output mode</string> 28 <widget class="QLabel" name="label_region">
29 </property> 29 <property name="text">
30 </widget> 30 <string>Region:</string>
31 </item> 31 </property>
32 <item row="4" column="0"> 32 </widget>
33 <widget class="QLabel" name="label_console_id"> 33 </item>
34 <property name="text"> 34 <item row="2" column="1">
35 <string>Console ID:</string> 35 <widget class="QComboBox" name="combo_time_zone">
36 </property> 36 <item>
37 </widget> 37 <property name="text">
38 </item> 38 <string>Auto</string>
39 <item row="0" column="1"> 39 </property>
40 <widget class="QComboBox" name="combo_language"> 40 </item>
41 <property name="toolTip"> 41 <item>
42 <string>Note: this can be overridden when region setting is auto-select</string> 42 <property name="text">
43 </property> 43 <string>Default</string>
44 <item> 44 </property>
45 <property name="text"> 45 </item>
46 <string>Japanese (日本語)</string> 46 <item>
47 </property> 47 <property name="text">
48 </item> 48 <string>CET</string>
49 <item> 49 </property>
50 <property name="text"> 50 </item>
51 <string>English</string> 51 <item>
52 </property> 52 <property name="text">
53 </item> 53 <string>CST6CDT</string>
54 <item> 54 </property>
55 <property name="text"> 55 </item>
56 <string>French (français)</string> 56 <item>
57 </property> 57 <property name="text">
58 </item> 58 <string>Cuba</string>
59 <item> 59 </property>
60 <property name="text"> 60 </item>
61 <string>German (Deutsch)</string> 61 <item>
62 </property> 62 <property name="text">
63 </item> 63 <string>EET</string>
64 <item> 64 </property>
65 <property name="text"> 65 </item>
66 <string>Italian (italiano)</string> 66 <item>
67 </property> 67 <property name="text">
68 </item> 68 <string>Egypt</string>
69 <item> 69 </property>
70 <property name="text"> 70 </item>
71 <string>Spanish (español)</string> 71 <item>
72 </property> 72 <property name="text">
73 </item> 73 <string>Eire</string>
74 <item> 74 </property>
75 <property name="text"> 75 </item>
76 <string>Chinese</string> 76 <item>
77 </property> 77 <property name="text">
78 </item> 78 <string>EST</string>
79 <item> 79 </property>
80 <property name="text"> 80 </item>
81 <string>Korean (한국어)</string> 81 <item>
82 </property> 82 <property name="text">
83 </item> 83 <string>EST5EDT</string>
84 <item> 84 </property>
85 <property name="text"> 85 </item>
86 <string>Dutch (Nederlands)</string> 86 <item>
87 </property> 87 <property name="text">
88 </item> 88 <string>GB</string>
89 <item> 89 </property>
90 <property name="text"> 90 </item>
91 <string>Portuguese (português)</string> 91 <item>
92 </property> 92 <property name="text">
93 </item> 93 <string>GB-Eire</string>
94 <item> 94 </property>
95 <property name="text"> 95 </item>
96 <string>Russian (Русский)</string> 96 <item>
97 </property> 97 <property name="text">
98 </item> 98 <string>GMT</string>
99 <item> 99 </property>
100 <property name="text"> 100 </item>
101 <string>Taiwanese</string> 101 <item>
102 </property> 102 <property name="text">
103 </item> 103 <string>GMT+0</string>
104 <item> 104 </property>
105 <property name="text"> 105 </item>
106 <string>British English</string> 106 <item>
107 </property> 107 <property name="text">
108 </item> 108 <string>GMT-0</string>
109 <item> 109 </property>
110 <property name="text"> 110 </item>
111 <string>Canadian French</string> 111 <item>
112 </property> 112 <property name="text">
113 </item> 113 <string>GMT0</string>
114 <item> 114 </property>
115 <property name="text"> 115 </item>
116 <string>Latin American Spanish</string> 116 <item>
117 </property> 117 <property name="text">
118 </item> 118 <string>Greenwich</string>
119 <item> 119 </property>
120 <property name="text"> 120 </item>
121 <string>Simplified Chinese</string> 121 <item>
122 </property> 122 <property name="text">
123 </item> 123 <string>Hongkong</string>
124 <item> 124 </property>
125 <property name="text"> 125 </item>
126 <string>Traditional Chinese (正體中文)</string> 126 <item>
127 </property> 127 <property name="text">
128 </item> 128 <string>HST</string>
129 </widget> 129 </property>
130 </item> 130 </item>
131 <item row="1" column="0"> 131 <item>
132 <widget class="QLabel" name="label_region"> 132 <property name="text">
133 <property name="text"> 133 <string>Iceland</string>
134 <string>Region:</string> 134 </property>
135 </property> 135 </item>
136 </widget> 136 <item>
137 </item> 137 <property name="text">
138 <item row="1" column="1"> 138 <string>Iran</string>
139 <widget class="QComboBox" name="combo_region"> 139 </property>
140 <item> 140 </item>
141 <property name="text"> 141 <item>
142 <string>Japan</string> 142 <property name="text">
143 </property> 143 <string>Israel</string>
144 </item> 144 </property>
145 <item> 145 </item>
146 <property name="text"> 146 <item>
147 <string>USA</string> 147 <property name="text">
148 </property> 148 <string>Jamaica</string>
149 </item> 149 </property>
150 <item> 150 </item>
151 <property name="text"> 151 <item>
152 <string>Europe</string> 152 <property name="text">
153 </property> 153 <string>Japan</string>
154 </item> 154 </property>
155 <item> 155 </item>
156 <property name="text"> 156 <item>
157 <string>Australia</string> 157 <property name="text">
158 </property> 158 <string>Kwajalein</string>
159 </item> 159 </property>
160 <item> 160 </item>
161 <property name="text"> 161 <item>
162 <string>China</string> 162 <property name="text">
163 </property> 163 <string>Libya</string>
164 </item> 164 </property>
165 <item> 165 </item>
166 <property name="text"> 166 <item>
167 <string>Korea</string> 167 <property name="text">
168 </property> 168 <string>MET</string>
169 </item> 169 </property>
170 <item> 170 </item>
171 <property name="text"> 171 <item>
172 <string>Taiwan</string> 172 <property name="text">
173 </property> 173 <string>MST</string>
174 </item> 174 </property>
175 </widget> 175 </item>
176 </item> 176 <item>
177 <item row="2" column="0"> 177 <property name="text">
178 <widget class="QLabel" name="label_timezone"> 178 <string>MST7MDT</string>
179 <property name="text"> 179 </property>
180 <string>Time Zone:</string> 180 </item>
181 </property> 181 <item>
182 </widget> 182 <property name="text">
183 </item> 183 <string>Navajo</string>
184 <item row="2" column="1"> 184 </property>
185 <widget class="QComboBox" name="combo_time_zone"> 185 </item>
186 <item> 186 <item>
187 <property name="text"> 187 <property name="text">
188 <string>Auto</string> 188 <string>NZ</string>
189 </property> 189 </property>
190 </item> 190 </item>
191 <item> 191 <item>
192 <property name="text"> 192 <property name="text">
193 <string>Default</string> 193 <string>NZ-CHAT</string>
194 </property> 194 </property>
195 </item> 195 </item>
196 <item> 196 <item>
197 <property name="text"> 197 <property name="text">
198 <string>CET</string> 198 <string>Poland</string>
199 </property> 199 </property>
200 </item> 200 </item>
201 <item> 201 <item>
202 <property name="text"> 202 <property name="text">
203 <string>CST6CDT</string> 203 <string>Portugal</string>
204 </property> 204 </property>
205 </item> 205 </item>
206 <item> 206 <item>
207 <property name="text"> 207 <property name="text">
208 <string>Cuba</string> 208 <string>PRC</string>
209 </property> 209 </property>
210 </item> 210 </item>
211 <item> 211 <item>
212 <property name="text"> 212 <property name="text">
213 <string>EET</string> 213 <string>PST8PDT</string>
214 </property> 214 </property>
215 </item> 215 </item>
216 <item> 216 <item>
217 <property name="text"> 217 <property name="text">
218 <string>Egypt</string> 218 <string>ROC</string>
219 </property> 219 </property>
220 </item> 220 </item>
221 <item> 221 <item>
222 <property name="text"> 222 <property name="text">
223 <string>Eire</string> 223 <string>ROK</string>
224 </property> 224 </property>
225 </item> 225 </item>
226 <item> 226 <item>
227 <property name="text"> 227 <property name="text">
228 <string>EST</string> 228 <string>Singapore</string>
229 </property> 229 </property>
230 </item> 230 </item>
231 <item> 231 <item>
232 <property name="text"> 232 <property name="text">
233 <string>EST5EDT</string> 233 <string>Turkey</string>
234 </property> 234 </property>
235 </item> 235 </item>
236 <item> 236 <item>
237 <property name="text"> 237 <property name="text">
238 <string>GB</string> 238 <string>UCT</string>
239 </property> 239 </property>
240 </item> 240 </item>
241 <item> 241 <item>
242 <property name="text"> 242 <property name="text">
243 <string>GB-Eire</string> 243 <string>Universal</string>
244 </property> 244 </property>
245 </item> 245 </item>
246 <item> 246 <item>
247 <property name="text"> 247 <property name="text">
248 <string>GMT</string> 248 <string>UTC</string>
249 </property> 249 </property>
250 </item> 250 </item>
251 <item> 251 <item>
252 <property name="text"> 252 <property name="text">
253 <string>GMT+0</string> 253 <string>W-SU</string>
254 </property> 254 </property>
255 </item> 255 </item>
256 <item> 256 <item>
257 <property name="text"> 257 <property name="text">
258 <string>GMT-0</string> 258 <string>WET</string>
259 </property> 259 </property>
260 </item> 260 </item>
261 <item> 261 <item>
262 <property name="text"> 262 <property name="text">
263 <string>GMT0</string> 263 <string>Zulu</string>
264 </property> 264 </property>
265 </item> 265 </item>
266 <item> 266 </widget>
267 <property name="text"> 267 </item>
268 <string>Greenwich</string> 268 <item row="1" column="1">
269 </property> 269 <widget class="QComboBox" name="combo_region">
270 </item> 270 <item>
271 <item> 271 <property name="text">
272 <property name="text"> 272 <string>Japan</string>
273 <string>Hongkong</string> 273 </property>
274 </property> 274 </item>
275 </item> 275 <item>
276 <item> 276 <property name="text">
277 <property name="text"> 277 <string>USA</string>
278 <string>HST</string> 278 </property>
279 </property> 279 </item>
280 </item> 280 <item>
281 <item> 281 <property name="text">
282 <property name="text"> 282 <string>Europe</string>
283 <string>Iceland</string> 283 </property>
284 </property> 284 </item>
285 </item> 285 <item>
286 <item> 286 <property name="text">
287 <property name="text"> 287 <string>Australia</string>
288 <string>Iran</string> 288 </property>
289 </property> 289 </item>
290 </item> 290 <item>
291 <item> 291 <property name="text">
292 <property name="text"> 292 <string>China</string>
293 <string>Israel</string> 293 </property>
294 </property> 294 </item>
295 </item> 295 <item>
296 <item> 296 <property name="text">
297 <property name="text"> 297 <string>Korea</string>
298 <string>Jamaica</string> 298 </property>
299 </property> 299 </item>
300 </item> 300 <item>
301 <item> 301 <property name="text">
302 <property name="text"> 302 <string>Taiwan</string>
303 <string>Japan</string> 303 </property>
304 </property> 304 </item>
305 </item> 305 </widget>
306 <item> 306 </item>
307 <property name="text"> 307 <item row="2" column="0">
308 <string>Kwajalein</string> 308 <widget class="QLabel" name="label_timezone">
309 </property> 309 <property name="text">
310 </item> 310 <string>Time Zone:</string>
311 <item> 311 </property>
312 <property name="text"> 312 </widget>
313 <string>Libya</string> 313 </item>
314 </property> 314 <item row="0" column="1">
315 </item> 315 <widget class="QComboBox" name="combo_language">
316 <item> 316 <property name="toolTip">
317 <property name="text"> 317 <string>Note: this can be overridden when region setting is auto-select</string>
318 <string>MET</string> 318 </property>
319 </property> 319 <item>
320 </item> 320 <property name="text">
321 <item> 321 <string>Japanese (日本語)</string>
322 <property name="text"> 322 </property>
323 <string>MST</string> 323 </item>
324 </property> 324 <item>
325 </item> 325 <property name="text">
326 <item> 326 <string>English</string>
327 <property name="text"> 327 </property>
328 <string>MST7MDT</string> 328 </item>
329 </property> 329 <item>
330 </item> 330 <property name="text">
331 <item> 331 <string>French (français)</string>
332 <property name="text"> 332 </property>
333 <string>Navajo</string> 333 </item>
334 </property> 334 <item>
335 </item> 335 <property name="text">
336 <item> 336 <string>German (Deutsch)</string>
337 <property name="text"> 337 </property>
338 <string>NZ</string> 338 </item>
339 </property> 339 <item>
340 </item> 340 <property name="text">
341 <item> 341 <string>Italian (italiano)</string>
342 <property name="text"> 342 </property>
343 <string>NZ-CHAT</string> 343 </item>
344 </property> 344 <item>
345 </item> 345 <property name="text">
346 <item> 346 <string>Spanish (español)</string>
347 <property name="text"> 347 </property>
348 <string>Poland</string> 348 </item>
349 </property> 349 <item>
350 </item> 350 <property name="text">
351 <item> 351 <string>Chinese</string>
352 <property name="text"> 352 </property>
353 <string>Portugal</string> 353 </item>
354 </property> 354 <item>
355 </item> 355 <property name="text">
356 <item> 356 <string>Korean (한국어)</string>
357 <property name="text"> 357 </property>
358 <string>PRC</string> 358 </item>
359 </property> 359 <item>
360 </item> 360 <property name="text">
361 <item> 361 <string>Dutch (Nederlands)</string>
362 <property name="text"> 362 </property>
363 <string>PST8PDT</string> 363 </item>
364 </property> 364 <item>
365 </item> 365 <property name="text">
366 <item> 366 <string>Portuguese (português)</string>
367 <property name="text"> 367 </property>
368 <string>ROC</string> 368 </item>
369 </property> 369 <item>
370 </item> 370 <property name="text">
371 <item> 371 <string>Russian (Русский)</string>
372 <property name="text"> 372 </property>
373 <string>ROK</string> 373 </item>
374 </property> 374 <item>
375 </item> 375 <property name="text">
376 <item> 376 <string>Taiwanese</string>
377 <property name="text"> 377 </property>
378 <string>Singapore</string> 378 </item>
379 </property> 379 <item>
380 </item> 380 <property name="text">
381 <item> 381 <string>British English</string>
382 <property name="text"> 382 </property>
383 <string>Turkey</string> 383 </item>
384 </property> 384 <item>
385 </item> 385 <property name="text">
386 <item> 386 <string>Canadian French</string>
387 <property name="text"> 387 </property>
388 <string>UCT</string> 388 </item>
389 </property> 389 <item>
390 </item> 390 <property name="text">
391 <item> 391 <string>Latin American Spanish</string>
392 <property name="text"> 392 </property>
393 <string>Universal</string> 393 </item>
394 </property> 394 <item>
395 </item> 395 <property name="text">
396 <item> 396 <string>Simplified Chinese</string>
397 <property name="text"> 397 </property>
398 <string>UTC</string> 398 </item>
399 </property> 399 <item>
400 </item> 400 <property name="text">
401 <item> 401 <string>Traditional Chinese (正體中文)</string>
402 <property name="text"> 402 </property>
403 <string>W-SU</string> 403 </item>
404 </property> 404 </widget>
405 </item> 405 </item>
406 <item> 406 <item row="5" column="0">
407 <property name="text"> 407 <widget class="QCheckBox" name="custom_rtc_checkbox">
408 <string>WET</string> 408 <property name="text">
409 </property> 409 <string>Custom RTC</string>
410 </item> 410 </property>
411 <item> 411 </widget>
412 <property name="text"> 412 </item>
413 <string>Zulu</string> 413 <item row="0" column="0">
414 </property> 414 <widget class="QLabel" name="label_language">
415 </item> 415 <property name="text">
416 </widget> 416 <string>Language</string>
417 </item> 417 </property>
418 <item row="6" column="0"> 418 </widget>
419 <widget class="QCheckBox" name="rng_seed_checkbox"> 419 </item>
420 <property name="text"> 420 <item row="6" column="0">
421 <string>RNG Seed</string> 421 <widget class="QCheckBox" name="rng_seed_checkbox">
422 </property> 422 <property name="text">
423 </widget> 423 <string>RNG Seed</string>
424 </item> 424 </property>
425 <item row="3" column="1"> 425 </widget>
426 <widget class="QComboBox" name="combo_sound"> 426 </item>
427 <item> 427 <item row="3" column="1">
428 <property name="text"> 428 <widget class="QComboBox" name="combo_sound">
429 <string>Mono</string> 429 <item>
430 </property> 430 <property name="text">
431 </item> 431 <string>Mono</string>
432 <item> 432 </property>
433 <property name="text"> 433 </item>
434 <string>Stereo</string> 434 <item>
435 </property> 435 <property name="text">
436 </item> 436 <string>Stereo</string>
437 <item> 437 </property>
438 <property name="text"> 438 </item>
439 <string>Surround</string> 439 <item>
440 </property> 440 <property name="text">
441 </item> 441 <string>Surround</string>
442 </widget> 442 </property>
443 </item> 443 </item>
444 <item row="0" column="0"> 444 </widget>
445 <widget class="QLabel" name="label_language"> 445 </item>
446 <property name="text"> 446 <item row="4" column="0">
447 <string>Language</string> 447 <widget class="QLabel" name="label_console_id">
448 </property> 448 <property name="text">
449 </widget> 449 <string>Console ID:</string>
450 </item> 450 </property>
451 <item row="4" column="1"> 451 </widget>
452 <widget class="QPushButton" name="button_regenerate_console_id"> 452 </item>
453 <property name="sizePolicy"> 453 <item row="3" column="0">
454 <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> 454 <widget class="QLabel" name="label_sound">
455 <horstretch>0</horstretch> 455 <property name="text">
456 <verstretch>0</verstretch> 456 <string>Sound output mode</string>
457 </sizepolicy> 457 </property>
458 </property> 458 </widget>
459 <property name="layoutDirection"> 459 </item>
460 <enum>Qt::RightToLeft</enum> 460 <item row="5" column="1">
461 </property> 461 <widget class="QDateTimeEdit" name="custom_rtc_edit">
462 <property name="text"> 462 <property name="minimumDate">
463 <string>Regenerate</string> 463 <date>
464 </property> 464 <year>1970</year>
465 </widget> 465 <month>1</month>
466 </item> 466 <day>1</day>
467 <item row="5" column="0"> 467 </date>
468 <widget class="QCheckBox" name="custom_rtc_checkbox"> 468 </property>
469 <property name="text"> 469 <property name="displayFormat">
470 <string>Custom RTC</string> 470 <string>d MMM yyyy h:mm:ss AP</string>
471 </property> 471 </property>
472 </widget> 472 </widget>
473 </item> 473 </item>
474 <item row="5" column="1"> 474 <item row="6" column="1">
475 <widget class="QDateTimeEdit" name="custom_rtc_edit"> 475 <widget class="QLineEdit" name="rng_seed_edit">
476 <property name="minimumDate"> 476 <property name="sizePolicy">
477 <date> 477 <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
478 <year>1970</year> 478 <horstretch>0</horstretch>
479 <month>1</month> 479 <verstretch>0</verstretch>
480 <day>1</day> 480 </sizepolicy>
481 </date> 481 </property>
482 </property> 482 <property name="font">
483 <property name="displayFormat"> 483 <font>
484 <string>d MMM yyyy h:mm:ss AP</string> 484 <family>Lucida Console</family>
485 </property> 485 </font>
486 </widget> 486 </property>
487 </item> 487 <property name="inputMask">
488 <item row="6" column="1"> 488 <string notr="true">HHHHHHHH</string>
489 <widget class="QLineEdit" name="rng_seed_edit"> 489 </property>
490 <property name="sizePolicy"> 490 <property name="maxLength">
491 <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> 491 <number>8</number>
492 <horstretch>0</horstretch> 492 </property>
493 <verstretch>0</verstretch> 493 </widget>
494 </sizepolicy> 494 </item>
495 </property> 495 <item row="4" column="1">
496 <property name="font"> 496 <widget class="QPushButton" name="button_regenerate_console_id">
497 <font> 497 <property name="sizePolicy">
498 <family>Lucida Console</family> 498 <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
499 </font> 499 <horstretch>0</horstretch>
500 </property> 500 <verstretch>0</verstretch>
501 <property name="inputMask"> 501 </sizepolicy>
502 <string notr="true">HHHHHHHH</string> 502 </property>
503 </property> 503 <property name="layoutDirection">
504 <property name="maxLength"> 504 <enum>Qt::RightToLeft</enum>
505 <number>8</number> 505 </property>
506 </property> 506 <property name="text">
507 </widget> 507 <string>Regenerate</string>
508 </property>
509 </widget>
510 </item>
511 </layout>
508 </item> 512 </item>
509 </layout> 513 </layout>
510 </widget> 514 </widget>
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index f391a41a9..3439cb333 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -38,7 +38,10 @@ constexpr std::array<std::array<Qt::GlobalColor, 2>, 10> WaitTreeColors{{
38 38
39bool IsDarkTheme() { 39bool IsDarkTheme() {
40 const auto& theme = UISettings::values.theme; 40 const auto& theme = UISettings::values.theme;
41 return theme == QStringLiteral("qdarkstyle") || theme == QStringLiteral("colorful_dark"); 41 return theme == QStringLiteral("qdarkstyle") ||
42 theme == QStringLiteral("qdarkstyle_midnight_blue") ||
43 theme == QStringLiteral("colorful_dark") ||
44 theme == QStringLiteral("colorful_midnight_blue");
42} 45}
43 46
44} // namespace 47} // namespace
diff --git a/src/yuzu/uisettings.cpp b/src/yuzu/uisettings.cpp
index 738c4b2fc..a51175f36 100644
--- a/src/yuzu/uisettings.cpp
+++ b/src/yuzu/uisettings.cpp
@@ -11,6 +11,8 @@ const Themes themes{{
11 {"Light Colorful", "colorful"}, 11 {"Light Colorful", "colorful"},
12 {"Dark", "qdarkstyle"}, 12 {"Dark", "qdarkstyle"},
13 {"Dark Colorful", "colorful_dark"}, 13 {"Dark Colorful", "colorful_dark"},
14 {"Midnight Blue", "qdarkstyle_midnight_blue"},
15 {"Midnight Blue Colorful", "colorful_midnight_blue"},
14}}; 16}};
15 17
16Values values = {}; 18Values values = {};
diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h
index 6cc65736d..ac7b9aef6 100644
--- a/src/yuzu/uisettings.h
+++ b/src/yuzu/uisettings.h
@@ -24,7 +24,7 @@ struct Shortcut {
24 ContextualShortcut shortcut; 24 ContextualShortcut shortcut;
25}; 25};
26 26
27using Themes = std::array<std::pair<const char*, const char*>, 4>; 27using Themes = std::array<std::pair<const char*, const char*>, 6>;
28extern const Themes themes; 28extern const Themes themes;
29 29
30struct GameDir { 30struct GameDir {