summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeModules/CopyYuzuQt5Deps.cmake12
-rw-r--r--README.md3
-rw-r--r--dist/license.md6
-rw-r--r--dist/qt_themes/default/icons/16x16/checked.pngbin451 -> 657 bytes
-rw-r--r--dist/qt_themes/default/icons/16x16/failed.pngbin428 -> 524 bytes
-rw-r--r--license.txt4
-rw-r--r--src/core/core.cpp2
-rw-r--r--src/core/gdbstub/gdbstub.cpp9
-rw-r--r--src/core/gdbstub/gdbstub.h7
-rw-r--r--src/core/hle/service/am/am.cpp42
-rw-r--r--src/core/hle/service/am/am.h3
-rw-r--r--src/core/hle/service/am/applets/web_browser.cpp6
-rw-r--r--src/core/hle/service/hid/hid.cpp9
-rw-r--r--src/core/hle/service/hid/hid.h1
-rw-r--r--src/core/hle/service/sm/controller.cpp2
-rw-r--r--src/video_core/engines/const_buffer_engine_interface.h14
-rw-r--r--src/video_core/engines/maxwell_3d.cpp25
-rw-r--r--src/video_core/engines/maxwell_3d.h23
-rw-r--r--src/video_core/engines/shader_bytecode.h6
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp10
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp67
-rw-r--r--src/video_core/renderer_vulkan/maxwell_to_vk.cpp20
-rw-r--r--src/video_core/shader/decode/xmad.cpp9
-rw-r--r--src/video_core/shader/shader_ir.cpp85
-rw-r--r--src/video_core/shader/shader_ir.h8
-rw-r--r--src/yuzu/main.cpp15
26 files changed, 299 insertions, 89 deletions
diff --git a/CMakeModules/CopyYuzuQt5Deps.cmake b/CMakeModules/CopyYuzuQt5Deps.cmake
index 1e9810bba..2598b9b60 100644
--- a/CMakeModules/CopyYuzuQt5Deps.cmake
+++ b/CMakeModules/CopyYuzuQt5Deps.cmake
@@ -6,9 +6,9 @@ function(copy_yuzu_Qt5_deps target_dir)
6 set(Qt5_STYLES_DIR "${Qt5_DIR}/../../../plugins/styles/") 6 set(Qt5_STYLES_DIR "${Qt5_DIR}/../../../plugins/styles/")
7 set(Qt5_IMAGEFORMATS_DIR "${Qt5_DIR}/../../../plugins/imageformats/") 7 set(Qt5_IMAGEFORMATS_DIR "${Qt5_DIR}/../../../plugins/imageformats/")
8 set(Qt5_RESOURCES_DIR "${Qt5_DIR}/../../../resources/") 8 set(Qt5_RESOURCES_DIR "${Qt5_DIR}/../../../resources/")
9 set(PLATFORMS ${DLL_DEST}platforms/) 9 set(PLATFORMS ${DLL_DEST}plugins/platforms/)
10 set(STYLES ${DLL_DEST}styles/) 10 set(STYLES ${DLL_DEST}plugins/styles/)
11 set(IMAGEFORMATS ${DLL_DEST}imageformats/) 11 set(IMAGEFORMATS ${DLL_DEST}plugins/imageformats/)
12 windows_copy_files(${target_dir} ${Qt5_DLL_DIR} ${DLL_DEST} 12 windows_copy_files(${target_dir} ${Qt5_DLL_DIR} ${DLL_DEST}
13 icudt*.dll 13 icudt*.dll
14 icuin*.dll 14 icuin*.dll
@@ -42,11 +42,15 @@ function(copy_yuzu_Qt5_deps target_dir)
42 icudtl.dat 42 icudtl.dat
43 ) 43 )
44 endif () 44 endif ()
45
46 windows_copy_files(yuzu ${Qt5_PLATFORMS_DIR} ${PLATFORMS} qwindows$<$<CONFIG:Debug>:d>.*) 45 windows_copy_files(yuzu ${Qt5_PLATFORMS_DIR} ${PLATFORMS} qwindows$<$<CONFIG:Debug>:d>.*)
47 windows_copy_files(yuzu ${Qt5_STYLES_DIR} ${STYLES} qwindowsvistastyle$<$<CONFIG:Debug>:d>.*) 46 windows_copy_files(yuzu ${Qt5_STYLES_DIR} ${STYLES} qwindowsvistastyle$<$<CONFIG:Debug>:d>.*)
48 windows_copy_files(yuzu ${Qt5_IMAGEFORMATS_DIR} ${IMAGEFORMATS} 47 windows_copy_files(yuzu ${Qt5_IMAGEFORMATS_DIR} ${IMAGEFORMATS}
49 qjpeg$<$<CONFIG:Debug>:d>.* 48 qjpeg$<$<CONFIG:Debug>:d>.*
50 qgif$<$<CONFIG:Debug>:d>.* 49 qgif$<$<CONFIG:Debug>:d>.*
51 ) 50 )
51 # Create an empty qt.conf file. Qt will detect that this file exists, and use the folder that its in as the root folder.
52 # This way it'll look for plugins in the root/plugins/ folder
53 add_custom_command(TARGET yuzu POST_BUILD
54 COMMAND ${CMAKE_COMMAND} -E touch ${DLL_DEST}qt.conf
55 )
52endfunction(copy_yuzu_Qt5_deps) 56endfunction(copy_yuzu_Qt5_deps)
diff --git a/README.md b/README.md
index e8e7946de..1e9f67e08 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,7 @@ yuzu emulator
2============= 2=============
3[![Travis CI Build Status](https://travis-ci.com/yuzu-emu/yuzu.svg?branch=master)](https://travis-ci.com/yuzu-emu/yuzu) 3[![Travis CI Build Status](https://travis-ci.com/yuzu-emu/yuzu.svg?branch=master)](https://travis-ci.com/yuzu-emu/yuzu)
4[![Azure Mainline CI Build Status](https://dev.azure.com/yuzu-emu/yuzu/_apis/build/status/yuzu%20mainline?branchName=master)](https://dev.azure.com/yuzu-emu/yuzu/) 4[![Azure Mainline CI Build Status](https://dev.azure.com/yuzu-emu/yuzu/_apis/build/status/yuzu%20mainline?branchName=master)](https://dev.azure.com/yuzu-emu/yuzu/)
5[![Discord](https://img.shields.io/discord/398318088170242053?color=%237289DA&label=yuzu&logo=discord&logoColor=white)](https://discord.gg/XQV6dn9)
5 6
6yuzu is an experimental open-source emulator for the Nintendo Switch from the creators of [Citra](https://citra-emu.org/). 7yuzu is an experimental open-source emulator for the Nintendo Switch from the creators of [Citra](https://citra-emu.org/).
7 8
@@ -21,7 +22,7 @@ For development discussion, please join us on [Discord](https://discord.gg/XQV6d
21 22
22Most of the development happens on GitHub. It's also where [our central repository](https://github.com/yuzu-emu/yuzu) is hosted. 23Most of the development happens on GitHub. It's also where [our central repository](https://github.com/yuzu-emu/yuzu) is hosted.
23 24
24If you want to contribute please take a look at the [Contributor's Guide](CONTRIBUTING.md) and [Developer Information](https://github.com/yuzu-emu/yuzu/wiki/Developer-Information). You should also contact any of the developers on Discord in order to know about the current state of the emulator. 25If you want to contribute please take a look at the [Contributor's Guide](https://github.com/yuzu-emu/yuzu/wiki/Contributing) and [Developer Information](https://github.com/yuzu-emu/yuzu/wiki/Developer-Information). You should also contact any of the developers on Discord in order to know about the current state of the emulator.
25 26
26### Building 27### Building
27 28
diff --git a/dist/license.md b/dist/license.md
index b777ebb20..f1ff35c95 100644
--- a/dist/license.md
+++ b/dist/license.md
@@ -2,8 +2,8 @@ The icons in this folder and its subfolders have the following licenses:
2 2
3Icon Name | License | Origin/Author 3Icon Name | License | Origin/Author
4--- | --- | --- 4--- | --- | ---
5qt_themes/default/icons/16x16/checked.png | Free for non-commercial use 5qt_themes/default/icons/16x16/checked.png | CC BY-ND 3.0 | https://icons8.com
6qt_themes/default/icons/16x16/failed.png | Free for non-commercial use 6qt_themes/default/icons/16x16/failed.png | CC BY-ND 3.0 | https://icons8.com
7qt_themes/default/icons/16x16/lock.png | CC BY-ND 3.0 | https://icons8.com 7qt_themes/default/icons/16x16/lock.png | CC BY-ND 3.0 | https://icons8.com
8qt_themes/default/icons/256x256/plus_folder.png | CC BY-ND 3.0 | https://icons8.com 8qt_themes/default/icons/256x256/plus_folder.png | CC BY-ND 3.0 | https://icons8.com
9qt_themes/default/icons/48x48/bad_folder.png | CC BY-ND 3.0 | https://icons8.com 9qt_themes/default/icons/48x48/bad_folder.png | CC BY-ND 3.0 | https://icons8.com
@@ -11,8 +11,6 @@ qt_themes/default/icons/48x48/chip.png | CC BY-ND 3.0 | https://icons8.com
11qt_themes/default/icons/48x48/folder.png | CC BY-ND 3.0 | https://icons8.com 11qt_themes/default/icons/48x48/folder.png | CC BY-ND 3.0 | https://icons8.com
12qt_themes/default/icons/48x48/plus.png | CC0 1.0 | Designed by BreadFish64 from the Citra team 12qt_themes/default/icons/48x48/plus.png | CC0 1.0 | Designed by BreadFish64 from the Citra team
13qt_themes/default/icons/48x48/sd_card.png | CC BY-ND 3.0 | https://icons8.com 13qt_themes/default/icons/48x48/sd_card.png | CC BY-ND 3.0 | https://icons8.com
14qt_themes/qdarkstyle/icons/16x16/checked.png | Free for non-commercial use
15qt_themes/qdarkstyle/icons/16x16/failed.png | Free for non-commercial use
16qt_themes/qdarkstyle/icons/16x16/lock.png | CC BY-ND 3.0 | https://icons8.com 14qt_themes/qdarkstyle/icons/16x16/lock.png | CC BY-ND 3.0 | https://icons8.com
17qt_themes/qdarkstyle/icons/256x256/plus_folder.png | CC BY-ND 3.0 | https://icons8.com 15qt_themes/qdarkstyle/icons/256x256/plus_folder.png | CC BY-ND 3.0 | https://icons8.com
18qt_themes/qdarkstyle/icons/48x48/bad_folder.png | CC BY-ND 3.0 | https://icons8.com 16qt_themes/qdarkstyle/icons/48x48/bad_folder.png | CC BY-ND 3.0 | https://icons8.com
diff --git a/dist/qt_themes/default/icons/16x16/checked.png b/dist/qt_themes/default/icons/16x16/checked.png
index c277e6b40..3e017b715 100644
--- a/dist/qt_themes/default/icons/16x16/checked.png
+++ b/dist/qt_themes/default/icons/16x16/checked.png
Binary files differ
diff --git a/dist/qt_themes/default/icons/16x16/failed.png b/dist/qt_themes/default/icons/16x16/failed.png
index ac10f174a..7c4047dd0 100644
--- a/dist/qt_themes/default/icons/16x16/failed.png
+++ b/dist/qt_themes/default/icons/16x16/failed.png
Binary files differ
diff --git a/license.txt b/license.txt
index bf5aec0e6..86e7b3c1b 100644
--- a/license.txt
+++ b/license.txt
@@ -343,8 +343,8 @@ The icons used in this project have the following licenses:
343 343
344Icon Name | License | Origin/Author 344Icon Name | License | Origin/Author
345--- | --- | --- 345--- | --- | ---
346checked.png | Free for non-commercial use 346checked.png | CC BY-ND 3.0 | https://icons8.com
347failed.png | Free for non-commercial use 347failed.png | CC BY-ND 3.0 | https://icons8.com
348lock.png | CC BY-ND 3.0 | https://icons8.com 348lock.png | CC BY-ND 3.0 | https://icons8.com
349plus_folder.png (Default, Dark) | CC BY-ND 3.0 | https://icons8.com 349plus_folder.png (Default, Dark) | CC BY-ND 3.0 | https://icons8.com
350bad_folder.png (Default, Dark) | CC BY-ND 3.0 | https://icons8.com 350bad_folder.png (Default, Dark) | CC BY-ND 3.0 | https://icons8.com
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 218508126..d1bc9340d 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -166,7 +166,7 @@ struct System::Impl {
166 service_manager = std::make_shared<Service::SM::ServiceManager>(); 166 service_manager = std::make_shared<Service::SM::ServiceManager>();
167 167
168 Service::Init(service_manager, system); 168 Service::Init(service_manager, system);
169 GDBStub::Init(); 169 GDBStub::DeferStart();
170 170
171 renderer = VideoCore::CreateRenderer(emu_window, system); 171 renderer = VideoCore::CreateRenderer(emu_window, system);
172 if (!renderer->Init()) { 172 if (!renderer->Init()) {
diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp
index e8d8871a7..6d15aeed9 100644
--- a/src/core/gdbstub/gdbstub.cpp
+++ b/src/core/gdbstub/gdbstub.cpp
@@ -141,6 +141,7 @@ constexpr char target_xml[] =
141)"; 141)";
142 142
143int gdbserver_socket = -1; 143int gdbserver_socket = -1;
144bool defer_start = false;
144 145
145u8 command_buffer[GDB_BUFFER_SIZE]; 146u8 command_buffer[GDB_BUFFER_SIZE];
146u32 command_length; 147u32 command_length;
@@ -1166,6 +1167,9 @@ static void RemoveBreakpoint() {
1166 1167
1167void HandlePacket() { 1168void HandlePacket() {
1168 if (!IsConnected()) { 1169 if (!IsConnected()) {
1170 if (defer_start) {
1171 ToggleServer(true);
1172 }
1169 return; 1173 return;
1170 } 1174 }
1171 1175
@@ -1256,6 +1260,10 @@ void ToggleServer(bool status) {
1256 } 1260 }
1257} 1261}
1258 1262
1263void DeferStart() {
1264 defer_start = true;
1265}
1266
1259static void Init(u16 port) { 1267static void Init(u16 port) {
1260 if (!server_enabled) { 1268 if (!server_enabled) {
1261 // Set the halt loop to false in case the user enabled the gdbstub mid-execution. 1269 // Set the halt loop to false in case the user enabled the gdbstub mid-execution.
@@ -1341,6 +1349,7 @@ void Shutdown() {
1341 if (!server_enabled) { 1349 if (!server_enabled) {
1342 return; 1350 return;
1343 } 1351 }
1352 defer_start = false;
1344 1353
1345 LOG_INFO(Debug_GDBStub, "Stopping GDB ..."); 1354 LOG_INFO(Debug_GDBStub, "Stopping GDB ...");
1346 if (gdbserver_socket != -1) { 1355 if (gdbserver_socket != -1) {
diff --git a/src/core/gdbstub/gdbstub.h b/src/core/gdbstub/gdbstub.h
index 5a36524b2..8fe3c320b 100644
--- a/src/core/gdbstub/gdbstub.h
+++ b/src/core/gdbstub/gdbstub.h
@@ -43,6 +43,13 @@ void ToggleServer(bool status);
43/// Start the gdbstub server. 43/// Start the gdbstub server.
44void Init(); 44void Init();
45 45
46/**
47 * Defer initialization of the gdbstub to the first packet processing functions.
48 * This avoids a case where the gdbstub thread is frozen after initialization
49 * and fails to respond in time to packets.
50 */
51void DeferStart();
52
46/// Stop gdbstub server. 53/// Stop gdbstub server.
47void Shutdown(); 54void Shutdown();
48 55
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index d1bf13c89..557608e76 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -52,6 +52,11 @@ enum class LaunchParameterKind : u32 {
52 AccountPreselectedUser = 2, 52 AccountPreselectedUser = 2,
53}; 53};
54 54
55enum class VrMode : u8 {
56 Disabled = 0,
57 Enabled = 1,
58};
59
55constexpr u32 LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC = 0xC79497CA; 60constexpr u32 LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC = 0xC79497CA;
56 61
57struct LaunchParameterAccountPreselectedUser { 62struct LaunchParameterAccountPreselectedUser {
@@ -605,11 +610,11 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system,
605 {30, nullptr, "GetHomeButtonReaderLockAccessor"}, 610 {30, nullptr, "GetHomeButtonReaderLockAccessor"},
606 {31, nullptr, "GetReaderLockAccessorEx"}, 611 {31, nullptr, "GetReaderLockAccessorEx"},
607 {40, nullptr, "GetCradleFwVersion"}, 612 {40, nullptr, "GetCradleFwVersion"},
608 {50, nullptr, "IsVrModeEnabled"}, 613 {50, &ICommonStateGetter::IsVrModeEnabled, "IsVrModeEnabled"},
609 {51, nullptr, "SetVrModeEnabled"}, 614 {51, &ICommonStateGetter::SetVrModeEnabled, "SetVrModeEnabled"},
610 {52, &ICommonStateGetter::SetLcdBacklighOffEnabled, "SetLcdBacklighOffEnabled"}, 615 {52, &ICommonStateGetter::SetLcdBacklighOffEnabled, "SetLcdBacklighOffEnabled"},
611 {53, nullptr, "BeginVrModeEx"}, 616 {53, nullptr, "BeginVrModeEx"},
612 {54, nullptr, "EndVrModeEx"}, 617 {54, &ICommonStateGetter::EndVrModeEx, "EndVrModeEx"},
613 {55, nullptr, "IsInControllerFirmwareUpdateSection"}, 618 {55, nullptr, "IsInControllerFirmwareUpdateSection"},
614 {60, &ICommonStateGetter::GetDefaultDisplayResolution, "GetDefaultDisplayResolution"}, 619 {60, &ICommonStateGetter::GetDefaultDisplayResolution, "GetDefaultDisplayResolution"},
615 {61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent, "GetDefaultDisplayResolutionChangeEvent"}, 620 {61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent, "GetDefaultDisplayResolutionChangeEvent"},
@@ -672,6 +677,30 @@ void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) {
672 rb.Push(static_cast<u8>(FocusState::InFocus)); 677 rb.Push(static_cast<u8>(FocusState::InFocus));
673} 678}
674 679
680void ICommonStateGetter::IsVrModeEnabled(Kernel::HLERequestContext& ctx) {
681 LOG_WARNING(Service_AM, "(STUBBED) called");
682
683 IPC::ResponseBuilder rb{ctx, 3};
684 rb.Push(RESULT_SUCCESS);
685 rb.PushEnum(VrMode::Disabled);
686}
687
688void ICommonStateGetter::SetVrModeEnabled(Kernel::HLERequestContext& ctx) {
689 IPC::RequestParser rp{ctx};
690 const auto is_vr_mode_enabled = rp.Pop<bool>();
691
692 LOG_WARNING(Service_AM, "(STUBBED) called. is_vr_mode_enabled={}", is_vr_mode_enabled);
693
694 IPC::ResponseBuilder rb{ctx, 2};
695 if (!is_vr_mode_enabled) {
696 rb.Push(RESULT_SUCCESS);
697 } else {
698 // TODO: Find better error code for this
699 UNIMPLEMENTED_MSG("is_vr_mode_enabled={}", is_vr_mode_enabled);
700 rb.Push(RESULT_UNKNOWN);
701 }
702}
703
675void ICommonStateGetter::SetLcdBacklighOffEnabled(Kernel::HLERequestContext& ctx) { 704void ICommonStateGetter::SetLcdBacklighOffEnabled(Kernel::HLERequestContext& ctx) {
676 IPC::RequestParser rp{ctx}; 705 IPC::RequestParser rp{ctx};
677 const auto is_lcd_backlight_off_enabled = rp.Pop<bool>(); 706 const auto is_lcd_backlight_off_enabled = rp.Pop<bool>();
@@ -683,6 +712,13 @@ void ICommonStateGetter::SetLcdBacklighOffEnabled(Kernel::HLERequestContext& ctx
683 rb.Push(RESULT_SUCCESS); 712 rb.Push(RESULT_SUCCESS);
684} 713}
685 714
715void ICommonStateGetter::EndVrModeEx(Kernel::HLERequestContext& ctx) {
716 LOG_WARNING(Service_AM, "(STUBBED) called");
717
718 IPC::ResponseBuilder rb{ctx, 2};
719 rb.Push(RESULT_SUCCESS);
720}
721
686void ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(Kernel::HLERequestContext& ctx) { 722void ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(Kernel::HLERequestContext& ctx) {
687 LOG_DEBUG(Service_AM, "called"); 723 LOG_DEBUG(Service_AM, "called");
688 724
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index 0843de781..53cfce10f 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -182,7 +182,10 @@ private:
182 void GetOperationMode(Kernel::HLERequestContext& ctx); 182 void GetOperationMode(Kernel::HLERequestContext& ctx);
183 void GetPerformanceMode(Kernel::HLERequestContext& ctx); 183 void GetPerformanceMode(Kernel::HLERequestContext& ctx);
184 void GetBootMode(Kernel::HLERequestContext& ctx); 184 void GetBootMode(Kernel::HLERequestContext& ctx);
185 void IsVrModeEnabled(Kernel::HLERequestContext& ctx);
186 void SetVrModeEnabled(Kernel::HLERequestContext& ctx);
185 void SetLcdBacklighOffEnabled(Kernel::HLERequestContext& ctx); 187 void SetLcdBacklighOffEnabled(Kernel::HLERequestContext& ctx);
188 void EndVrModeEx(Kernel::HLERequestContext& ctx);
186 void GetDefaultDisplayResolution(Kernel::HLERequestContext& ctx); 189 void GetDefaultDisplayResolution(Kernel::HLERequestContext& ctx);
187 void SetCpuBoostMode(Kernel::HLERequestContext& ctx); 190 void SetCpuBoostMode(Kernel::HLERequestContext& ctx);
188 191
diff --git a/src/core/hle/service/am/applets/web_browser.cpp b/src/core/hle/service/am/applets/web_browser.cpp
index 12443c910..9f30e167d 100644
--- a/src/core/hle/service/am/applets/web_browser.cpp
+++ b/src/core/hle/service/am/applets/web_browser.cpp
@@ -254,6 +254,12 @@ void WebBrowser::Execute() {
254 254
255 if (status != RESULT_SUCCESS) { 255 if (status != RESULT_SUCCESS) {
256 complete = true; 256 complete = true;
257
258 // This is a workaround in order not to softlock yuzu when an error happens during the
259 // webapplet init. In order to avoid an svcBreak, the status is set to RESULT_SUCCESS
260 Finalize();
261 status = RESULT_SUCCESS;
262
257 return; 263 return;
258 } 264 }
259 265
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index e6b56a9f9..d6ed5f304 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -235,7 +235,7 @@ Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) {
235 {303, nullptr, "ActivateSevenSixAxisSensor"}, 235 {303, nullptr, "ActivateSevenSixAxisSensor"},
236 {304, nullptr, "StartSevenSixAxisSensor"}, 236 {304, nullptr, "StartSevenSixAxisSensor"},
237 {305, nullptr, "StopSevenSixAxisSensor"}, 237 {305, nullptr, "StopSevenSixAxisSensor"},
238 {306, nullptr, "InitializeSevenSixAxisSensor"}, 238 {306, &Hid::InitializeSevenSixAxisSensor, "InitializeSevenSixAxisSensor"},
239 {307, nullptr, "FinalizeSevenSixAxisSensor"}, 239 {307, nullptr, "FinalizeSevenSixAxisSensor"},
240 {308, nullptr, "SetSevenSixAxisSensorFusionStrength"}, 240 {308, nullptr, "SetSevenSixAxisSensorFusionStrength"},
241 {309, nullptr, "GetSevenSixAxisSensorFusionStrength"}, 241 {309, nullptr, "GetSevenSixAxisSensorFusionStrength"},
@@ -853,6 +853,13 @@ void Hid::SetPalmaBoostMode(Kernel::HLERequestContext& ctx) {
853 rb.Push(RESULT_SUCCESS); 853 rb.Push(RESULT_SUCCESS);
854} 854}
855 855
856void Hid::InitializeSevenSixAxisSensor(Kernel::HLERequestContext& ctx) {
857 LOG_WARNING(Service_HID, "(STUBBED) called");
858
859 IPC::ResponseBuilder rb{ctx, 2};
860 rb.Push(RESULT_SUCCESS);
861}
862
856class HidDbg final : public ServiceFramework<HidDbg> { 863class HidDbg final : public ServiceFramework<HidDbg> {
857public: 864public:
858 explicit HidDbg() : ServiceFramework{"hid:dbg"} { 865 explicit HidDbg() : ServiceFramework{"hid:dbg"} {
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index ad20f147c..039c38b58 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -128,6 +128,7 @@ private:
128 void StopSixAxisSensor(Kernel::HLERequestContext& ctx); 128 void StopSixAxisSensor(Kernel::HLERequestContext& ctx);
129 void SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx); 129 void SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx);
130 void SetPalmaBoostMode(Kernel::HLERequestContext& ctx); 130 void SetPalmaBoostMode(Kernel::HLERequestContext& ctx);
131 void InitializeSevenSixAxisSensor(Kernel::HLERequestContext& ctx);
131 132
132 std::shared_ptr<IAppletResource> applet_resource; 133 std::shared_ptr<IAppletResource> applet_resource;
133 Core::System& system; 134 Core::System& system;
diff --git a/src/core/hle/service/sm/controller.cpp b/src/core/hle/service/sm/controller.cpp
index c45b285f8..9cca84b31 100644
--- a/src/core/hle/service/sm/controller.cpp
+++ b/src/core/hle/service/sm/controller.cpp
@@ -44,7 +44,7 @@ void Controller::QueryPointerBufferSize(Kernel::HLERequestContext& ctx) {
44 44
45 IPC::ResponseBuilder rb{ctx, 3}; 45 IPC::ResponseBuilder rb{ctx, 3};
46 rb.Push(RESULT_SUCCESS); 46 rb.Push(RESULT_SUCCESS);
47 rb.Push<u16>(0x500); 47 rb.Push<u16>(0x1000);
48} 48}
49 49
50Controller::Controller() : ServiceFramework("IpcController") { 50Controller::Controller() : ServiceFramework("IpcController") {
diff --git a/src/video_core/engines/const_buffer_engine_interface.h b/src/video_core/engines/const_buffer_engine_interface.h
index 724ee0fd6..ebe139504 100644
--- a/src/video_core/engines/const_buffer_engine_interface.h
+++ b/src/video_core/engines/const_buffer_engine_interface.h
@@ -18,10 +18,14 @@ struct SamplerDescriptor {
18 union { 18 union {
19 u32 raw = 0; 19 u32 raw = 0;
20 BitField<0, 2, Tegra::Shader::TextureType> texture_type; 20 BitField<0, 2, Tegra::Shader::TextureType> texture_type;
21 BitField<2, 3, Tegra::Texture::ComponentType> component_type; 21 BitField<2, 3, Tegra::Texture::ComponentType> r_type;
22 BitField<5, 1, u32> is_array; 22 BitField<5, 1, u32> is_array;
23 BitField<6, 1, u32> is_buffer; 23 BitField<6, 1, u32> is_buffer;
24 BitField<7, 1, u32> is_shadow; 24 BitField<7, 1, u32> is_shadow;
25 BitField<8, 3, Tegra::Texture::ComponentType> g_type;
26 BitField<11, 3, Tegra::Texture::ComponentType> b_type;
27 BitField<14, 3, Tegra::Texture::ComponentType> a_type;
28 BitField<17, 7, Tegra::Texture::TextureFormat> format;
25 }; 29 };
26 30
27 bool operator==(const SamplerDescriptor& rhs) const noexcept { 31 bool operator==(const SamplerDescriptor& rhs) const noexcept {
@@ -36,9 +40,11 @@ struct SamplerDescriptor {
36 using Tegra::Shader::TextureType; 40 using Tegra::Shader::TextureType;
37 SamplerDescriptor result; 41 SamplerDescriptor result;
38 42
39 // This is going to be used to determine the shading language type. 43 result.format.Assign(tic.format.Value());
40 // Because of that we don't care about all component types on color textures. 44 result.r_type.Assign(tic.r_type.Value());
41 result.component_type.Assign(tic.r_type.Value()); 45 result.g_type.Assign(tic.g_type.Value());
46 result.b_type.Assign(tic.b_type.Value());
47 result.a_type.Assign(tic.a_type.Value());
42 48
43 switch (tic.texture_type.Value()) { 49 switch (tic.texture_type.Value()) {
44 case Tegra::Texture::TextureType::Texture1D: 50 case Tegra::Texture::TextureType::Texture1D:
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index ce536e29b..ba63b44b4 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -98,6 +98,8 @@ void Maxwell3D::InitializeRegisterDefaults() {
98 regs.framebuffer_srgb = 1; 98 regs.framebuffer_srgb = 1;
99 regs.front_face = Maxwell3D::Regs::FrontFace::ClockWise; 99 regs.front_face = Maxwell3D::Regs::FrontFace::ClockWise;
100 100
101 shadow_state = regs;
102
101 mme_inline[MAXWELL3D_REG_INDEX(draw.vertex_end_gl)] = true; 103 mme_inline[MAXWELL3D_REG_INDEX(draw.vertex_end_gl)] = true;
102 mme_inline[MAXWELL3D_REG_INDEX(draw.vertex_begin_gl)] = true; 104 mme_inline[MAXWELL3D_REG_INDEX(draw.vertex_begin_gl)] = true;
103 mme_inline[MAXWELL3D_REG_INDEX(vertex_buffer.count)] = true; 105 mme_inline[MAXWELL3D_REG_INDEX(vertex_buffer.count)] = true;
@@ -160,8 +162,17 @@ void Maxwell3D::CallMethod(const GPU::MethodCall& method_call) {
160 ASSERT_MSG(method < Regs::NUM_REGS, 162 ASSERT_MSG(method < Regs::NUM_REGS,
161 "Invalid Maxwell3D register, increase the size of the Regs structure"); 163 "Invalid Maxwell3D register, increase the size of the Regs structure");
162 164
163 if (regs.reg_array[method] != method_call.argument) { 165 u32 arg = method_call.argument;
164 regs.reg_array[method] = method_call.argument; 166 // Keep track of the register value in shadow_state when requested.
167 if (shadow_state.shadow_ram_control == Regs::ShadowRamControl::Track ||
168 shadow_state.shadow_ram_control == Regs::ShadowRamControl::TrackWithFilter) {
169 shadow_state.reg_array[method] = arg;
170 } else if (shadow_state.shadow_ram_control == Regs::ShadowRamControl::Replay) {
171 arg = shadow_state.reg_array[method];
172 }
173
174 if (regs.reg_array[method] != arg) {
175 regs.reg_array[method] = arg;
165 176
166 for (const auto& table : dirty.tables) { 177 for (const auto& table : dirty.tables) {
167 dirty.flags[table[method]] = true; 178 dirty.flags[table[method]] = true;
@@ -169,12 +180,16 @@ void Maxwell3D::CallMethod(const GPU::MethodCall& method_call) {
169 } 180 }
170 181
171 switch (method) { 182 switch (method) {
183 case MAXWELL3D_REG_INDEX(shadow_ram_control): {
184 shadow_state.shadow_ram_control = static_cast<Regs::ShadowRamControl>(method_call.argument);
185 break;
186 }
172 case MAXWELL3D_REG_INDEX(macros.data): { 187 case MAXWELL3D_REG_INDEX(macros.data): {
173 ProcessMacroUpload(method_call.argument); 188 ProcessMacroUpload(arg);
174 break; 189 break;
175 } 190 }
176 case MAXWELL3D_REG_INDEX(macros.bind): { 191 case MAXWELL3D_REG_INDEX(macros.bind): {
177 ProcessMacroBind(method_call.argument); 192 ProcessMacroBind(arg);
178 break; 193 break;
179 } 194 }
180 case MAXWELL3D_REG_INDEX(firmware[4]): { 195 case MAXWELL3D_REG_INDEX(firmware[4]): {
@@ -250,7 +265,7 @@ void Maxwell3D::CallMethod(const GPU::MethodCall& method_call) {
250 } 265 }
251 case MAXWELL3D_REG_INDEX(data_upload): { 266 case MAXWELL3D_REG_INDEX(data_upload): {
252 const bool is_last_call = method_call.IsLastCall(); 267 const bool is_last_call = method_call.IsLastCall();
253 upload_state.ProcessData(method_call.argument, is_last_call); 268 upload_state.ProcessData(arg, is_last_call);
254 if (is_last_call) { 269 if (is_last_call) {
255 OnMemoryWrite(); 270 OnMemoryWrite();
256 } 271 }
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index 8a9e9992e..d24c9f657 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -531,6 +531,17 @@ public:
531 Fill = 0x1b02, 531 Fill = 0x1b02,
532 }; 532 };
533 533
534 enum class ShadowRamControl : u32 {
535 // write value to shadow ram
536 Track = 0,
537 // write value to shadow ram ( with validation ??? )
538 TrackWithFilter = 1,
539 // only write to real hw register
540 Passthrough = 2,
541 // write value from shadow ram to real hw register
542 Replay = 3,
543 };
544
534 struct RenderTargetConfig { 545 struct RenderTargetConfig {
535 u32 address_high; 546 u32 address_high;
536 u32 address_low; 547 u32 address_low;
@@ -674,7 +685,9 @@ public:
674 u32 bind; 685 u32 bind;
675 } macros; 686 } macros;
676 687
677 INSERT_UNION_PADDING_WORDS(0x17); 688 ShadowRamControl shadow_ram_control;
689
690 INSERT_UNION_PADDING_WORDS(0x16);
678 691
679 Upload::Registers upload; 692 Upload::Registers upload;
680 struct { 693 struct {
@@ -1263,7 +1276,12 @@ public:
1263 }; 1276 };
1264 std::array<u32, NUM_REGS> reg_array; 1277 std::array<u32, NUM_REGS> reg_array;
1265 }; 1278 };
1266 } regs{}; 1279 };
1280
1281 Regs regs{};
1282
1283 /// Store temporary hw register values, used by some calls to restore state after a operation
1284 Regs shadow_state;
1267 1285
1268 static_assert(sizeof(Regs) == Regs::NUM_REGS * sizeof(u32), "Maxwell3D Regs has wrong size"); 1286 static_assert(sizeof(Regs) == Regs::NUM_REGS * sizeof(u32), "Maxwell3D Regs has wrong size");
1269 static_assert(std::is_trivially_copyable_v<Regs>, "Maxwell3D Regs must be trivially copyable"); 1287 static_assert(std::is_trivially_copyable_v<Regs>, "Maxwell3D Regs must be trivially copyable");
@@ -1458,6 +1476,7 @@ private:
1458 "Field " #field_name " has invalid position") 1476 "Field " #field_name " has invalid position")
1459 1477
1460ASSERT_REG_POSITION(macros, 0x45); 1478ASSERT_REG_POSITION(macros, 0x45);
1479ASSERT_REG_POSITION(shadow_ram_control, 0x49);
1461ASSERT_REG_POSITION(upload, 0x60); 1480ASSERT_REG_POSITION(upload, 0x60);
1462ASSERT_REG_POSITION(exec_upload, 0x6C); 1481ASSERT_REG_POSITION(exec_upload, 0x6C);
1463ASSERT_REG_POSITION(data_upload, 0x6D); 1482ASSERT_REG_POSITION(data_upload, 0x6D);
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index eba42deb4..49dc5abe0 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -82,6 +82,10 @@ union Attribute {
82 Position = 7, 82 Position = 7,
83 Attribute_0 = 8, 83 Attribute_0 = 8,
84 Attribute_31 = 39, 84 Attribute_31 = 39,
85 FrontColor = 40,
86 FrontSecondaryColor = 41,
87 BackColor = 42,
88 BackSecondaryColor = 43,
85 ClipDistances0123 = 44, 89 ClipDistances0123 = 44,
86 ClipDistances4567 = 45, 90 ClipDistances4567 = 45,
87 PointCoord = 46, 91 PointCoord = 46,
@@ -89,6 +93,8 @@ union Attribute {
89 // shader, and a tuple of (TessCoord.x, TessCoord.y, TessCoord.z, ~) when inside a Tess Eval 93 // shader, and a tuple of (TessCoord.x, TessCoord.y, TessCoord.z, ~) when inside a Tess Eval
90 // shader. 94 // shader.
91 TessCoordInstanceIDVertexID = 47, 95 TessCoordInstanceIDVertexID = 47,
96 TexCoord_0 = 48,
97 TexCoord_7 = 55,
92 // This attribute contains a tuple of (Unk, Unk, Unk, gl_FrontFacing) when inside a fragment 98 // This attribute contains a tuple of (Unk, Unk, Unk, gl_FrontFacing) when inside a fragment
93 // shader. It is unknown what the other values contain. 99 // shader. It is unknown what the other values contain.
94 FrontFacing = 63, 100 FrontFacing = 63,
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 063f41327..826eee7df 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -933,13 +933,15 @@ void RasterizerOpenGL::SyncViewport() {
933 } 933 }
934 flags[Dirty::Viewport0 + i] = false; 934 flags[Dirty::Viewport0 + i] = false;
935 935
936 const Common::Rectangle<f32> rect{regs.viewport_transform[i].GetRect()}; 936 const auto& src = regs.viewport_transform[i];
937 const Common::Rectangle<f32> rect{src.GetRect()};
937 glViewportIndexedf(static_cast<GLuint>(i), rect.left, rect.bottom, rect.GetWidth(), 938 glViewportIndexedf(static_cast<GLuint>(i), rect.left, rect.bottom, rect.GetWidth(),
938 rect.GetHeight()); 939 rect.GetHeight());
939 940
940 const auto& src = regs.viewports[i]; 941 const GLdouble reduce_z = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne;
941 glDepthRangeIndexed(static_cast<GLuint>(i), static_cast<GLdouble>(src.depth_range_near), 942 const GLdouble near_depth = src.translate_z - src.scale_z * reduce_z;
942 static_cast<GLdouble>(src.depth_range_far)); 943 const GLdouble far_depth = src.translate_z + src.scale_z;
944 glDepthRangeIndexed(static_cast<GLuint>(i), near_depth, far_depth);
943 } 945 }
944 } 946 }
945} 947}
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 2c38f57fd..8aa4a7ac9 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -366,10 +366,19 @@ constexpr bool IsGenericAttribute(Attribute::Index index) {
366 return index >= Attribute::Index::Attribute_0 && index <= Attribute::Index::Attribute_31; 366 return index >= Attribute::Index::Attribute_0 && index <= Attribute::Index::Attribute_31;
367} 367}
368 368
369constexpr bool IsLegacyTexCoord(Attribute::Index index) {
370 return static_cast<int>(index) >= static_cast<int>(Attribute::Index::TexCoord_0) &&
371 static_cast<int>(index) <= static_cast<int>(Attribute::Index::TexCoord_7);
372}
373
369constexpr Attribute::Index ToGenericAttribute(u64 value) { 374constexpr Attribute::Index ToGenericAttribute(u64 value) {
370 return static_cast<Attribute::Index>(value + static_cast<u64>(Attribute::Index::Attribute_0)); 375 return static_cast<Attribute::Index>(value + static_cast<u64>(Attribute::Index::Attribute_0));
371} 376}
372 377
378constexpr int GetLegacyTexCoordIndex(Attribute::Index index) {
379 return static_cast<int>(index) - static_cast<int>(Attribute::Index::TexCoord_0);
380}
381
373u32 GetGenericAttributeIndex(Attribute::Index index) { 382u32 GetGenericAttributeIndex(Attribute::Index index) {
374 ASSERT(IsGenericAttribute(index)); 383 ASSERT(IsGenericAttribute(index));
375 return static_cast<u32>(index) - static_cast<u32>(Attribute::Index::Attribute_0); 384 return static_cast<u32>(index) - static_cast<u32>(Attribute::Index::Attribute_0);
@@ -498,7 +507,7 @@ private:
498 if (!identifier.empty()) { 507 if (!identifier.empty()) {
499 code.AddLine("// {}", identifier); 508 code.AddLine("// {}", identifier);
500 } 509 }
501 code.AddLine("#version 440 core"); 510 code.AddLine("#version 440 {}", ir.UsesLegacyVaryings() ? "compatibility" : "core");
502 code.AddLine("#extension GL_ARB_separate_shader_objects : enable"); 511 code.AddLine("#extension GL_ARB_separate_shader_objects : enable");
503 if (device.HasShaderBallot()) { 512 if (device.HasShaderBallot()) {
504 code.AddLine("#extension GL_ARB_shader_ballot : require"); 513 code.AddLine("#extension GL_ARB_shader_ballot : require");
@@ -561,6 +570,16 @@ private:
561 if (stage != ShaderType::Fragment) { 570 if (stage != ShaderType::Fragment) {
562 return; 571 return;
563 } 572 }
573 if (ir.UsesLegacyVaryings()) {
574 code.AddLine("in gl_PerFragment {{");
575 ++code.scope;
576 code.AddLine("vec4 gl_TexCoord[8];");
577 code.AddLine("vec4 gl_Color;");
578 code.AddLine("vec4 gl_SecondaryColor;");
579 --code.scope;
580 code.AddLine("}};");
581 }
582
564 for (u32 rt = 0; rt < Maxwell::NumRenderTargets; ++rt) { 583 for (u32 rt = 0; rt < Maxwell::NumRenderTargets; ++rt) {
565 code.AddLine("layout (location = {}) out vec4 frag_color{};", rt, rt); 584 code.AddLine("layout (location = {}) out vec4 frag_color{};", rt, rt);
566 } 585 }
@@ -617,12 +636,12 @@ private:
617 code.AddLine("float gl_PointSize;"); 636 code.AddLine("float gl_PointSize;");
618 } 637 }
619 638
620 if (ir.UsesInstanceId()) { 639 if (ir.UsesLegacyVaryings()) {
621 code.AddLine("int gl_InstanceID;"); 640 code.AddLine("vec4 gl_TexCoord[8];");
622 } 641 code.AddLine("vec4 gl_FrontColor;");
623 642 code.AddLine("vec4 gl_FrontSecondaryColor;");
624 if (ir.UsesVertexId()) { 643 code.AddLine("vec4 gl_BackColor;");
625 code.AddLine("int gl_VertexID;"); 644 code.AddLine("vec4 gl_BackSecondaryColor;");
626 } 645 }
627 646
628 --code.scope; 647 --code.scope;
@@ -1128,6 +1147,10 @@ private:
1128 default: 1147 default:
1129 UNREACHABLE(); 1148 UNREACHABLE();
1130 } 1149 }
1150 case Attribute::Index::FrontColor:
1151 return {"gl_Color"s + GetSwizzle(element), Type::Float};
1152 case Attribute::Index::FrontSecondaryColor:
1153 return {"gl_SecondaryColor"s + GetSwizzle(element), Type::Float};
1131 case Attribute::Index::PointCoord: 1154 case Attribute::Index::PointCoord:
1132 switch (element) { 1155 switch (element) {
1133 case 0: 1156 case 0:
@@ -1168,6 +1191,12 @@ private:
1168 return {GeometryPass(GetGenericInputAttribute(attribute)) + GetSwizzle(element), 1191 return {GeometryPass(GetGenericInputAttribute(attribute)) + GetSwizzle(element),
1169 Type::Float}; 1192 Type::Float};
1170 } 1193 }
1194 if (IsLegacyTexCoord(attribute)) {
1195 UNIMPLEMENTED_IF(stage == ShaderType::Geometry);
1196 return {fmt::format("gl_TexCoord[{}]{}", GetLegacyTexCoordIndex(attribute),
1197 GetSwizzle(element)),
1198 Type::Float};
1199 }
1171 break; 1200 break;
1172 } 1201 }
1173 UNIMPLEMENTED_MSG("Unhandled input attribute: {}", static_cast<u32>(attribute)); 1202 UNIMPLEMENTED_MSG("Unhandled input attribute: {}", static_cast<u32>(attribute));
@@ -1206,11 +1235,12 @@ private:
1206 } 1235 }
1207 1236
1208 std::optional<Expression> GetOutputAttribute(const AbufNode* abuf) { 1237 std::optional<Expression> GetOutputAttribute(const AbufNode* abuf) {
1238 const u32 element = abuf->GetElement();
1209 switch (const auto attribute = abuf->GetIndex()) { 1239 switch (const auto attribute = abuf->GetIndex()) {
1210 case Attribute::Index::Position: 1240 case Attribute::Index::Position:
1211 return {{"gl_Position"s + GetSwizzle(abuf->GetElement()), Type::Float}}; 1241 return {{"gl_Position"s + GetSwizzle(element), Type::Float}};
1212 case Attribute::Index::LayerViewportPointSize: 1242 case Attribute::Index::LayerViewportPointSize:
1213 switch (abuf->GetElement()) { 1243 switch (element) {
1214 case 0: 1244 case 0:
1215 UNIMPLEMENTED(); 1245 UNIMPLEMENTED();
1216 return {}; 1246 return {};
@@ -1228,13 +1258,26 @@ private:
1228 return {{"gl_PointSize", Type::Float}}; 1258 return {{"gl_PointSize", Type::Float}};
1229 } 1259 }
1230 return {}; 1260 return {};
1261 case Attribute::Index::FrontColor:
1262 return {{"gl_FrontColor"s + GetSwizzle(element), Type::Float}};
1263 case Attribute::Index::FrontSecondaryColor:
1264 return {{"gl_FrontSecondaryColor"s + GetSwizzle(element), Type::Float}};
1265 case Attribute::Index::BackColor:
1266 return {{"gl_BackColor"s + GetSwizzle(element), Type::Float}};
1267 case Attribute::Index::BackSecondaryColor:
1268 return {{"gl_BackSecondaryColor"s + GetSwizzle(element), Type::Float}};
1231 case Attribute::Index::ClipDistances0123: 1269 case Attribute::Index::ClipDistances0123:
1232 return {{fmt::format("gl_ClipDistance[{}]", abuf->GetElement()), Type::Float}}; 1270 return {{fmt::format("gl_ClipDistance[{}]", element), Type::Float}};
1233 case Attribute::Index::ClipDistances4567: 1271 case Attribute::Index::ClipDistances4567:
1234 return {{fmt::format("gl_ClipDistance[{}]", abuf->GetElement() + 4), Type::Float}}; 1272 return {{fmt::format("gl_ClipDistance[{}]", element + 4), Type::Float}};
1235 default: 1273 default:
1236 if (IsGenericAttribute(attribute)) { 1274 if (IsGenericAttribute(attribute)) {
1237 return {{GetGenericOutputAttribute(attribute, abuf->GetElement()), Type::Float}}; 1275 return {{GetGenericOutputAttribute(attribute, element), Type::Float}};
1276 }
1277 if (IsLegacyTexCoord(attribute)) {
1278 return {{fmt::format("gl_TexCoord[{}]{}", GetLegacyTexCoordIndex(attribute),
1279 GetSwizzle(element)),
1280 Type::Float}};
1238 } 1281 }
1239 UNIMPLEMENTED_MSG("Unhandled output attribute: {}", static_cast<u32>(attribute)); 1282 UNIMPLEMENTED_MSG("Unhandled output attribute: {}", static_cast<u32>(attribute));
1240 return {}; 1283 return {};
diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
index f93447610..7480cb7c3 100644
--- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
+++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
@@ -401,6 +401,26 @@ vk::Format VertexFormat(Maxwell::VertexAttribute::Type type, Maxwell::VertexAttr
401 } 401 }
402 break; 402 break;
403 case Maxwell::VertexAttribute::Type::SignedScaled: 403 case Maxwell::VertexAttribute::Type::SignedScaled:
404 switch (size) {
405 case Maxwell::VertexAttribute::Size::Size_8:
406 return vk::Format::eR8Sscaled;
407 case Maxwell::VertexAttribute::Size::Size_8_8:
408 return vk::Format::eR8G8Sscaled;
409 case Maxwell::VertexAttribute::Size::Size_8_8_8:
410 return vk::Format::eR8G8B8Sscaled;
411 case Maxwell::VertexAttribute::Size::Size_8_8_8_8:
412 return vk::Format::eR8G8B8A8Sscaled;
413 case Maxwell::VertexAttribute::Size::Size_16:
414 return vk::Format::eR16Sscaled;
415 case Maxwell::VertexAttribute::Size::Size_16_16:
416 return vk::Format::eR16G16Sscaled;
417 case Maxwell::VertexAttribute::Size::Size_16_16_16:
418 return vk::Format::eR16G16B16Sscaled;
419 case Maxwell::VertexAttribute::Size::Size_16_16_16_16:
420 return vk::Format::eR16G16B16A16Sscaled;
421 default:
422 break;
423 }
404 break; 424 break;
405 case Maxwell::VertexAttribute::Type::Float: 425 case Maxwell::VertexAttribute::Type::Float:
406 switch (size) { 426 switch (size) {
diff --git a/src/video_core/shader/decode/xmad.cpp b/src/video_core/shader/decode/xmad.cpp
index fbd7e9a17..6191ffba1 100644
--- a/src/video_core/shader/decode/xmad.cpp
+++ b/src/video_core/shader/decode/xmad.cpp
@@ -31,7 +31,7 @@ u32 ShaderIR::DecodeXmad(NodeBlock& bb, u32 pc) {
31 const bool is_signed_b = instr.xmad.sign_b == 1; 31 const bool is_signed_b = instr.xmad.sign_b == 1;
32 const bool is_signed_c = is_signed_a; 32 const bool is_signed_c = is_signed_a;
33 33
34 auto [is_merge, is_psl, is_high_b, mode, op_b, 34 auto [is_merge, is_psl, is_high_b, mode, op_b_binding,
35 op_c] = [&]() -> std::tuple<bool, bool, bool, Tegra::Shader::XmadMode, Node, Node> { 35 op_c] = [&]() -> std::tuple<bool, bool, bool, Tegra::Shader::XmadMode, Node, Node> {
36 switch (opcode->get().GetId()) { 36 switch (opcode->get().GetId()) {
37 case OpCode::Id::XMAD_CR: 37 case OpCode::Id::XMAD_CR:
@@ -67,9 +67,10 @@ u32 ShaderIR::DecodeXmad(NodeBlock& bb, u32 pc) {
67 op_a = SignedOperation(OperationCode::IBitfieldExtract, is_signed_a, std::move(op_a), 67 op_a = SignedOperation(OperationCode::IBitfieldExtract, is_signed_a, std::move(op_a),
68 instr.xmad.high_a ? Immediate(16) : Immediate(0), Immediate(16)); 68 instr.xmad.high_a ? Immediate(16) : Immediate(0), Immediate(16));
69 69
70 const Node original_b = op_b; 70 const Node original_b = op_b_binding;
71 op_b = SignedOperation(OperationCode::IBitfieldExtract, is_signed_b, std::move(op_b), 71 const Node op_b =
72 is_high_b ? Immediate(16) : Immediate(0), Immediate(16)); 72 SignedOperation(OperationCode::IBitfieldExtract, is_signed_b, std::move(op_b_binding),
73 is_high_b ? Immediate(16) : Immediate(0), Immediate(16));
73 74
74 // we already check sign_a and sign_b is difference or not before so just use one in here. 75 // we already check sign_a and sign_b is difference or not before so just use one in here.
75 Node product = SignedOperation(OperationCode::IMul, is_signed_a, op_a, op_b); 76 Node product = SignedOperation(OperationCode::IMul, is_signed_a, op_a, op_b);
diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp
index 425927777..baf7188d2 100644
--- a/src/video_core/shader/shader_ir.cpp
+++ b/src/video_core/shader/shader_ir.cpp
@@ -96,6 +96,7 @@ Node ShaderIR::GetPredicate(bool immediate) {
96} 96}
97 97
98Node ShaderIR::GetInputAttribute(Attribute::Index index, u64 element, Node buffer) { 98Node ShaderIR::GetInputAttribute(Attribute::Index index, u64 element, Node buffer) {
99 MarkAttributeUsage(index, element);
99 used_input_attributes.emplace(index); 100 used_input_attributes.emplace(index);
100 return MakeNode<AbufNode>(index, static_cast<u32>(element), std::move(buffer)); 101 return MakeNode<AbufNode>(index, static_cast<u32>(element), std::move(buffer));
101} 102}
@@ -106,42 +107,8 @@ Node ShaderIR::GetPhysicalInputAttribute(Tegra::Shader::Register physical_addres
106} 107}
107 108
108Node ShaderIR::GetOutputAttribute(Attribute::Index index, u64 element, Node buffer) { 109Node ShaderIR::GetOutputAttribute(Attribute::Index index, u64 element, Node buffer) {
109 if (index == Attribute::Index::LayerViewportPointSize) { 110 MarkAttributeUsage(index, element);
110 switch (element) {
111 case 0:
112 UNIMPLEMENTED();
113 break;
114 case 1:
115 uses_layer = true;
116 break;
117 case 2:
118 uses_viewport_index = true;
119 break;
120 case 3:
121 uses_point_size = true;
122 break;
123 }
124 }
125 if (index == Attribute::Index::TessCoordInstanceIDVertexID) {
126 switch (element) {
127 case 2:
128 uses_instance_id = true;
129 break;
130 case 3:
131 uses_vertex_id = true;
132 break;
133 default:
134 break;
135 }
136 }
137 if (index == Attribute::Index::ClipDistances0123 ||
138 index == Attribute::Index::ClipDistances4567) {
139 const auto clip_index =
140 static_cast<u32>((index == Attribute::Index::ClipDistances4567 ? 1 : 0) + element);
141 used_clip_distances.at(clip_index) = true;
142 }
143 used_output_attributes.insert(index); 111 used_output_attributes.insert(index);
144
145 return MakeNode<AbufNode>(index, static_cast<u32>(element), std::move(buffer)); 112 return MakeNode<AbufNode>(index, static_cast<u32>(element), std::move(buffer));
146} 113}
147 114
@@ -452,6 +419,54 @@ Node ShaderIR::BitfieldInsert(Node base, Node insert, u32 offset, u32 bits) {
452 Immediate(bits)); 419 Immediate(bits));
453} 420}
454 421
422void ShaderIR::MarkAttributeUsage(Attribute::Index index, u64 element) {
423 switch (index) {
424 case Attribute::Index::LayerViewportPointSize:
425 switch (element) {
426 case 0:
427 UNIMPLEMENTED();
428 break;
429 case 1:
430 uses_layer = true;
431 break;
432 case 2:
433 uses_viewport_index = true;
434 break;
435 case 3:
436 uses_point_size = true;
437 break;
438 }
439 break;
440 case Attribute::Index::TessCoordInstanceIDVertexID:
441 switch (element) {
442 case 2:
443 uses_instance_id = true;
444 break;
445 case 3:
446 uses_vertex_id = true;
447 break;
448 }
449 break;
450 case Attribute::Index::ClipDistances0123:
451 case Attribute::Index::ClipDistances4567: {
452 const u64 clip_index = (index == Attribute::Index::ClipDistances4567 ? 4 : 0) + element;
453 used_clip_distances.at(clip_index) = true;
454 break;
455 }
456 case Attribute::Index::FrontColor:
457 case Attribute::Index::FrontSecondaryColor:
458 case Attribute::Index::BackColor:
459 case Attribute::Index::BackSecondaryColor:
460 uses_legacy_varyings = true;
461 break;
462 default:
463 if (index >= Attribute::Index::TexCoord_0 && index <= Attribute::Index::TexCoord_7) {
464 uses_legacy_varyings = true;
465 }
466 break;
467 }
468}
469
455std::size_t ShaderIR::DeclareAmend(Node new_amend) { 470std::size_t ShaderIR::DeclareAmend(Node new_amend) {
456 const std::size_t id = amend_code.size(); 471 const std::size_t id = amend_code.size();
457 amend_code.push_back(new_amend); 472 amend_code.push_back(new_amend);
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h
index dde036b40..80fc9b82c 100644
--- a/src/video_core/shader/shader_ir.h
+++ b/src/video_core/shader/shader_ir.h
@@ -137,6 +137,10 @@ public:
137 return uses_vertex_id; 137 return uses_vertex_id;
138 } 138 }
139 139
140 bool UsesLegacyVaryings() const {
141 return uses_legacy_varyings;
142 }
143
140 bool UsesWarps() const { 144 bool UsesWarps() const {
141 return uses_warps; 145 return uses_warps;
142 } 146 }
@@ -343,6 +347,9 @@ private:
343 /// Inserts a sequence of bits from a node 347 /// Inserts a sequence of bits from a node
344 Node BitfieldInsert(Node base, Node insert, u32 offset, u32 bits); 348 Node BitfieldInsert(Node base, Node insert, u32 offset, u32 bits);
345 349
350 /// Marks the usage of a input or output attribute.
351 void MarkAttributeUsage(Tegra::Shader::Attribute::Index index, u64 element);
352
346 void WriteTexInstructionFloat(NodeBlock& bb, Tegra::Shader::Instruction instr, 353 void WriteTexInstructionFloat(NodeBlock& bb, Tegra::Shader::Instruction instr,
347 const Node4& components); 354 const Node4& components);
348 355
@@ -443,6 +450,7 @@ private:
443 bool uses_physical_attributes{}; // Shader uses AL2P or physical attribute read/writes 450 bool uses_physical_attributes{}; // Shader uses AL2P or physical attribute read/writes
444 bool uses_instance_id{}; 451 bool uses_instance_id{};
445 bool uses_vertex_id{}; 452 bool uses_vertex_id{};
453 bool uses_legacy_varyings{};
446 bool uses_warps{}; 454 bool uses_warps{};
447 bool uses_indexed_samplers{}; 455 bool uses_indexed_samplers{};
448 456
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 47615adfe..d7e59d0cd 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -1034,6 +1034,14 @@ void GMainWindow::BootGame(const QString& filename) {
1034} 1034}
1035 1035
1036void GMainWindow::ShutdownGame() { 1036void GMainWindow::ShutdownGame() {
1037 if (!emulation_running) {
1038 return;
1039 }
1040
1041 if (ui.action_Fullscreen->isChecked()) {
1042 HideFullscreen();
1043 }
1044
1037 AllowOSSleep(); 1045 AllowOSSleep();
1038 1046
1039 discord_rpc->Pause(); 1047 discord_rpc->Pause();
@@ -1716,11 +1724,6 @@ void GMainWindow::OnStartGame() {
1716} 1724}
1717 1725
1718void GMainWindow::OnPauseGame() { 1726void GMainWindow::OnPauseGame() {
1719 Core::System& system{Core::System::GetInstance()};
1720 if (system.GetExitLock() && !ConfirmForceLockedExit()) {
1721 return;
1722 }
1723
1724 emu_thread->SetRunning(false); 1727 emu_thread->SetRunning(false);
1725 1728
1726 ui.action_Start->setEnabled(true); 1729 ui.action_Start->setEnabled(true);
@@ -1803,7 +1806,7 @@ void GMainWindow::ToggleWindowMode() {
1803 // Render in the main window... 1806 // Render in the main window...
1804 render_window->BackupGeometry(); 1807 render_window->BackupGeometry();
1805 ui.horizontalLayout->addWidget(render_window); 1808 ui.horizontalLayout->addWidget(render_window);
1806 render_window->setFocusPolicy(Qt::ClickFocus); 1809 render_window->setFocusPolicy(Qt::StrongFocus);
1807 if (emulation_running) { 1810 if (emulation_running) {
1808 render_window->setVisible(true); 1811 render_window->setVisible(true);
1809 render_window->setFocus(); 1812 render_window->setFocus();