summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/CMakeLists.txt13
-rw-r--r--src/common/bit_field.h11
-rw-r--r--src/common/common_funcs.h22
-rw-r--r--src/core/file_sys/content_archive.cpp39
-rw-r--r--src/core/file_sys/romfs.h19
-rw-r--r--src/core/hle/ipc.h6
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp3
-rw-r--r--src/core/hle/kernel/object.h5
-rw-r--r--src/core/hle/kernel/readable_event.cpp10
-rw-r--r--src/core/hle/kernel/readable_event.h7
-rw-r--r--src/core/hle/kernel/svc.cpp2
-rw-r--r--src/core/hle/kernel/writable_event.cpp8
-rw-r--r--src/core/hle/kernel/writable_event.h6
-rw-r--r--src/core/hle/service/am/am.cpp47
-rw-r--r--src/core/hle/service/am/am.h3
-rw-r--r--src/core/hle/service/am/applets/applets.cpp10
-rw-r--r--src/core/hle/service/am/applets/error.cpp11
-rw-r--r--src/core/hle/service/aoc/aoc_u.cpp4
-rw-r--r--src/core/hle/service/audio/audout_u.cpp4
-rw-r--r--src/core/hle/service/audio/audren_u.cpp12
-rw-r--r--src/core/hle/service/bcat/backend/backend.cpp3
-rw-r--r--src/core/hle/service/btdrv/btdrv.cpp3
-rw-r--r--src/core/hle/service/btm/btm.cpp14
-rw-r--r--src/core/hle/service/friend/friend.cpp2
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp2
-rw-r--r--src/core/hle/service/hid/hid.cpp204
-rw-r--r--src/core/hle/service/hid/hid.h14
-rw-r--r--src/core/hle/service/nfp/nfp.cpp10
-rw-r--r--src/core/hle/service/nifm/nifm.cpp6
-rw-r--r--src/core/hle/service/nim/nim.cpp3
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.cpp3
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.cpp3
-rw-r--r--src/core/hle/service/vi/display/vi_display.cpp4
-rw-r--r--src/core/hle/service/vi/vi.cpp2
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h18
-rw-r--r--src/video_core/engines/fermi_2d.cpp30
-rw-r--r--src/video_core/engines/fermi_2d.h12
-rw-r--r--src/video_core/engines/kepler_compute.h18
-rw-r--r--src/video_core/engines/kepler_memory.h4
-rw-r--r--src/video_core/engines/maxwell_3d.h116
-rw-r--r--src/video_core/engines/maxwell_dma.h10
-rw-r--r--src/video_core/engines/shader_header.h50
-rw-r--r--src/video_core/gpu.h8
-rw-r--r--src/video_core/renderer_opengl/gl_buffer_cache.cpp31
-rw-r--r--src/video_core/renderer_opengl/gl_buffer_cache.h20
-rw-r--r--src/video_core/renderer_opengl/gl_device.cpp4
-rw-r--r--src/video_core/renderer_opengl/gl_device.h5
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp26
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp12
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.h3
-rw-r--r--src/video_core/shader/control_flow.cpp214
-rw-r--r--src/video_core/shader/decode/arithmetic.cpp11
-rw-r--r--src/video_core/shader/decode/arithmetic_half.cpp4
-rw-r--r--src/video_core/shader/decode/arithmetic_half_immediate.cpp8
-rw-r--r--src/video_core/shader/decode/ffma.cpp4
-rw-r--r--src/video_core/shader/decode/half_set.cpp4
-rw-r--r--src/video_core/shader/decode/half_set_predicate.cpp4
-rw-r--r--src/video_core/shader/decode/image.cpp50
-rw-r--r--src/video_core/shader/decode/texture.cpp101
-rw-r--r--src/video_core/shader/node.h101
-rw-r--r--src/video_core/shader/shader_ir.h14
-rw-r--r--src/video_core/textures/texture.h2
-rw-r--r--src/yuzu/debugger/wait_tree.cpp21
-rw-r--r--src/yuzu/debugger/wait_tree.h4
-rw-r--r--src/yuzu/main.cpp21
-rw-r--r--src/yuzu/main.h1
66 files changed, 749 insertions, 697 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 9c6f1c07c..9b0c3db68 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -3,17 +3,8 @@
3# could affect the result, but much more unlikely than the following files. Keeping a list of files 3# could affect the result, but much more unlikely than the following files. Keeping a list of files
4# like this allows for much better caching since it doesn't force the user to recompile binary shaders every update 4# like this allows for much better caching since it doesn't force the user to recompile binary shaders every update
5set(VIDEO_CORE "${CMAKE_SOURCE_DIR}/src/video_core") 5set(VIDEO_CORE "${CMAKE_SOURCE_DIR}/src/video_core")
6if (DEFINED ENV{CI}) 6if (DEFINED ENV{AZURECIREPO})
7 if (DEFINED ENV{TRAVIS}) 7 set(BUILD_REPOSITORY $ENV{AZURECIREPO})
8 set(BUILD_REPOSITORY $ENV{TRAVIS_REPO_SLUG})
9 set(BUILD_TAG $ENV{TRAVIS_TAG})
10 elseif(DEFINED ENV{APPVEYOR})
11 set(BUILD_REPOSITORY $ENV{APPVEYOR_REPO_NAME})
12 set(BUILD_TAG $ENV{APPVEYOR_REPO_TAG_NAME})
13 elseif(DEFINED ENV{AZURE})
14 set(BUILD_REPOSITORY $ENV{AZURE_REPO_NAME})
15 set(BUILD_TAG $ENV{AZURE_REPO_TAG})
16 endif()
17endif() 8endif()
18if (DEFINED ENV{TITLEBARFORMATIDLE}) 9if (DEFINED ENV{TITLEBARFORMATIDLE})
19 set(TITLE_BAR_FORMAT_IDLE $ENV{TITLEBARFORMATIDLE}) 10 set(TITLE_BAR_FORMAT_IDLE $ENV{TITLEBARFORMATIDLE})
diff --git a/src/common/bit_field.h b/src/common/bit_field.h
index 902e668e3..fd2bbbd99 100644
--- a/src/common/bit_field.h
+++ b/src/common/bit_field.h
@@ -36,6 +36,13 @@
36#include "common/common_funcs.h" 36#include "common/common_funcs.h"
37#include "common/swap.h" 37#include "common/swap.h"
38 38
39// Inlining
40#ifdef _WIN32
41#define FORCE_INLINE __forceinline
42#else
43#define FORCE_INLINE inline __attribute__((always_inline))
44#endif
45
39/* 46/*
40 * Abstract bitfield class 47 * Abstract bitfield class
41 * 48 *
@@ -168,11 +175,11 @@ public:
168 constexpr BitField(BitField&&) noexcept = default; 175 constexpr BitField(BitField&&) noexcept = default;
169 constexpr BitField& operator=(BitField&&) noexcept = default; 176 constexpr BitField& operator=(BitField&&) noexcept = default;
170 177
171 constexpr FORCE_INLINE operator T() const { 178 constexpr operator T() const {
172 return Value(); 179 return Value();
173 } 180 }
174 181
175 constexpr FORCE_INLINE void Assign(const T& value) { 182 constexpr void Assign(const T& value) {
176 storage = (static_cast<StorageType>(storage) & ~mask) | FormatValue(value); 183 storage = (static_cast<StorageType>(storage) & ~mask) | FormatValue(value);
177 } 184 }
178 185
diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h
index 04ecac959..c029dc7b3 100644
--- a/src/common/common_funcs.h
+++ b/src/common/common_funcs.h
@@ -1,10 +1,11 @@
1// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project 1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#pragma once 5#pragma once
6 6
7#include <algorithm> 7#include <algorithm>
8#include <array>
8#include <string> 9#include <string>
9 10
10#if !defined(ARCHITECTURE_x86_64) 11#if !defined(ARCHITECTURE_x86_64)
@@ -16,18 +17,15 @@
16#define CONCAT2(x, y) DO_CONCAT2(x, y) 17#define CONCAT2(x, y) DO_CONCAT2(x, y)
17#define DO_CONCAT2(x, y) x##y 18#define DO_CONCAT2(x, y) x##y
18 19
19// helper macro to properly align structure members. 20/// Helper macros to insert unused bytes or words to properly align structs. These values will be
20// Calling INSERT_PADDING_BYTES will add a new member variable with a name like "pad121", 21/// zero-initialized.
21// depending on the current source line to make sure variable names are unique. 22#define INSERT_PADDING_BYTES(num_bytes) std::array<u8, num_bytes> CONCAT2(pad, __LINE__){};
22#define INSERT_PADDING_BYTES(num_bytes) u8 CONCAT2(pad, __LINE__)[(num_bytes)] 23#define INSERT_PADDING_WORDS(num_words) std::array<u32, num_words> CONCAT2(pad, __LINE__){};
23#define INSERT_PADDING_WORDS(num_words) u32 CONCAT2(pad, __LINE__)[(num_words)]
24 24
25// Inlining 25/// These are similar to the INSERT_PADDING_* macros, but are needed for padding unions. This is
26#ifdef _WIN32 26/// because unions can only be initialized by one member.
27#define FORCE_INLINE __forceinline 27#define INSERT_UNION_PADDING_BYTES(num_bytes) std::array<u8, num_bytes> CONCAT2(pad, __LINE__);
28#else 28#define INSERT_UNION_PADDING_WORDS(num_words) std::array<u32, num_words> CONCAT2(pad, __LINE__);
29#define FORCE_INLINE inline __attribute__((always_inline))
30#endif
31 29
32#ifndef _MSC_VER 30#ifndef _MSC_VER
33 31
diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp
index ea5c92f61..b8bbdd1ef 100644
--- a/src/core/file_sys/content_archive.cpp
+++ b/src/core/file_sys/content_archive.cpp
@@ -32,11 +32,28 @@ enum class NCASectionFilesystemType : u8 {
32 ROMFS = 0x3, 32 ROMFS = 0x3,
33}; 33};
34 34
35struct IVFCLevel {
36 u64_le offset;
37 u64_le size;
38 u32_le block_size;
39 u32_le reserved;
40};
41static_assert(sizeof(IVFCLevel) == 0x18, "IVFCLevel has incorrect size.");
42
43struct IVFCHeader {
44 u32_le magic;
45 u32_le magic_number;
46 INSERT_UNION_PADDING_BYTES(8);
47 std::array<IVFCLevel, 6> levels;
48 INSERT_UNION_PADDING_BYTES(64);
49};
50static_assert(sizeof(IVFCHeader) == 0xE0, "IVFCHeader has incorrect size.");
51
35struct NCASectionHeaderBlock { 52struct NCASectionHeaderBlock {
36 INSERT_PADDING_BYTES(3); 53 INSERT_UNION_PADDING_BYTES(3);
37 NCASectionFilesystemType filesystem_type; 54 NCASectionFilesystemType filesystem_type;
38 NCASectionCryptoType crypto_type; 55 NCASectionCryptoType crypto_type;
39 INSERT_PADDING_BYTES(3); 56 INSERT_UNION_PADDING_BYTES(3);
40}; 57};
41static_assert(sizeof(NCASectionHeaderBlock) == 0x8, "NCASectionHeaderBlock has incorrect size."); 58static_assert(sizeof(NCASectionHeaderBlock) == 0x8, "NCASectionHeaderBlock has incorrect size.");
42 59
@@ -44,7 +61,7 @@ struct NCASectionRaw {
44 NCASectionHeaderBlock header; 61 NCASectionHeaderBlock header;
45 std::array<u8, 0x138> block_data; 62 std::array<u8, 0x138> block_data;
46 std::array<u8, 0x8> section_ctr; 63 std::array<u8, 0x8> section_ctr;
47 INSERT_PADDING_BYTES(0xB8); 64 INSERT_UNION_PADDING_BYTES(0xB8);
48}; 65};
49static_assert(sizeof(NCASectionRaw) == 0x200, "NCASectionRaw has incorrect size."); 66static_assert(sizeof(NCASectionRaw) == 0x200, "NCASectionRaw has incorrect size.");
50 67
@@ -52,19 +69,19 @@ struct PFS0Superblock {
52 NCASectionHeaderBlock header_block; 69 NCASectionHeaderBlock header_block;
53 std::array<u8, 0x20> hash; 70 std::array<u8, 0x20> hash;
54 u32_le size; 71 u32_le size;
55 INSERT_PADDING_BYTES(4); 72 INSERT_UNION_PADDING_BYTES(4);
56 u64_le hash_table_offset; 73 u64_le hash_table_offset;
57 u64_le hash_table_size; 74 u64_le hash_table_size;
58 u64_le pfs0_header_offset; 75 u64_le pfs0_header_offset;
59 u64_le pfs0_size; 76 u64_le pfs0_size;
60 INSERT_PADDING_BYTES(0x1B0); 77 INSERT_UNION_PADDING_BYTES(0x1B0);
61}; 78};
62static_assert(sizeof(PFS0Superblock) == 0x200, "PFS0Superblock has incorrect size."); 79static_assert(sizeof(PFS0Superblock) == 0x200, "PFS0Superblock has incorrect size.");
63 80
64struct RomFSSuperblock { 81struct RomFSSuperblock {
65 NCASectionHeaderBlock header_block; 82 NCASectionHeaderBlock header_block;
66 IVFCHeader ivfc; 83 IVFCHeader ivfc;
67 INSERT_PADDING_BYTES(0x118); 84 INSERT_UNION_PADDING_BYTES(0x118);
68}; 85};
69static_assert(sizeof(RomFSSuperblock) == 0x200, "RomFSSuperblock has incorrect size."); 86static_assert(sizeof(RomFSSuperblock) == 0x200, "RomFSSuperblock has incorrect size.");
70 87
@@ -72,24 +89,24 @@ struct BKTRHeader {
72 u64_le offset; 89 u64_le offset;
73 u64_le size; 90 u64_le size;
74 u32_le magic; 91 u32_le magic;
75 INSERT_PADDING_BYTES(0x4); 92 INSERT_UNION_PADDING_BYTES(0x4);
76 u32_le number_entries; 93 u32_le number_entries;
77 INSERT_PADDING_BYTES(0x4); 94 INSERT_UNION_PADDING_BYTES(0x4);
78}; 95};
79static_assert(sizeof(BKTRHeader) == 0x20, "BKTRHeader has incorrect size."); 96static_assert(sizeof(BKTRHeader) == 0x20, "BKTRHeader has incorrect size.");
80 97
81struct BKTRSuperblock { 98struct BKTRSuperblock {
82 NCASectionHeaderBlock header_block; 99 NCASectionHeaderBlock header_block;
83 IVFCHeader ivfc; 100 IVFCHeader ivfc;
84 INSERT_PADDING_BYTES(0x18); 101 INSERT_UNION_PADDING_BYTES(0x18);
85 BKTRHeader relocation; 102 BKTRHeader relocation;
86 BKTRHeader subsection; 103 BKTRHeader subsection;
87 INSERT_PADDING_BYTES(0xC0); 104 INSERT_UNION_PADDING_BYTES(0xC0);
88}; 105};
89static_assert(sizeof(BKTRSuperblock) == 0x200, "BKTRSuperblock has incorrect size."); 106static_assert(sizeof(BKTRSuperblock) == 0x200, "BKTRSuperblock has incorrect size.");
90 107
91union NCASectionHeader { 108union NCASectionHeader {
92 NCASectionRaw raw; 109 NCASectionRaw raw{};
93 PFS0Superblock pfs0; 110 PFS0Superblock pfs0;
94 RomFSSuperblock romfs; 111 RomFSSuperblock romfs;
95 BKTRSuperblock bktr; 112 BKTRSuperblock bktr;
diff --git a/src/core/file_sys/romfs.h b/src/core/file_sys/romfs.h
index 0f35639bc..1c89be8a4 100644
--- a/src/core/file_sys/romfs.h
+++ b/src/core/file_sys/romfs.h
@@ -13,25 +13,6 @@
13 13
14namespace FileSys { 14namespace FileSys {
15 15
16struct RomFSHeader;
17
18struct IVFCLevel {
19 u64_le offset;
20 u64_le size;
21 u32_le block_size;
22 u32_le reserved;
23};
24static_assert(sizeof(IVFCLevel) == 0x18, "IVFCLevel has incorrect size.");
25
26struct IVFCHeader {
27 u32_le magic;
28 u32_le magic_number;
29 INSERT_PADDING_BYTES(8);
30 std::array<IVFCLevel, 6> levels;
31 INSERT_PADDING_BYTES(64);
32};
33static_assert(sizeof(IVFCHeader) == 0xE0, "IVFCHeader has incorrect size.");
34
35enum class RomFSExtractionType { 16enum class RomFSExtractionType {
36 Full, // Includes data directory 17 Full, // Includes data directory
37 Truncated, // Traverses into data directory 18 Truncated, // Traverses into data directory
diff --git a/src/core/hle/ipc.h b/src/core/hle/ipc.h
index fae54bcc7..7ce313190 100644
--- a/src/core/hle/ipc.h
+++ b/src/core/hle/ipc.h
@@ -160,7 +160,7 @@ struct DomainMessageHeader {
160 // Used when responding to an IPC request, Server -> Client. 160 // Used when responding to an IPC request, Server -> Client.
161 struct { 161 struct {
162 u32_le num_objects; 162 u32_le num_objects;
163 INSERT_PADDING_WORDS(3); 163 INSERT_UNION_PADDING_WORDS(3);
164 }; 164 };
165 165
166 // Used when performing an IPC request, Client -> Server. 166 // Used when performing an IPC request, Client -> Server.
@@ -171,8 +171,10 @@ struct DomainMessageHeader {
171 BitField<16, 16, u32> size; 171 BitField<16, 16, u32> size;
172 }; 172 };
173 u32_le object_id; 173 u32_le object_id;
174 INSERT_PADDING_WORDS(2); 174 INSERT_UNION_PADDING_WORDS(2);
175 }; 175 };
176
177 std::array<u32, 4> raw{};
176 }; 178 };
177}; 179};
178static_assert(sizeof(DomainMessageHeader) == 16, "DomainMessageHeader size is incorrect"); 180static_assert(sizeof(DomainMessageHeader) == 16, "DomainMessageHeader size is incorrect");
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index f3da525d6..a7b5849b0 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -58,8 +58,7 @@ SharedPtr<WritableEvent> HLERequestContext::SleepClientThread(
58 auto& kernel = Core::System::GetInstance().Kernel(); 58 auto& kernel = Core::System::GetInstance().Kernel();
59 if (!writable_event) { 59 if (!writable_event) {
60 // Create event if not provided 60 // Create event if not provided
61 const auto pair = WritableEvent::CreateEventPair(kernel, ResetType::Automatic, 61 const auto pair = WritableEvent::CreateEventPair(kernel, "HLE Pause Event: " + reason);
62 "HLE Pause Event: " + reason);
63 writable_event = pair.writable; 62 writable_event = pair.writable;
64 } 63 }
65 64
diff --git a/src/core/hle/kernel/object.h b/src/core/hle/kernel/object.h
index 2821176a7..a6faeb83b 100644
--- a/src/core/hle/kernel/object.h
+++ b/src/core/hle/kernel/object.h
@@ -32,11 +32,6 @@ enum class HandleType : u32 {
32 ServerSession, 32 ServerSession,
33}; 33};
34 34
35enum class ResetType {
36 Automatic, ///< Reset automatically on object acquisition
37 Manual, ///< Never reset automatically
38};
39
40class Object : NonCopyable { 35class Object : NonCopyable {
41public: 36public:
42 explicit Object(KernelCore& kernel); 37 explicit Object(KernelCore& kernel);
diff --git a/src/core/hle/kernel/readable_event.cpp b/src/core/hle/kernel/readable_event.cpp
index 06463cd26..d8ac97aa1 100644
--- a/src/core/hle/kernel/readable_event.cpp
+++ b/src/core/hle/kernel/readable_event.cpp
@@ -20,15 +20,13 @@ bool ReadableEvent::ShouldWait(const Thread* thread) const {
20 20
21void ReadableEvent::Acquire(Thread* thread) { 21void ReadableEvent::Acquire(Thread* thread) {
22 ASSERT_MSG(!ShouldWait(thread), "object unavailable!"); 22 ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
23
24 if (reset_type == ResetType::Automatic) {
25 signaled = false;
26 }
27} 23}
28 24
29void ReadableEvent::Signal() { 25void ReadableEvent::Signal() {
30 signaled = true; 26 if (!signaled) {
31 WakeupAllWaitingThreads(); 27 signaled = true;
28 WakeupAllWaitingThreads();
29 };
32} 30}
33 31
34void ReadableEvent::Clear() { 32void ReadableEvent::Clear() {
diff --git a/src/core/hle/kernel/readable_event.h b/src/core/hle/kernel/readable_event.h
index 84215f572..11ff71c3a 100644
--- a/src/core/hle/kernel/readable_event.h
+++ b/src/core/hle/kernel/readable_event.h
@@ -27,10 +27,6 @@ public:
27 return name; 27 return name;
28 } 28 }
29 29
30 ResetType GetResetType() const {
31 return reset_type;
32 }
33
34 static constexpr HandleType HANDLE_TYPE = HandleType::ReadableEvent; 30 static constexpr HandleType HANDLE_TYPE = HandleType::ReadableEvent;
35 HandleType GetHandleType() const override { 31 HandleType GetHandleType() const override {
36 return HANDLE_TYPE; 32 return HANDLE_TYPE;
@@ -55,8 +51,7 @@ private:
55 51
56 void Signal(); 52 void Signal();
57 53
58 ResetType reset_type; 54 bool signaled{};
59 bool signaled;
60 55
61 std::string name; ///< Name of event (optional) 56 std::string name; ///< Name of event (optional)
62}; 57};
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index f64236be1..c63a9ba8b 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -2099,7 +2099,7 @@ static ResultCode CreateEvent(Core::System& system, Handle* write_handle, Handle
2099 2099
2100 auto& kernel = system.Kernel(); 2100 auto& kernel = system.Kernel();
2101 const auto [readable_event, writable_event] = 2101 const auto [readable_event, writable_event] =
2102 WritableEvent::CreateEventPair(kernel, ResetType::Manual, "CreateEvent"); 2102 WritableEvent::CreateEventPair(kernel, "CreateEvent");
2103 2103
2104 HandleTable& handle_table = kernel.CurrentProcess()->GetHandleTable(); 2104 HandleTable& handle_table = kernel.CurrentProcess()->GetHandleTable();
2105 2105
diff --git a/src/core/hle/kernel/writable_event.cpp b/src/core/hle/kernel/writable_event.cpp
index a58ea6ec8..c783a34ee 100644
--- a/src/core/hle/kernel/writable_event.cpp
+++ b/src/core/hle/kernel/writable_event.cpp
@@ -15,8 +15,7 @@ namespace Kernel {
15WritableEvent::WritableEvent(KernelCore& kernel) : Object{kernel} {} 15WritableEvent::WritableEvent(KernelCore& kernel) : Object{kernel} {}
16WritableEvent::~WritableEvent() = default; 16WritableEvent::~WritableEvent() = default;
17 17
18EventPair WritableEvent::CreateEventPair(KernelCore& kernel, ResetType reset_type, 18EventPair WritableEvent::CreateEventPair(KernelCore& kernel, std::string name) {
19 std::string name) {
20 SharedPtr<WritableEvent> writable_event(new WritableEvent(kernel)); 19 SharedPtr<WritableEvent> writable_event(new WritableEvent(kernel));
21 SharedPtr<ReadableEvent> readable_event(new ReadableEvent(kernel)); 20 SharedPtr<ReadableEvent> readable_event(new ReadableEvent(kernel));
22 21
@@ -24,7 +23,6 @@ EventPair WritableEvent::CreateEventPair(KernelCore& kernel, ResetType reset_typ
24 writable_event->readable = readable_event; 23 writable_event->readable = readable_event;
25 readable_event->name = name + ":Readable"; 24 readable_event->name = name + ":Readable";
26 readable_event->signaled = false; 25 readable_event->signaled = false;
27 readable_event->reset_type = reset_type;
28 26
29 return {std::move(readable_event), std::move(writable_event)}; 27 return {std::move(readable_event), std::move(writable_event)};
30} 28}
@@ -33,10 +31,6 @@ SharedPtr<ReadableEvent> WritableEvent::GetReadableEvent() const {
33 return readable; 31 return readable;
34} 32}
35 33
36ResetType WritableEvent::GetResetType() const {
37 return readable->reset_type;
38}
39
40void WritableEvent::Signal() { 34void WritableEvent::Signal() {
41 readable->Signal(); 35 readable->Signal();
42} 36}
diff --git a/src/core/hle/kernel/writable_event.h b/src/core/hle/kernel/writable_event.h
index d00c92a6b..f46cf1dd8 100644
--- a/src/core/hle/kernel/writable_event.h
+++ b/src/core/hle/kernel/writable_event.h
@@ -24,11 +24,9 @@ public:
24 /** 24 /**
25 * Creates an event 25 * Creates an event
26 * @param kernel The kernel instance to create this event under. 26 * @param kernel The kernel instance to create this event under.
27 * @param reset_type ResetType describing how to create event
28 * @param name Optional name of event 27 * @param name Optional name of event
29 */ 28 */
30 static EventPair CreateEventPair(KernelCore& kernel, ResetType reset_type, 29 static EventPair CreateEventPair(KernelCore& kernel, std::string name = "Unknown");
31 std::string name = "Unknown");
32 30
33 std::string GetTypeName() const override { 31 std::string GetTypeName() const override {
34 return "WritableEvent"; 32 return "WritableEvent";
@@ -44,8 +42,6 @@ public:
44 42
45 SharedPtr<ReadableEvent> GetReadableEvent() const; 43 SharedPtr<ReadableEvent> GetReadableEvent() const;
46 44
47 ResetType GetResetType() const;
48
49 void Signal(); 45 void Signal();
50 void Clear(); 46 void Clear();
51 bool IsSignaled() const; 47 bool IsSignaled() const;
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 3a32d5b41..ba54b3040 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -289,8 +289,8 @@ ISelfController::ISelfController(Core::System& system,
289 RegisterHandlers(functions); 289 RegisterHandlers(functions);
290 290
291 auto& kernel = system.Kernel(); 291 auto& kernel = system.Kernel();
292 launchable_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual, 292 launchable_event =
293 "ISelfController:LaunchableEvent"); 293 Kernel::WritableEvent::CreateEventPair(kernel, "ISelfController:LaunchableEvent");
294 294
295 // This event is created by AM on the first time GetAccumulatedSuspendedTickChangedEvent() is 295 // This event is created by AM on the first time GetAccumulatedSuspendedTickChangedEvent() is
296 // called. Yuzu can just create it unconditionally, since it doesn't need to support multiple 296 // called. Yuzu can just create it unconditionally, since it doesn't need to support multiple
@@ -298,7 +298,7 @@ ISelfController::ISelfController(Core::System& system,
298 // suspended if the event has previously been created by a call to 298 // suspended if the event has previously been created by a call to
299 // GetAccumulatedSuspendedTickChangedEvent. 299 // GetAccumulatedSuspendedTickChangedEvent.
300 accumulated_suspended_tick_changed_event = Kernel::WritableEvent::CreateEventPair( 300 accumulated_suspended_tick_changed_event = Kernel::WritableEvent::CreateEventPair(
301 kernel, Kernel::ResetType::Manual, "ISelfController:AccumulatedSuspendedTickChangedEvent"); 301 kernel, "ISelfController:AccumulatedSuspendedTickChangedEvent");
302 accumulated_suspended_tick_changed_event.writable->Signal(); 302 accumulated_suspended_tick_changed_event.writable->Signal();
303} 303}
304 304
@@ -523,10 +523,10 @@ void ISelfController::GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequest
523} 523}
524 524
525AppletMessageQueue::AppletMessageQueue(Kernel::KernelCore& kernel) { 525AppletMessageQueue::AppletMessageQueue(Kernel::KernelCore& kernel) {
526 on_new_message = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual, 526 on_new_message =
527 "AMMessageQueue:OnMessageRecieved"); 527 Kernel::WritableEvent::CreateEventPair(kernel, "AMMessageQueue:OnMessageRecieved");
528 on_operation_mode_changed = Kernel::WritableEvent::CreateEventPair( 528 on_operation_mode_changed =
529 kernel, Kernel::ResetType::Automatic, "AMMessageQueue:OperationModeChanged"); 529 Kernel::WritableEvent::CreateEventPair(kernel, "AMMessageQueue:OperationModeChanged");
530} 530}
531 531
532AppletMessageQueue::~AppletMessageQueue() = default; 532AppletMessageQueue::~AppletMessageQueue() = default;
@@ -1073,9 +1073,9 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
1073 {71, nullptr, "RequestToReboot"}, 1073 {71, nullptr, "RequestToReboot"},
1074 {80, nullptr, "ExitAndRequestToShowThanksMessage"}, 1074 {80, nullptr, "ExitAndRequestToShowThanksMessage"},
1075 {90, &IApplicationFunctions::EnableApplicationCrashReport, "EnableApplicationCrashReport"}, 1075 {90, &IApplicationFunctions::EnableApplicationCrashReport, "EnableApplicationCrashReport"},
1076 {100, nullptr, "InitializeApplicationCopyrightFrameBuffer"}, 1076 {100, &IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer, "InitializeApplicationCopyrightFrameBuffer"},
1077 {101, nullptr, "SetApplicationCopyrightImage"}, 1077 {101, &IApplicationFunctions::SetApplicationCopyrightImage, "SetApplicationCopyrightImage"},
1078 {102, nullptr, "SetApplicationCopyrightVisibility"}, 1078 {102, &IApplicationFunctions::SetApplicationCopyrightVisibility, "SetApplicationCopyrightVisibility"},
1079 {110, nullptr, "QueryApplicationPlayStatistics"}, 1079 {110, nullptr, "QueryApplicationPlayStatistics"},
1080 {120, nullptr, "ExecuteProgram"}, 1080 {120, nullptr, "ExecuteProgram"},
1081 {121, nullptr, "ClearUserChannel"}, 1081 {121, nullptr, "ClearUserChannel"},
@@ -1091,7 +1091,7 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
1091 1091
1092 auto& kernel = system.Kernel(); 1092 auto& kernel = system.Kernel();
1093 gpu_error_detected_event = Kernel::WritableEvent::CreateEventPair( 1093 gpu_error_detected_event = Kernel::WritableEvent::CreateEventPair(
1094 kernel, Kernel::ResetType::Manual, "IApplicationFunctions:GpuErrorDetectedSystemEvent"); 1094 kernel, "IApplicationFunctions:GpuErrorDetectedSystemEvent");
1095} 1095}
1096 1096
1097IApplicationFunctions::~IApplicationFunctions() = default; 1097IApplicationFunctions::~IApplicationFunctions() = default;
@@ -1103,6 +1103,31 @@ void IApplicationFunctions::EnableApplicationCrashReport(Kernel::HLERequestConte
1103 rb.Push(RESULT_SUCCESS); 1103 rb.Push(RESULT_SUCCESS);
1104} 1104}
1105 1105
1106void IApplicationFunctions::InitializeApplicationCopyrightFrameBuffer(
1107 Kernel::HLERequestContext& ctx) {
1108 LOG_WARNING(Service_AM, "(STUBBED) called");
1109
1110 IPC::ResponseBuilder rb{ctx, 2};
1111 rb.Push(RESULT_SUCCESS);
1112}
1113
1114void IApplicationFunctions::SetApplicationCopyrightImage(Kernel::HLERequestContext& ctx) {
1115 LOG_WARNING(Service_AM, "(STUBBED) called");
1116
1117 IPC::ResponseBuilder rb{ctx, 2};
1118 rb.Push(RESULT_SUCCESS);
1119}
1120
1121void IApplicationFunctions::SetApplicationCopyrightVisibility(Kernel::HLERequestContext& ctx) {
1122 IPC::RequestParser rp{ctx};
1123 const auto is_visible = rp.Pop<bool>();
1124
1125 LOG_WARNING(Service_AM, "(STUBBED) called, is_visible={}", is_visible);
1126
1127 IPC::ResponseBuilder rb{ctx, 2};
1128 rb.Push(RESULT_SUCCESS);
1129}
1130
1106void IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed( 1131void IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed(
1107 Kernel::HLERequestContext& ctx) { 1132 Kernel::HLERequestContext& ctx) {
1108 LOG_WARNING(Service_AM, "(STUBBED) called"); 1133 LOG_WARNING(Service_AM, "(STUBBED) called");
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index ccd053c13..2ae9402a8 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -252,6 +252,9 @@ private:
252 void BeginBlockingHomeButton(Kernel::HLERequestContext& ctx); 252 void BeginBlockingHomeButton(Kernel::HLERequestContext& ctx);
253 void EndBlockingHomeButton(Kernel::HLERequestContext& ctx); 253 void EndBlockingHomeButton(Kernel::HLERequestContext& ctx);
254 void EnableApplicationCrashReport(Kernel::HLERequestContext& ctx); 254 void EnableApplicationCrashReport(Kernel::HLERequestContext& ctx);
255 void InitializeApplicationCopyrightFrameBuffer(Kernel::HLERequestContext& ctx);
256 void SetApplicationCopyrightImage(Kernel::HLERequestContext& ctx);
257 void SetApplicationCopyrightVisibility(Kernel::HLERequestContext& ctx);
255 void GetGpuErrorDetectedSystemEvent(Kernel::HLERequestContext& ctx); 258 void GetGpuErrorDetectedSystemEvent(Kernel::HLERequestContext& ctx);
256 259
257 bool launch_popped_application_specific = false; 260 bool launch_popped_application_specific = false;
diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp
index 720fe766f..673ad1f7f 100644
--- a/src/core/hle/service/am/applets/applets.cpp
+++ b/src/core/hle/service/am/applets/applets.cpp
@@ -24,12 +24,12 @@
24namespace Service::AM::Applets { 24namespace Service::AM::Applets {
25 25
26AppletDataBroker::AppletDataBroker(Kernel::KernelCore& kernel) { 26AppletDataBroker::AppletDataBroker(Kernel::KernelCore& kernel) {
27 state_changed_event = Kernel::WritableEvent::CreateEventPair( 27 state_changed_event =
28 kernel, Kernel::ResetType::Manual, "ILibraryAppletAccessor:StateChangedEvent"); 28 Kernel::WritableEvent::CreateEventPair(kernel, "ILibraryAppletAccessor:StateChangedEvent");
29 pop_out_data_event = Kernel::WritableEvent::CreateEventPair( 29 pop_out_data_event =
30 kernel, Kernel::ResetType::Manual, "ILibraryAppletAccessor:PopDataOutEvent"); 30 Kernel::WritableEvent::CreateEventPair(kernel, "ILibraryAppletAccessor:PopDataOutEvent");
31 pop_interactive_out_data_event = Kernel::WritableEvent::CreateEventPair( 31 pop_interactive_out_data_event = Kernel::WritableEvent::CreateEventPair(
32 kernel, Kernel::ResetType::Manual, "ILibraryAppletAccessor:PopInteractiveDataOutEvent"); 32 kernel, "ILibraryAppletAccessor:PopInteractiveDataOutEvent");
33} 33}
34 34
35AppletDataBroker::~AppletDataBroker() = default; 35AppletDataBroker::~AppletDataBroker() = default;
diff --git a/src/core/hle/service/am/applets/error.cpp b/src/core/hle/service/am/applets/error.cpp
index a7db26725..eab0d42c9 100644
--- a/src/core/hle/service/am/applets/error.cpp
+++ b/src/core/hle/service/am/applets/error.cpp
@@ -20,9 +20,9 @@ namespace Service::AM::Applets {
20struct ShowError { 20struct ShowError {
21 u8 mode; 21 u8 mode;
22 bool jump; 22 bool jump;
23 INSERT_PADDING_BYTES(4); 23 INSERT_UNION_PADDING_BYTES(4);
24 bool use_64bit_error_code; 24 bool use_64bit_error_code;
25 INSERT_PADDING_BYTES(1); 25 INSERT_UNION_PADDING_BYTES(1);
26 u64 error_code_64; 26 u64 error_code_64;
27 u32 error_code_32; 27 u32 error_code_32;
28}; 28};
@@ -32,7 +32,7 @@ static_assert(sizeof(ShowError) == 0x14, "ShowError has incorrect size.");
32struct ShowErrorRecord { 32struct ShowErrorRecord {
33 u8 mode; 33 u8 mode;
34 bool jump; 34 bool jump;
35 INSERT_PADDING_BYTES(6); 35 INSERT_UNION_PADDING_BYTES(6);
36 u64 error_code_64; 36 u64 error_code_64;
37 u64 posix_time; 37 u64 posix_time;
38}; 38};
@@ -41,7 +41,7 @@ static_assert(sizeof(ShowErrorRecord) == 0x18, "ShowErrorRecord has incorrect si
41struct SystemErrorArg { 41struct SystemErrorArg {
42 u8 mode; 42 u8 mode;
43 bool jump; 43 bool jump;
44 INSERT_PADDING_BYTES(6); 44 INSERT_UNION_PADDING_BYTES(6);
45 u64 error_code_64; 45 u64 error_code_64;
46 std::array<char, 8> language_code; 46 std::array<char, 8> language_code;
47 std::array<char, 0x800> main_text; 47 std::array<char, 0x800> main_text;
@@ -52,7 +52,7 @@ static_assert(sizeof(SystemErrorArg) == 0x1018, "SystemErrorArg has incorrect si
52struct ApplicationErrorArg { 52struct ApplicationErrorArg {
53 u8 mode; 53 u8 mode;
54 bool jump; 54 bool jump;
55 INSERT_PADDING_BYTES(6); 55 INSERT_UNION_PADDING_BYTES(6);
56 u32 error_code; 56 u32 error_code;
57 std::array<char, 8> language_code; 57 std::array<char, 8> language_code;
58 std::array<char, 0x800> main_text; 58 std::array<char, 0x800> main_text;
@@ -65,6 +65,7 @@ union Error::ErrorArguments {
65 ShowErrorRecord error_record; 65 ShowErrorRecord error_record;
66 SystemErrorArg system_error; 66 SystemErrorArg system_error;
67 ApplicationErrorArg application_error; 67 ApplicationErrorArg application_error;
68 std::array<u8, 0x1018> raw{};
68}; 69};
69 70
70namespace { 71namespace {
diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp
index e9cf1e840..f36ccbc49 100644
--- a/src/core/hle/service/aoc/aoc_u.cpp
+++ b/src/core/hle/service/aoc/aoc_u.cpp
@@ -67,8 +67,8 @@ AOC_U::AOC_U(Core::System& system)
67 RegisterHandlers(functions); 67 RegisterHandlers(functions);
68 68
69 auto& kernel = system.Kernel(); 69 auto& kernel = system.Kernel();
70 aoc_change_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual, 70 aoc_change_event =
71 "GetAddOnContentListChanged:Event"); 71 Kernel::WritableEvent::CreateEventPair(kernel, "GetAddOnContentListChanged:Event");
72} 72}
73 73
74AOC_U::~AOC_U() = default; 74AOC_U::~AOC_U() = default;
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp
index 9afefb5c6..6a29377e3 100644
--- a/src/core/hle/service/audio/audout_u.cpp
+++ b/src/core/hle/service/audio/audout_u.cpp
@@ -65,8 +65,8 @@ public:
65 RegisterHandlers(functions); 65 RegisterHandlers(functions);
66 66
67 // This is the event handle used to check if the audio buffer was released 67 // This is the event handle used to check if the audio buffer was released
68 buffer_event = Kernel::WritableEvent::CreateEventPair( 68 buffer_event =
69 system.Kernel(), Kernel::ResetType::Manual, "IAudioOutBufferReleased"); 69 Kernel::WritableEvent::CreateEventPair(system.Kernel(), "IAudioOutBufferReleased");
70 70
71 stream = audio_core.OpenStream(system.CoreTiming(), audio_params.sample_rate, 71 stream = audio_core.OpenStream(system.CoreTiming(), audio_params.sample_rate,
72 audio_params.channel_count, std::move(unique_name), 72 audio_params.channel_count, std::move(unique_name),
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index f162249ed..4ea7ade6e 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -47,8 +47,8 @@ public:
47 // clang-format on 47 // clang-format on
48 RegisterHandlers(functions); 48 RegisterHandlers(functions);
49 49
50 system_event = Kernel::WritableEvent::CreateEventPair( 50 system_event =
51 system.Kernel(), Kernel::ResetType::Manual, "IAudioRenderer:SystemEvent"); 51 Kernel::WritableEvent::CreateEventPair(system.Kernel(), "IAudioRenderer:SystemEvent");
52 renderer = std::make_unique<AudioCore::AudioRenderer>( 52 renderer = std::make_unique<AudioCore::AudioRenderer>(
53 system.CoreTiming(), audren_params, system_event.writable, instance_number); 53 system.CoreTiming(), audren_params, system_event.writable, instance_number);
54 } 54 }
@@ -180,17 +180,17 @@ public:
180 RegisterHandlers(functions); 180 RegisterHandlers(functions);
181 181
182 auto& kernel = system.Kernel(); 182 auto& kernel = system.Kernel();
183 buffer_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic, 183 buffer_event =
184 "IAudioOutBufferReleasedEvent"); 184 Kernel::WritableEvent::CreateEventPair(kernel, "IAudioOutBufferReleasedEvent");
185 185
186 // Should be similar to audio_output_device_switch_event 186 // Should be similar to audio_output_device_switch_event
187 audio_input_device_switch_event = Kernel::WritableEvent::CreateEventPair( 187 audio_input_device_switch_event = Kernel::WritableEvent::CreateEventPair(
188 kernel, Kernel::ResetType::Automatic, "IAudioDevice:AudioInputDeviceSwitchedEvent"); 188 kernel, "IAudioDevice:AudioInputDeviceSwitchedEvent");
189 189
190 // Should only be signalled when an audio output device has been changed, example: speaker 190 // Should only be signalled when an audio output device has been changed, example: speaker
191 // to headset 191 // to headset
192 audio_output_device_switch_event = Kernel::WritableEvent::CreateEventPair( 192 audio_output_device_switch_event = Kernel::WritableEvent::CreateEventPair(
193 kernel, Kernel::ResetType::Automatic, "IAudioDevice:AudioOutputDeviceSwitchedEvent"); 193 kernel, "IAudioDevice:AudioOutputDeviceSwitchedEvent");
194 } 194 }
195 195
196private: 196private:
diff --git a/src/core/hle/service/bcat/backend/backend.cpp b/src/core/hle/service/bcat/backend/backend.cpp
index b86fda29a..dec0849b8 100644
--- a/src/core/hle/service/bcat/backend/backend.cpp
+++ b/src/core/hle/service/bcat/backend/backend.cpp
@@ -13,8 +13,7 @@ namespace Service::BCAT {
13ProgressServiceBackend::ProgressServiceBackend(Kernel::KernelCore& kernel, 13ProgressServiceBackend::ProgressServiceBackend(Kernel::KernelCore& kernel,
14 std::string_view event_name) { 14 std::string_view event_name) {
15 event = Kernel::WritableEvent::CreateEventPair( 15 event = Kernel::WritableEvent::CreateEventPair(
16 kernel, Kernel::ResetType::Automatic, 16 kernel, std::string("ProgressServiceBackend:UpdateEvent:").append(event_name));
17 std::string("ProgressServiceBackend:UpdateEvent:").append(event_name));
18} 17}
19 18
20Kernel::SharedPtr<Kernel::ReadableEvent> ProgressServiceBackend::GetEvent() const { 19Kernel::SharedPtr<Kernel::ReadableEvent> ProgressServiceBackend::GetEvent() const {
diff --git a/src/core/hle/service/btdrv/btdrv.cpp b/src/core/hle/service/btdrv/btdrv.cpp
index afce581e5..4574d9572 100644
--- a/src/core/hle/service/btdrv/btdrv.cpp
+++ b/src/core/hle/service/btdrv/btdrv.cpp
@@ -34,8 +34,7 @@ public:
34 RegisterHandlers(functions); 34 RegisterHandlers(functions);
35 35
36 auto& kernel = system.Kernel(); 36 auto& kernel = system.Kernel();
37 register_event = Kernel::WritableEvent::CreateEventPair( 37 register_event = Kernel::WritableEvent::CreateEventPair(kernel, "BT:RegisterEvent");
38 kernel, Kernel::ResetType::Automatic, "BT:RegisterEvent");
39 } 38 }
40 39
41private: 40private:
diff --git a/src/core/hle/service/btm/btm.cpp b/src/core/hle/service/btm/btm.cpp
index 920fc6ff7..251b3c9df 100644
--- a/src/core/hle/service/btm/btm.cpp
+++ b/src/core/hle/service/btm/btm.cpp
@@ -57,14 +57,12 @@ public:
57 RegisterHandlers(functions); 57 RegisterHandlers(functions);
58 58
59 auto& kernel = system.Kernel(); 59 auto& kernel = system.Kernel();
60 scan_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic, 60 scan_event = Kernel::WritableEvent::CreateEventPair(kernel, "IBtmUserCore:ScanEvent");
61 "IBtmUserCore:ScanEvent"); 61 connection_event =
62 connection_event = Kernel::WritableEvent::CreateEventPair( 62 Kernel::WritableEvent::CreateEventPair(kernel, "IBtmUserCore:ConnectionEvent");
63 kernel, Kernel::ResetType::Automatic, "IBtmUserCore:ConnectionEvent"); 63 service_discovery =
64 service_discovery = Kernel::WritableEvent::CreateEventPair( 64 Kernel::WritableEvent::CreateEventPair(kernel, "IBtmUserCore:Discovery");
65 kernel, Kernel::ResetType::Automatic, "IBtmUserCore:Discovery"); 65 config_event = Kernel::WritableEvent::CreateEventPair(kernel, "IBtmUserCore:ConfigEvent");
66 config_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic,
67 "IBtmUserCore:ConfigEvent");
68 } 66 }
69 67
70private: 68private:
diff --git a/src/core/hle/service/friend/friend.cpp b/src/core/hle/service/friend/friend.cpp
index 75dd9043b..1a0214f08 100644
--- a/src/core/hle/service/friend/friend.cpp
+++ b/src/core/hle/service/friend/friend.cpp
@@ -162,7 +162,7 @@ public:
162 RegisterHandlers(functions); 162 RegisterHandlers(functions);
163 163
164 notification_event = Kernel::WritableEvent::CreateEventPair( 164 notification_event = Kernel::WritableEvent::CreateEventPair(
165 system.Kernel(), Kernel::ResetType::Manual, "INotificationService:NotifyEvent"); 165 system.Kernel(), "INotificationService:NotifyEvent");
166 } 166 }
167 167
168private: 168private:
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 81bd2f3cb..79fff517e 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -174,7 +174,7 @@ void Controller_NPad::OnInit() {
174 auto& kernel = system.Kernel(); 174 auto& kernel = system.Kernel();
175 for (std::size_t i = 0; i < styleset_changed_events.size(); i++) { 175 for (std::size_t i = 0; i < styleset_changed_events.size(); i++) {
176 styleset_changed_events[i] = Kernel::WritableEvent::CreateEventPair( 176 styleset_changed_events[i] = Kernel::WritableEvent::CreateEventPair(
177 kernel, Kernel::ResetType::Manual, fmt::format("npad:NpadStyleSetChanged_{}", i)); 177 kernel, fmt::format("npad:NpadStyleSetChanged_{}", i));
178 } 178 }
179 179
180 if (!IsControllerActivated()) { 180 if (!IsControllerActivated()) {
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index ba1da4181..ecc130f6c 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -203,13 +203,13 @@ Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) {
203 {120, &Hid::SetNpadJoyHoldType, "SetNpadJoyHoldType"}, 203 {120, &Hid::SetNpadJoyHoldType, "SetNpadJoyHoldType"},
204 {121, &Hid::GetNpadJoyHoldType, "GetNpadJoyHoldType"}, 204 {121, &Hid::GetNpadJoyHoldType, "GetNpadJoyHoldType"},
205 {122, &Hid::SetNpadJoyAssignmentModeSingleByDefault, "SetNpadJoyAssignmentModeSingleByDefault"}, 205 {122, &Hid::SetNpadJoyAssignmentModeSingleByDefault, "SetNpadJoyAssignmentModeSingleByDefault"},
206 {123, nullptr, "SetNpadJoyAssignmentModeSingleByDefault"}, 206 {123, &Hid::SetNpadJoyAssignmentModeSingle, "SetNpadJoyAssignmentModeSingle"},
207 {124, &Hid::SetNpadJoyAssignmentModeDual, "SetNpadJoyAssignmentModeDual"}, 207 {124, &Hid::SetNpadJoyAssignmentModeDual, "SetNpadJoyAssignmentModeDual"},
208 {125, &Hid::MergeSingleJoyAsDualJoy, "MergeSingleJoyAsDualJoy"}, 208 {125, &Hid::MergeSingleJoyAsDualJoy, "MergeSingleJoyAsDualJoy"},
209 {126, &Hid::StartLrAssignmentMode, "StartLrAssignmentMode"}, 209 {126, &Hid::StartLrAssignmentMode, "StartLrAssignmentMode"},
210 {127, &Hid::StopLrAssignmentMode, "StopLrAssignmentMode"}, 210 {127, &Hid::StopLrAssignmentMode, "StopLrAssignmentMode"},
211 {128, &Hid::SetNpadHandheldActivationMode, "SetNpadHandheldActivationMode"}, 211 {128, &Hid::SetNpadHandheldActivationMode, "SetNpadHandheldActivationMode"},
212 {129, nullptr, "GetNpadHandheldActivationMode"}, 212 {129, &Hid::GetNpadHandheldActivationMode, "GetNpadHandheldActivationMode"},
213 {130, &Hid::SwapNpadAssignment, "SwapNpadAssignment"}, 213 {130, &Hid::SwapNpadAssignment, "SwapNpadAssignment"},
214 {131, nullptr, "IsUnintendedHomeButtonInputProtectionEnabled"}, 214 {131, nullptr, "IsUnintendedHomeButtonInputProtectionEnabled"},
215 {132, nullptr, "EnableUnintendedHomeButtonInputProtection"}, 215 {132, nullptr, "EnableUnintendedHomeButtonInputProtection"},
@@ -557,10 +557,126 @@ void Hid::SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx
557 LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", npad_id, 557 LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", npad_id,
558 applet_resource_user_id); 558 applet_resource_user_id);
559 559
560 auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
561 controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Single);
562
563 IPC::ResponseBuilder rb{ctx, 2};
564 rb.Push(RESULT_SUCCESS);
565}
566
567void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) {
568 // TODO: Check the differences between this and SetNpadJoyAssignmentModeSingleByDefault
569 IPC::RequestParser rp{ctx};
570 const auto npad_id{rp.Pop<u32>()};
571 const auto applet_resource_user_id{rp.Pop<u64>()};
572 const auto npad_joy_device_type{rp.Pop<u64>()};
573
574 LOG_WARNING(Service_HID,
575 "(STUBBED) called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}",
576 npad_id, applet_resource_user_id, npad_joy_device_type);
577
578 auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
579 controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Single);
580
581 IPC::ResponseBuilder rb{ctx, 2};
582 rb.Push(RESULT_SUCCESS);
583}
584
585void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) {
586 IPC::RequestParser rp{ctx};
587 const auto npad_id{rp.Pop<u32>()};
588 const auto applet_resource_user_id{rp.Pop<u64>()};
589
590 LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", npad_id,
591 applet_resource_user_id);
592
593 auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
594 controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Dual);
595
596 IPC::ResponseBuilder rb{ctx, 2};
597 rb.Push(RESULT_SUCCESS);
598}
599
600void Hid::MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) {
601 IPC::RequestParser rp{ctx};
602 const auto unknown_1{rp.Pop<u32>()};
603 const auto unknown_2{rp.Pop<u32>()};
604 const auto applet_resource_user_id{rp.Pop<u64>()};
605
606 LOG_WARNING(Service_HID,
607 "(STUBBED) called, unknown_1={}, unknown_2={}, applet_resource_user_id={}",
608 unknown_1, unknown_2, applet_resource_user_id);
609
610 IPC::ResponseBuilder rb{ctx, 2};
611 rb.Push(RESULT_SUCCESS);
612}
613
614void Hid::StartLrAssignmentMode(Kernel::HLERequestContext& ctx) {
615 IPC::RequestParser rp{ctx};
616 const auto applet_resource_user_id{rp.Pop<u64>()};
617
618 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
619 auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
620 controller.StartLRAssignmentMode();
621
622 IPC::ResponseBuilder rb{ctx, 2};
623 rb.Push(RESULT_SUCCESS);
624}
625
626void Hid::StopLrAssignmentMode(Kernel::HLERequestContext& ctx) {
627 IPC::RequestParser rp{ctx};
628 const auto applet_resource_user_id{rp.Pop<u64>()};
629
630 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
631 auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
632 controller.StopLRAssignmentMode();
633
634 IPC::ResponseBuilder rb{ctx, 2};
635 rb.Push(RESULT_SUCCESS);
636}
637
638void Hid::SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) {
639 IPC::RequestParser rp{ctx};
640 const auto applet_resource_user_id{rp.Pop<u64>()};
641 const auto mode{rp.Pop<u64>()};
642
643 LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}, mode={}",
644 applet_resource_user_id, mode);
645
646 IPC::ResponseBuilder rb{ctx, 2};
647 rb.Push(RESULT_SUCCESS);
648}
649
650void Hid::GetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) {
651 IPC::RequestParser rp{ctx};
652 const auto applet_resource_user_id{rp.Pop<u64>()};
653
654 LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}",
655 applet_resource_user_id);
656
560 IPC::ResponseBuilder rb{ctx, 2}; 657 IPC::ResponseBuilder rb{ctx, 2};
561 rb.Push(RESULT_SUCCESS); 658 rb.Push(RESULT_SUCCESS);
562} 659}
563 660
661void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) {
662 IPC::RequestParser rp{ctx};
663 const auto npad_1{rp.Pop<u32>()};
664 const auto npad_2{rp.Pop<u32>()};
665 const auto applet_resource_user_id{rp.Pop<u64>()};
666
667 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, npad_1={}, npad_2={}",
668 applet_resource_user_id, npad_1, npad_2);
669
670 auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
671 IPC::ResponseBuilder rb{ctx, 2};
672 if (controller.SwapNpadAssignment(npad_1, npad_2)) {
673 rb.Push(RESULT_SUCCESS);
674 } else {
675 LOG_ERROR(Service_HID, "Npads are not connected!");
676 rb.Push(ERR_NPAD_NOT_CONNECTED);
677 }
678}
679
564void Hid::BeginPermitVibrationSession(Kernel::HLERequestContext& ctx) { 680void Hid::BeginPermitVibrationSession(Kernel::HLERequestContext& ctx) {
565 IPC::RequestParser rp{ctx}; 681 IPC::RequestParser rp{ctx};
566 const auto applet_resource_user_id{rp.Pop<u64>()}; 682 const auto applet_resource_user_id{rp.Pop<u64>()};
@@ -635,47 +751,6 @@ void Hid::GetActualVibrationValue(Kernel::HLERequestContext& ctx) {
635 applet_resource->GetController<Controller_NPad>(HidController::NPad).GetLastVibration()); 751 applet_resource->GetController<Controller_NPad>(HidController::NPad).GetLastVibration());
636} 752}
637 753
638void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) {
639 IPC::RequestParser rp{ctx};
640 const auto npad_id{rp.Pop<u32>()};
641 const auto applet_resource_user_id{rp.Pop<u64>()};
642
643 LOG_DEBUG(Service_HID, "called, npad_id={}, applet_resource_user_id={}", npad_id,
644 applet_resource_user_id);
645
646 auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
647 controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Dual);
648
649 IPC::ResponseBuilder rb{ctx, 2};
650 rb.Push(RESULT_SUCCESS);
651}
652
653void Hid::MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) {
654 IPC::RequestParser rp{ctx};
655 const auto unknown_1{rp.Pop<u32>()};
656 const auto unknown_2{rp.Pop<u32>()};
657 const auto applet_resource_user_id{rp.Pop<u64>()};
658
659 LOG_WARNING(Service_HID,
660 "(STUBBED) called, unknown_1={}, unknown_2={}, applet_resource_user_id={}",
661 unknown_1, unknown_2, applet_resource_user_id);
662
663 IPC::ResponseBuilder rb{ctx, 2};
664 rb.Push(RESULT_SUCCESS);
665}
666
667void Hid::SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) {
668 IPC::RequestParser rp{ctx};
669 const auto applet_resource_user_id{rp.Pop<u64>()};
670 const auto mode{rp.Pop<u64>()};
671
672 LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}, mode={}",
673 applet_resource_user_id, mode);
674
675 IPC::ResponseBuilder rb{ctx, 2};
676 rb.Push(RESULT_SUCCESS);
677}
678
679void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { 754void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) {
680 LOG_DEBUG(Service_HID, "called"); 755 LOG_DEBUG(Service_HID, "called");
681 756
@@ -769,49 +844,6 @@ void Hid::SetPalmaBoostMode(Kernel::HLERequestContext& ctx) {
769 rb.Push(RESULT_SUCCESS); 844 rb.Push(RESULT_SUCCESS);
770} 845}
771 846
772void Hid::StartLrAssignmentMode(Kernel::HLERequestContext& ctx) {
773 IPC::RequestParser rp{ctx};
774 const auto applet_resource_user_id{rp.Pop<u64>()};
775
776 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
777 auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
778 controller.StartLRAssignmentMode();
779
780 IPC::ResponseBuilder rb{ctx, 2};
781 rb.Push(RESULT_SUCCESS);
782}
783
784void Hid::StopLrAssignmentMode(Kernel::HLERequestContext& ctx) {
785 IPC::RequestParser rp{ctx};
786 const auto applet_resource_user_id{rp.Pop<u64>()};
787
788 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
789 auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
790 controller.StopLRAssignmentMode();
791
792 IPC::ResponseBuilder rb{ctx, 2};
793 rb.Push(RESULT_SUCCESS);
794}
795
796void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) {
797 IPC::RequestParser rp{ctx};
798 const auto npad_1{rp.Pop<u32>()};
799 const auto npad_2{rp.Pop<u32>()};
800 const auto applet_resource_user_id{rp.Pop<u64>()};
801
802 LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, npad_1={}, npad_2={}",
803 applet_resource_user_id, npad_1, npad_2);
804
805 auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
806 IPC::ResponseBuilder rb{ctx, 2};
807 if (controller.SwapNpadAssignment(npad_1, npad_2)) {
808 rb.Push(RESULT_SUCCESS);
809 } else {
810 LOG_ERROR(Service_HID, "Npads are not connected!");
811 rb.Push(ERR_NPAD_NOT_CONNECTED);
812 }
813}
814
815class HidDbg final : public ServiceFramework<HidDbg> { 847class HidDbg final : public ServiceFramework<HidDbg> {
816public: 848public:
817 explicit HidDbg() : ServiceFramework{"hid:dbg"} { 849 explicit HidDbg() : ServiceFramework{"hid:dbg"} {
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index 01852e019..f08e036a3 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -106,14 +106,19 @@ private:
106 void SetNpadJoyHoldType(Kernel::HLERequestContext& ctx); 106 void SetNpadJoyHoldType(Kernel::HLERequestContext& ctx);
107 void GetNpadJoyHoldType(Kernel::HLERequestContext& ctx); 107 void GetNpadJoyHoldType(Kernel::HLERequestContext& ctx);
108 void SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx); 108 void SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx);
109 void SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx);
110 void SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx);
111 void MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx);
112 void StartLrAssignmentMode(Kernel::HLERequestContext& ctx);
113 void StopLrAssignmentMode(Kernel::HLERequestContext& ctx);
114 void SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx);
115 void GetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx);
116 void SwapNpadAssignment(Kernel::HLERequestContext& ctx);
109 void BeginPermitVibrationSession(Kernel::HLERequestContext& ctx); 117 void BeginPermitVibrationSession(Kernel::HLERequestContext& ctx);
110 void EndPermitVibrationSession(Kernel::HLERequestContext& ctx); 118 void EndPermitVibrationSession(Kernel::HLERequestContext& ctx);
111 void SendVibrationValue(Kernel::HLERequestContext& ctx); 119 void SendVibrationValue(Kernel::HLERequestContext& ctx);
112 void SendVibrationValues(Kernel::HLERequestContext& ctx); 120 void SendVibrationValues(Kernel::HLERequestContext& ctx);
113 void GetActualVibrationValue(Kernel::HLERequestContext& ctx); 121 void GetActualVibrationValue(Kernel::HLERequestContext& ctx);
114 void SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx);
115 void MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx);
116 void SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx);
117 void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx); 122 void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx);
118 void CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx); 123 void CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx);
119 void PermitVibration(Kernel::HLERequestContext& ctx); 124 void PermitVibration(Kernel::HLERequestContext& ctx);
@@ -123,9 +128,6 @@ private:
123 void StopSixAxisSensor(Kernel::HLERequestContext& ctx); 128 void StopSixAxisSensor(Kernel::HLERequestContext& ctx);
124 void SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx); 129 void SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx);
125 void SetPalmaBoostMode(Kernel::HLERequestContext& ctx); 130 void SetPalmaBoostMode(Kernel::HLERequestContext& ctx);
126 void StartLrAssignmentMode(Kernel::HLERequestContext& ctx);
127 void StopLrAssignmentMode(Kernel::HLERequestContext& ctx);
128 void SwapNpadAssignment(Kernel::HLERequestContext& ctx);
129 131
130 std::shared_ptr<IAppletResource> applet_resource; 132 std::shared_ptr<IAppletResource> applet_resource;
131 Core::System& system; 133 Core::System& system;
diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp
index aa886cd3e..795d7b716 100644
--- a/src/core/hle/service/nfp/nfp.cpp
+++ b/src/core/hle/service/nfp/nfp.cpp
@@ -26,8 +26,7 @@ constexpr ResultCode ERR_NO_APPLICATION_AREA(ErrorModule::NFP, 152);
26Module::Interface::Interface(std::shared_ptr<Module> module, Core::System& system, const char* name) 26Module::Interface::Interface(std::shared_ptr<Module> module, Core::System& system, const char* name)
27 : ServiceFramework(name), module(std::move(module)), system(system) { 27 : ServiceFramework(name), module(std::move(module)), system(system) {
28 auto& kernel = system.Kernel(); 28 auto& kernel = system.Kernel();
29 nfc_tag_load = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic, 29 nfc_tag_load = Kernel::WritableEvent::CreateEventPair(kernel, "IUser:NFCTagDetected");
30 "IUser:NFCTagDetected");
31} 30}
32 31
33Module::Interface::~Interface() = default; 32Module::Interface::~Interface() = default;
@@ -66,10 +65,9 @@ public:
66 RegisterHandlers(functions); 65 RegisterHandlers(functions);
67 66
68 auto& kernel = system.Kernel(); 67 auto& kernel = system.Kernel();
69 deactivate_event = Kernel::WritableEvent::CreateEventPair( 68 deactivate_event = Kernel::WritableEvent::CreateEventPair(kernel, "IUser:DeactivateEvent");
70 kernel, Kernel::ResetType::Automatic, "IUser:DeactivateEvent"); 69 availability_change_event =
71 availability_change_event = Kernel::WritableEvent::CreateEventPair( 70 Kernel::WritableEvent::CreateEventPair(kernel, "IUser:AvailabilityChangeEvent");
72 kernel, Kernel::ResetType::Automatic, "IUser:AvailabilityChangeEvent");
73 } 71 }
74 72
75private: 73private:
diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp
index 756a2af57..01d557c7a 100644
--- a/src/core/hle/service/nifm/nifm.cpp
+++ b/src/core/hle/service/nifm/nifm.cpp
@@ -69,10 +69,8 @@ public:
69 RegisterHandlers(functions); 69 RegisterHandlers(functions);
70 70
71 auto& kernel = system.Kernel(); 71 auto& kernel = system.Kernel();
72 event1 = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic, 72 event1 = Kernel::WritableEvent::CreateEventPair(kernel, "IRequest:Event1");
73 "IRequest:Event1"); 73 event2 = Kernel::WritableEvent::CreateEventPair(kernel, "IRequest:Event2");
74 event2 = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic,
75 "IRequest:Event2");
76 } 74 }
77 75
78private: 76private:
diff --git a/src/core/hle/service/nim/nim.cpp b/src/core/hle/service/nim/nim.cpp
index 75d414952..7d6cf2070 100644
--- a/src/core/hle/service/nim/nim.cpp
+++ b/src/core/hle/service/nim/nim.cpp
@@ -141,8 +141,7 @@ public:
141 141
142 auto& kernel = system.Kernel(); 142 auto& kernel = system.Kernel();
143 finished_event = Kernel::WritableEvent::CreateEventPair( 143 finished_event = Kernel::WritableEvent::CreateEventPair(
144 kernel, Kernel::ResetType::Automatic, 144 kernel, "IEnsureNetworkClockAvailabilityService:FinishEvent");
145 "IEnsureNetworkClockAvailabilityService:FinishEvent");
146 } 145 }
147 146
148private: 147private:
diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp
index 7bfb99e34..cc9cd3fd1 100644
--- a/src/core/hle/service/nvdrv/nvdrv.cpp
+++ b/src/core/hle/service/nvdrv/nvdrv.cpp
@@ -40,8 +40,7 @@ Module::Module(Core::System& system) {
40 auto& kernel = system.Kernel(); 40 auto& kernel = system.Kernel();
41 for (u32 i = 0; i < MaxNvEvents; i++) { 41 for (u32 i = 0; i < MaxNvEvents; i++) {
42 std::string event_label = fmt::format("NVDRV::NvEvent_{}", i); 42 std::string event_label = fmt::format("NVDRV::NvEvent_{}", i);
43 events_interface.events[i] = 43 events_interface.events[i] = Kernel::WritableEvent::CreateEventPair(kernel, event_label);
44 Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual, event_label);
45 events_interface.status[i] = EventState::Free; 44 events_interface.status[i] = EventState::Free;
46 events_interface.registered[i] = false; 45 events_interface.registered[i] = false;
47 } 46 }
diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp
index 55b68eb0c..1af11e80c 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.cpp
+++ b/src/core/hle/service/nvflinger/buffer_queue.cpp
@@ -16,8 +16,7 @@ namespace Service::NVFlinger {
16 16
17BufferQueue::BufferQueue(Kernel::KernelCore& kernel, u32 id, u64 layer_id) 17BufferQueue::BufferQueue(Kernel::KernelCore& kernel, u32 id, u64 layer_id)
18 : id(id), layer_id(layer_id) { 18 : id(id), layer_id(layer_id) {
19 buffer_wait_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual, 19 buffer_wait_event = Kernel::WritableEvent::CreateEventPair(kernel, "BufferQueue NativeHandle");
20 "BufferQueue NativeHandle");
21} 20}
22 21
23BufferQueue::~BufferQueue() = default; 22BufferQueue::~BufferQueue() = default;
diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp
index 006a6d9ff..07033fb98 100644
--- a/src/core/hle/service/vi/display/vi_display.cpp
+++ b/src/core/hle/service/vi/display/vi_display.cpp
@@ -17,8 +17,8 @@ namespace Service::VI {
17 17
18Display::Display(u64 id, std::string name, Core::System& system) : id{id}, name{std::move(name)} { 18Display::Display(u64 id, std::string name, Core::System& system) : id{id}, name{std::move(name)} {
19 auto& kernel = system.Kernel(); 19 auto& kernel = system.Kernel();
20 vsync_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual, 20 vsync_event =
21 fmt::format("Display VSync Event {}", id)); 21 Kernel::WritableEvent::CreateEventPair(kernel, fmt::format("Display VSync Event {}", id));
22} 22}
23 23
24Display::~Display() = default; 24Display::~Display() = default;
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index 199b30635..611cecc20 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -45,7 +45,7 @@ struct DisplayInfo {
45 45
46 /// Whether or not the display has a limited number of layers. 46 /// Whether or not the display has a limited number of layers.
47 u8 has_limited_layers{1}; 47 u8 has_limited_layers{1};
48 INSERT_PADDING_BYTES(7){}; 48 INSERT_PADDING_BYTES(7);
49 49
50 /// Indicates the total amount of layers supported by the display. 50 /// Indicates the total amount of layers supported by the display.
51 /// @note This is only valid if has_limited_layers is set. 51 /// @note This is only valid if has_limited_layers is set.
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index 2442ddfd6..4408b5001 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -12,6 +12,10 @@
12#include <utility> 12#include <utility>
13#include <vector> 13#include <vector>
14 14
15#include <boost/icl/interval_map.hpp>
16#include <boost/icl/interval_set.hpp>
17#include <boost/range/iterator_range.hpp>
18
15#include "common/alignment.h" 19#include "common/alignment.h"
16#include "common/common_types.h" 20#include "common/common_types.h"
17#include "core/core.h" 21#include "core/core.h"
@@ -30,7 +34,7 @@ public:
30 using BufferInfo = std::pair<const TBufferType*, u64>; 34 using BufferInfo = std::pair<const TBufferType*, u64>;
31 35
32 BufferInfo UploadMemory(GPUVAddr gpu_addr, std::size_t size, std::size_t alignment = 4, 36 BufferInfo UploadMemory(GPUVAddr gpu_addr, std::size_t size, std::size_t alignment = 4,
33 bool is_written = false) { 37 bool is_written = false, bool use_fast_cbuf = false) {
34 std::lock_guard lock{mutex}; 38 std::lock_guard lock{mutex};
35 39
36 auto& memory_manager = system.GPU().MemoryManager(); 40 auto& memory_manager = system.GPU().MemoryManager();
@@ -43,9 +47,13 @@ public:
43 // Cache management is a big overhead, so only cache entries with a given size. 47 // Cache management is a big overhead, so only cache entries with a given size.
44 // TODO: Figure out which size is the best for given games. 48 // TODO: Figure out which size is the best for given games.
45 constexpr std::size_t max_stream_size = 0x800; 49 constexpr std::size_t max_stream_size = 0x800;
46 if (size < max_stream_size) { 50 if (use_fast_cbuf || size < max_stream_size) {
47 if (!is_written && !IsRegionWritten(cache_addr, cache_addr + size - 1)) { 51 if (!is_written && !IsRegionWritten(cache_addr, cache_addr + size - 1)) {
48 return StreamBufferUpload(host_ptr, size, alignment); 52 if (use_fast_cbuf) {
53 return ConstBufferUpload(host_ptr, size);
54 } else {
55 return StreamBufferUpload(host_ptr, size, alignment);
56 }
49 } 57 }
50 } 58 }
51 59
@@ -152,6 +160,10 @@ protected:
152 virtual void CopyBlock(const TBuffer& src, const TBuffer& dst, std::size_t src_offset, 160 virtual void CopyBlock(const TBuffer& src, const TBuffer& dst, std::size_t src_offset,
153 std::size_t dst_offset, std::size_t size) = 0; 161 std::size_t dst_offset, std::size_t size) = 0;
154 162
163 virtual BufferInfo ConstBufferUpload(const void* raw_pointer, std::size_t size) {
164 return {};
165 }
166
155 /// Register an object into the cache 167 /// Register an object into the cache
156 void Register(const MapInterval& new_map, bool inherit_written = false) { 168 void Register(const MapInterval& new_map, bool inherit_written = false) {
157 const CacheAddr cache_ptr = new_map->GetStart(); 169 const CacheAddr cache_ptr = new_map->GetStart();
diff --git a/src/video_core/engines/fermi_2d.cpp b/src/video_core/engines/fermi_2d.cpp
index 7ff44f06d..85d308e26 100644
--- a/src/video_core/engines/fermi_2d.cpp
+++ b/src/video_core/engines/fermi_2d.cpp
@@ -28,6 +28,13 @@ void Fermi2D::CallMethod(const GPU::MethodCall& method_call) {
28 } 28 }
29} 29}
30 30
31std::pair<u32, u32> DelimitLine(u32 src_1, u32 src_2, u32 dst_1, u32 dst_2, u32 src_line) {
32 const u32 line_a = src_2 - src_1;
33 const u32 line_b = dst_2 - dst_1;
34 const u32 excess = std::max<s32>(0, line_a - src_line + src_1);
35 return {line_b - (excess * line_b) / line_a, excess};
36}
37
31void Fermi2D::HandleSurfaceCopy() { 38void Fermi2D::HandleSurfaceCopy() {
32 LOG_DEBUG(HW_GPU, "Requested a surface copy with operation {}", 39 LOG_DEBUG(HW_GPU, "Requested a surface copy with operation {}",
33 static_cast<u32>(regs.operation)); 40 static_cast<u32>(regs.operation));
@@ -47,10 +54,27 @@ void Fermi2D::HandleSurfaceCopy() {
47 src_blit_x2 = static_cast<u32>((regs.blit_src_x >> 32) + regs.blit_dst_width); 54 src_blit_x2 = static_cast<u32>((regs.blit_src_x >> 32) + regs.blit_dst_width);
48 src_blit_y2 = static_cast<u32>((regs.blit_src_y >> 32) + regs.blit_dst_height); 55 src_blit_y2 = static_cast<u32>((regs.blit_src_y >> 32) + regs.blit_dst_height);
49 } 56 }
57 u32 dst_blit_x2 = regs.blit_dst_x + regs.blit_dst_width;
58 u32 dst_blit_y2 = regs.blit_dst_y + regs.blit_dst_height;
59 const auto [new_dst_w, src_excess_x] =
60 DelimitLine(src_blit_x1, src_blit_x2, regs.blit_dst_x, dst_blit_x2, regs.src.width);
61 const auto [new_dst_h, src_excess_y] =
62 DelimitLine(src_blit_y1, src_blit_y2, regs.blit_dst_y, dst_blit_y2, regs.src.height);
63 dst_blit_x2 = new_dst_w + regs.blit_dst_x;
64 src_blit_x2 = src_blit_x2 - src_excess_x;
65 dst_blit_y2 = new_dst_h + regs.blit_dst_y;
66 src_blit_y2 = src_blit_y2 - src_excess_y;
67 const auto [new_src_w, dst_excess_x] =
68 DelimitLine(regs.blit_dst_x, dst_blit_x2, src_blit_x1, src_blit_x2, regs.dst.width);
69 const auto [new_src_h, dst_excess_y] =
70 DelimitLine(regs.blit_dst_y, dst_blit_y2, src_blit_y1, src_blit_y2, regs.dst.height);
71 src_blit_x2 = new_src_w + src_blit_x1;
72 dst_blit_x2 = dst_blit_x2 - dst_excess_x;
73 src_blit_y2 = new_src_h + src_blit_y1;
74 dst_blit_y2 = dst_blit_y2 - dst_excess_y;
50 const Common::Rectangle<u32> src_rect{src_blit_x1, src_blit_y1, src_blit_x2, src_blit_y2}; 75 const Common::Rectangle<u32> src_rect{src_blit_x1, src_blit_y1, src_blit_x2, src_blit_y2};
51 const Common::Rectangle<u32> dst_rect{regs.blit_dst_x, regs.blit_dst_y, 76 const Common::Rectangle<u32> dst_rect{regs.blit_dst_x, regs.blit_dst_y, dst_blit_x2,
52 regs.blit_dst_x + regs.blit_dst_width, 77 dst_blit_y2};
53 regs.blit_dst_y + regs.blit_dst_height};
54 Config copy_config; 78 Config copy_config;
55 copy_config.operation = regs.operation; 79 copy_config.operation = regs.operation;
56 copy_config.filter = regs.blit_control.filter; 80 copy_config.filter = regs.blit_control.filter;
diff --git a/src/video_core/engines/fermi_2d.h b/src/video_core/engines/fermi_2d.h
index 0901cf2fa..dba342c70 100644
--- a/src/video_core/engines/fermi_2d.h
+++ b/src/video_core/engines/fermi_2d.h
@@ -99,19 +99,19 @@ public:
99 99
100 union { 100 union {
101 struct { 101 struct {
102 INSERT_PADDING_WORDS(0x80); 102 INSERT_UNION_PADDING_WORDS(0x80);
103 103
104 Surface dst; 104 Surface dst;
105 105
106 INSERT_PADDING_WORDS(2); 106 INSERT_UNION_PADDING_WORDS(2);
107 107
108 Surface src; 108 Surface src;
109 109
110 INSERT_PADDING_WORDS(0x15); 110 INSERT_UNION_PADDING_WORDS(0x15);
111 111
112 Operation operation; 112 Operation operation;
113 113
114 INSERT_PADDING_WORDS(0x177); 114 INSERT_UNION_PADDING_WORDS(0x177);
115 115
116 union { 116 union {
117 u32 raw; 117 u32 raw;
@@ -119,7 +119,7 @@ public:
119 BitField<4, 1, Filter> filter; 119 BitField<4, 1, Filter> filter;
120 } blit_control; 120 } blit_control;
121 121
122 INSERT_PADDING_WORDS(0x8); 122 INSERT_UNION_PADDING_WORDS(0x8);
123 123
124 u32 blit_dst_x; 124 u32 blit_dst_x;
125 u32 blit_dst_y; 125 u32 blit_dst_y;
@@ -130,7 +130,7 @@ public:
130 u64 blit_src_x; 130 u64 blit_src_x;
131 u64 blit_src_y; 131 u64 blit_src_y;
132 132
133 INSERT_PADDING_WORDS(0x21); 133 INSERT_UNION_PADDING_WORDS(0x21);
134 }; 134 };
135 std::array<u32, NUM_REGS> reg_array; 135 std::array<u32, NUM_REGS> reg_array;
136 }; 136 };
diff --git a/src/video_core/engines/kepler_compute.h b/src/video_core/engines/kepler_compute.h
index b185c98c7..5259d92bd 100644
--- a/src/video_core/engines/kepler_compute.h
+++ b/src/video_core/engines/kepler_compute.h
@@ -51,7 +51,7 @@ public:
51 51
52 union { 52 union {
53 struct { 53 struct {
54 INSERT_PADDING_WORDS(0x60); 54 INSERT_UNION_PADDING_WORDS(0x60);
55 55
56 Upload::Registers upload; 56 Upload::Registers upload;
57 57
@@ -63,7 +63,7 @@ public:
63 63
64 u32 data_upload; 64 u32 data_upload;
65 65
66 INSERT_PADDING_WORDS(0x3F); 66 INSERT_UNION_PADDING_WORDS(0x3F);
67 67
68 struct { 68 struct {
69 u32 address; 69 u32 address;
@@ -72,11 +72,11 @@ public:
72 } 72 }
73 } launch_desc_loc; 73 } launch_desc_loc;
74 74
75 INSERT_PADDING_WORDS(0x1); 75 INSERT_UNION_PADDING_WORDS(0x1);
76 76
77 u32 launch; 77 u32 launch;
78 78
79 INSERT_PADDING_WORDS(0x4A7); 79 INSERT_UNION_PADDING_WORDS(0x4A7);
80 80
81 struct { 81 struct {
82 u32 address_high; 82 u32 address_high;
@@ -88,7 +88,7 @@ public:
88 } 88 }
89 } tsc; 89 } tsc;
90 90
91 INSERT_PADDING_WORDS(0x3); 91 INSERT_UNION_PADDING_WORDS(0x3);
92 92
93 struct { 93 struct {
94 u32 address_high; 94 u32 address_high;
@@ -100,7 +100,7 @@ public:
100 } 100 }
101 } tic; 101 } tic;
102 102
103 INSERT_PADDING_WORDS(0x22); 103 INSERT_UNION_PADDING_WORDS(0x22);
104 104
105 struct { 105 struct {
106 u32 address_high; 106 u32 address_high;
@@ -111,11 +111,11 @@ public:
111 } 111 }
112 } code_loc; 112 } code_loc;
113 113
114 INSERT_PADDING_WORDS(0x3FE); 114 INSERT_UNION_PADDING_WORDS(0x3FE);
115 115
116 u32 tex_cb_index; 116 u32 tex_cb_index;
117 117
118 INSERT_PADDING_WORDS(0x374); 118 INSERT_UNION_PADDING_WORDS(0x374);
119 }; 119 };
120 std::array<u32, NUM_REGS> reg_array; 120 std::array<u32, NUM_REGS> reg_array;
121 }; 121 };
@@ -179,7 +179,7 @@ public:
179 }; 179 };
180 180
181 INSERT_PADDING_WORDS(0x11); 181 INSERT_PADDING_WORDS(0x11);
182 } launch_description; 182 } launch_description{};
183 183
184 struct { 184 struct {
185 u32 write_offset = 0; 185 u32 write_offset = 0;
diff --git a/src/video_core/engines/kepler_memory.h b/src/video_core/engines/kepler_memory.h
index e0e25c321..396fb6e86 100644
--- a/src/video_core/engines/kepler_memory.h
+++ b/src/video_core/engines/kepler_memory.h
@@ -45,7 +45,7 @@ public:
45 45
46 union { 46 union {
47 struct { 47 struct {
48 INSERT_PADDING_WORDS(0x60); 48 INSERT_UNION_PADDING_WORDS(0x60);
49 49
50 Upload::Registers upload; 50 Upload::Registers upload;
51 51
@@ -57,7 +57,7 @@ public:
57 57
58 u32 data; 58 u32 data;
59 59
60 INSERT_PADDING_WORDS(0x11); 60 INSERT_UNION_PADDING_WORDS(0x11);
61 }; 61 };
62 std::array<u32, NUM_REGS> reg_array; 62 std::array<u32, NUM_REGS> reg_array;
63 }; 63 };
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index 8cc842684..1aa7c274f 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -496,7 +496,7 @@ public:
496 Equation equation_a; 496 Equation equation_a;
497 Factor factor_source_a; 497 Factor factor_source_a;
498 Factor factor_dest_a; 498 Factor factor_dest_a;
499 INSERT_PADDING_WORDS(1); 499 INSERT_UNION_PADDING_WORDS(1);
500 }; 500 };
501 501
502 struct RenderTargetConfig { 502 struct RenderTargetConfig {
@@ -517,7 +517,7 @@ public:
517 }; 517 };
518 u32 layer_stride; 518 u32 layer_stride;
519 u32 base_layer; 519 u32 base_layer;
520 INSERT_PADDING_WORDS(7); 520 INSERT_UNION_PADDING_WORDS(7);
521 521
522 GPUVAddr Address() const { 522 GPUVAddr Address() const {
523 return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | 523 return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
@@ -542,7 +542,7 @@ public:
542 f32 translate_x; 542 f32 translate_x;
543 f32 translate_y; 543 f32 translate_y;
544 f32 translate_z; 544 f32 translate_z;
545 INSERT_PADDING_WORDS(2); 545 INSERT_UNION_PADDING_WORDS(2);
546 546
547 Common::Rectangle<s32> GetRect() const { 547 Common::Rectangle<s32> GetRect() const {
548 return { 548 return {
@@ -606,7 +606,7 @@ public:
606 606
607 union { 607 union {
608 struct { 608 struct {
609 INSERT_PADDING_WORDS(0x45); 609 INSERT_UNION_PADDING_WORDS(0x45);
610 610
611 struct { 611 struct {
612 u32 upload_address; 612 u32 upload_address;
@@ -615,7 +615,7 @@ public:
615 u32 bind; 615 u32 bind;
616 } macros; 616 } macros;
617 617
618 INSERT_PADDING_WORDS(0x17); 618 INSERT_UNION_PADDING_WORDS(0x17);
619 619
620 Upload::Registers upload; 620 Upload::Registers upload;
621 struct { 621 struct {
@@ -626,7 +626,7 @@ public:
626 626
627 u32 data_upload; 627 u32 data_upload;
628 628
629 INSERT_PADDING_WORDS(0x44); 629 INSERT_UNION_PADDING_WORDS(0x44);
630 630
631 struct { 631 struct {
632 union { 632 union {
@@ -636,11 +636,11 @@ public:
636 }; 636 };
637 } sync_info; 637 } sync_info;
638 638
639 INSERT_PADDING_WORDS(0x11E); 639 INSERT_UNION_PADDING_WORDS(0x11E);
640 640
641 u32 tfb_enabled; 641 u32 tfb_enabled;
642 642
643 INSERT_PADDING_WORDS(0x2E); 643 INSERT_UNION_PADDING_WORDS(0x2E);
644 644
645 std::array<RenderTargetConfig, NumRenderTargets> rt; 645 std::array<RenderTargetConfig, NumRenderTargets> rt;
646 646
@@ -648,49 +648,49 @@ public:
648 648
649 std::array<ViewPort, NumViewports> viewports; 649 std::array<ViewPort, NumViewports> viewports;
650 650
651 INSERT_PADDING_WORDS(0x1D); 651 INSERT_UNION_PADDING_WORDS(0x1D);
652 652
653 struct { 653 struct {
654 u32 first; 654 u32 first;
655 u32 count; 655 u32 count;
656 } vertex_buffer; 656 } vertex_buffer;
657 657
658 INSERT_PADDING_WORDS(1); 658 INSERT_UNION_PADDING_WORDS(1);
659 659
660 float clear_color[4]; 660 float clear_color[4];
661 float clear_depth; 661 float clear_depth;
662 662
663 INSERT_PADDING_WORDS(0x3); 663 INSERT_UNION_PADDING_WORDS(0x3);
664 664
665 s32 clear_stencil; 665 s32 clear_stencil;
666 666
667 INSERT_PADDING_WORDS(0x7); 667 INSERT_UNION_PADDING_WORDS(0x7);
668 668
669 u32 polygon_offset_point_enable; 669 u32 polygon_offset_point_enable;
670 u32 polygon_offset_line_enable; 670 u32 polygon_offset_line_enable;
671 u32 polygon_offset_fill_enable; 671 u32 polygon_offset_fill_enable;
672 672
673 INSERT_PADDING_WORDS(0xD); 673 INSERT_UNION_PADDING_WORDS(0xD);
674 674
675 std::array<ScissorTest, NumViewports> scissor_test; 675 std::array<ScissorTest, NumViewports> scissor_test;
676 676
677 INSERT_PADDING_WORDS(0x15); 677 INSERT_UNION_PADDING_WORDS(0x15);
678 678
679 s32 stencil_back_func_ref; 679 s32 stencil_back_func_ref;
680 u32 stencil_back_mask; 680 u32 stencil_back_mask;
681 u32 stencil_back_func_mask; 681 u32 stencil_back_func_mask;
682 682
683 INSERT_PADDING_WORDS(0xC); 683 INSERT_UNION_PADDING_WORDS(0xC);
684 684
685 u32 color_mask_common; 685 u32 color_mask_common;
686 686
687 INSERT_PADDING_WORDS(0x6); 687 INSERT_UNION_PADDING_WORDS(0x6);
688 688
689 u32 rt_separate_frag_data; 689 u32 rt_separate_frag_data;
690 690
691 f32 depth_bounds[2]; 691 f32 depth_bounds[2];
692 692
693 INSERT_PADDING_WORDS(0xA); 693 INSERT_UNION_PADDING_WORDS(0xA);
694 694
695 struct { 695 struct {
696 u32 address_high; 696 u32 address_high;
@@ -710,7 +710,7 @@ public:
710 } 710 }
711 } zeta; 711 } zeta;
712 712
713 INSERT_PADDING_WORDS(0x41); 713 INSERT_UNION_PADDING_WORDS(0x41);
714 714
715 union { 715 union {
716 BitField<0, 4, u32> stencil; 716 BitField<0, 4, u32> stencil;
@@ -719,11 +719,11 @@ public:
719 BitField<12, 4, u32> viewport; 719 BitField<12, 4, u32> viewport;
720 } clear_flags; 720 } clear_flags;
721 721
722 INSERT_PADDING_WORDS(0x19); 722 INSERT_UNION_PADDING_WORDS(0x19);
723 723
724 std::array<VertexAttribute, NumVertexAttributes> vertex_attrib_format; 724 std::array<VertexAttribute, NumVertexAttributes> vertex_attrib_format;
725 725
726 INSERT_PADDING_WORDS(0xF); 726 INSERT_UNION_PADDING_WORDS(0xF);
727 727
728 struct { 728 struct {
729 union { 729 union {
@@ -746,16 +746,16 @@ public:
746 } 746 }
747 } rt_control; 747 } rt_control;
748 748
749 INSERT_PADDING_WORDS(0x2); 749 INSERT_UNION_PADDING_WORDS(0x2);
750 750
751 u32 zeta_width; 751 u32 zeta_width;
752 u32 zeta_height; 752 u32 zeta_height;
753 753
754 INSERT_PADDING_WORDS(0x27); 754 INSERT_UNION_PADDING_WORDS(0x27);
755 755
756 u32 depth_test_enable; 756 u32 depth_test_enable;
757 757
758 INSERT_PADDING_WORDS(0x5); 758 INSERT_UNION_PADDING_WORDS(0x5);
759 759
760 u32 independent_blend_enable; 760 u32 independent_blend_enable;
761 761
@@ -763,7 +763,7 @@ public:
763 763
764 u32 alpha_test_enabled; 764 u32 alpha_test_enabled;
765 765
766 INSERT_PADDING_WORDS(0x6); 766 INSERT_UNION_PADDING_WORDS(0x6);
767 767
768 u32 d3d_cull_mode; 768 u32 d3d_cull_mode;
769 769
@@ -777,7 +777,7 @@ public:
777 float b; 777 float b;
778 float a; 778 float a;
779 } blend_color; 779 } blend_color;
780 INSERT_PADDING_WORDS(0x4); 780 INSERT_UNION_PADDING_WORDS(0x4);
781 781
782 struct { 782 struct {
783 u32 separate_alpha; 783 u32 separate_alpha;
@@ -786,7 +786,7 @@ public:
786 Blend::Factor factor_dest_rgb; 786 Blend::Factor factor_dest_rgb;
787 Blend::Equation equation_a; 787 Blend::Equation equation_a;
788 Blend::Factor factor_source_a; 788 Blend::Factor factor_source_a;
789 INSERT_PADDING_WORDS(1); 789 INSERT_UNION_PADDING_WORDS(1);
790 Blend::Factor factor_dest_a; 790 Blend::Factor factor_dest_a;
791 791
792 u32 enable_common; 792 u32 enable_common;
@@ -802,7 +802,7 @@ public:
802 u32 stencil_front_func_mask; 802 u32 stencil_front_func_mask;
803 u32 stencil_front_mask; 803 u32 stencil_front_mask;
804 804
805 INSERT_PADDING_WORDS(0x2); 805 INSERT_UNION_PADDING_WORDS(0x2);
806 806
807 u32 frag_color_clamp; 807 u32 frag_color_clamp;
808 808
@@ -811,12 +811,12 @@ public:
811 BitField<4, 1, u32> triangle_rast_flip; 811 BitField<4, 1, u32> triangle_rast_flip;
812 } screen_y_control; 812 } screen_y_control;
813 813
814 INSERT_PADDING_WORDS(0x21); 814 INSERT_UNION_PADDING_WORDS(0x21);
815 815
816 u32 vb_element_base; 816 u32 vb_element_base;
817 u32 vb_base_instance; 817 u32 vb_base_instance;
818 818
819 INSERT_PADDING_WORDS(0x35); 819 INSERT_UNION_PADDING_WORDS(0x35);
820 820
821 union { 821 union {
822 BitField<0, 1, u32> c0; 822 BitField<0, 1, u32> c0;
@@ -829,11 +829,11 @@ public:
829 BitField<7, 1, u32> c7; 829 BitField<7, 1, u32> c7;
830 } clip_distance_enabled; 830 } clip_distance_enabled;
831 831
832 INSERT_PADDING_WORDS(0x1); 832 INSERT_UNION_PADDING_WORDS(0x1);
833 833
834 float point_size; 834 float point_size;
835 835
836 INSERT_PADDING_WORDS(0x7); 836 INSERT_UNION_PADDING_WORDS(0x7);
837 837
838 u32 zeta_enable; 838 u32 zeta_enable;
839 839
@@ -842,7 +842,7 @@ public:
842 BitField<4, 1, u32> alpha_to_one; 842 BitField<4, 1, u32> alpha_to_one;
843 } multisample_control; 843 } multisample_control;
844 844
845 INSERT_PADDING_WORDS(0x4); 845 INSERT_UNION_PADDING_WORDS(0x4);
846 846
847 struct { 847 struct {
848 u32 address_high; 848 u32 address_high;
@@ -866,11 +866,11 @@ public:
866 } 866 }
867 } tsc; 867 } tsc;
868 868
869 INSERT_PADDING_WORDS(0x1); 869 INSERT_UNION_PADDING_WORDS(0x1);
870 870
871 float polygon_offset_factor; 871 float polygon_offset_factor;
872 872
873 INSERT_PADDING_WORDS(0x1); 873 INSERT_UNION_PADDING_WORDS(0x1);
874 874
875 struct { 875 struct {
876 u32 tic_address_high; 876 u32 tic_address_high;
@@ -883,7 +883,7 @@ public:
883 } 883 }
884 } tic; 884 } tic;
885 885
886 INSERT_PADDING_WORDS(0x5); 886 INSERT_UNION_PADDING_WORDS(0x5);
887 887
888 u32 stencil_two_side_enable; 888 u32 stencil_two_side_enable;
889 StencilOp stencil_back_op_fail; 889 StencilOp stencil_back_op_fail;
@@ -891,13 +891,13 @@ public:
891 StencilOp stencil_back_op_zpass; 891 StencilOp stencil_back_op_zpass;
892 ComparisonOp stencil_back_func_func; 892 ComparisonOp stencil_back_func_func;
893 893
894 INSERT_PADDING_WORDS(0x4); 894 INSERT_UNION_PADDING_WORDS(0x4);
895 895
896 u32 framebuffer_srgb; 896 u32 framebuffer_srgb;
897 897
898 float polygon_offset_units; 898 float polygon_offset_units;
899 899
900 INSERT_PADDING_WORDS(0x11); 900 INSERT_UNION_PADDING_WORDS(0x11);
901 901
902 union { 902 union {
903 BitField<2, 1, u32> coord_origin; 903 BitField<2, 1, u32> coord_origin;
@@ -913,7 +913,7 @@ public:
913 (static_cast<GPUVAddr>(code_address_high) << 32) | code_address_low); 913 (static_cast<GPUVAddr>(code_address_high) << 32) | code_address_low);
914 } 914 }
915 } code_address; 915 } code_address;
916 INSERT_PADDING_WORDS(1); 916 INSERT_UNION_PADDING_WORDS(1);
917 917
918 struct { 918 struct {
919 u32 vertex_end_gl; 919 u32 vertex_end_gl;
@@ -925,14 +925,14 @@ public:
925 }; 925 };
926 } draw; 926 } draw;
927 927
928 INSERT_PADDING_WORDS(0xA); 928 INSERT_UNION_PADDING_WORDS(0xA);
929 929
930 struct { 930 struct {
931 u32 enabled; 931 u32 enabled;
932 u32 index; 932 u32 index;
933 } primitive_restart; 933 } primitive_restart;
934 934
935 INSERT_PADDING_WORDS(0x5F); 935 INSERT_UNION_PADDING_WORDS(0x5F);
936 936
937 struct { 937 struct {
938 u32 start_addr_high; 938 u32 start_addr_high;
@@ -973,9 +973,9 @@ public:
973 } 973 }
974 } index_array; 974 } index_array;
975 975
976 INSERT_PADDING_WORDS(0x7); 976 INSERT_UNION_PADDING_WORDS(0x7);
977 977
978 INSERT_PADDING_WORDS(0x1F); 978 INSERT_UNION_PADDING_WORDS(0x1F);
979 979
980 float polygon_offset_clamp; 980 float polygon_offset_clamp;
981 981
@@ -989,17 +989,17 @@ public:
989 } 989 }
990 } instanced_arrays; 990 } instanced_arrays;
991 991
992 INSERT_PADDING_WORDS(0x6); 992 INSERT_UNION_PADDING_WORDS(0x6);
993 993
994 Cull cull; 994 Cull cull;
995 995
996 u32 pixel_center_integer; 996 u32 pixel_center_integer;
997 997
998 INSERT_PADDING_WORDS(0x1); 998 INSERT_UNION_PADDING_WORDS(0x1);
999 999
1000 u32 viewport_transform_enabled; 1000 u32 viewport_transform_enabled;
1001 1001
1002 INSERT_PADDING_WORDS(0x3); 1002 INSERT_UNION_PADDING_WORDS(0x3);
1003 1003
1004 union { 1004 union {
1005 BitField<0, 1, u32> depth_range_0_1; 1005 BitField<0, 1, u32> depth_range_0_1;
@@ -1007,13 +1007,13 @@ public:
1007 BitField<4, 1, u32> depth_clamp_far; 1007 BitField<4, 1, u32> depth_clamp_far;
1008 } view_volume_clip_control; 1008 } view_volume_clip_control;
1009 1009
1010 INSERT_PADDING_WORDS(0x21); 1010 INSERT_UNION_PADDING_WORDS(0x21);
1011 struct { 1011 struct {
1012 u32 enable; 1012 u32 enable;
1013 LogicOperation operation; 1013 LogicOperation operation;
1014 } logic_op; 1014 } logic_op;
1015 1015
1016 INSERT_PADDING_WORDS(0x1); 1016 INSERT_UNION_PADDING_WORDS(0x1);
1017 1017
1018 union { 1018 union {
1019 u32 raw; 1019 u32 raw;
@@ -1026,9 +1026,9 @@ public:
1026 BitField<6, 4, u32> RT; 1026 BitField<6, 4, u32> RT;
1027 BitField<10, 11, u32> layer; 1027 BitField<10, 11, u32> layer;
1028 } clear_buffers; 1028 } clear_buffers;
1029 INSERT_PADDING_WORDS(0xB); 1029 INSERT_UNION_PADDING_WORDS(0xB);
1030 std::array<ColorMask, NumRenderTargets> color_mask; 1030 std::array<ColorMask, NumRenderTargets> color_mask;
1031 INSERT_PADDING_WORDS(0x38); 1031 INSERT_UNION_PADDING_WORDS(0x38);
1032 1032
1033 struct { 1033 struct {
1034 u32 query_address_high; 1034 u32 query_address_high;
@@ -1050,7 +1050,7 @@ public:
1050 } 1050 }
1051 } query; 1051 } query;
1052 1052
1053 INSERT_PADDING_WORDS(0x3C); 1053 INSERT_UNION_PADDING_WORDS(0x3C);
1054 1054
1055 struct { 1055 struct {
1056 union { 1056 union {
@@ -1090,10 +1090,10 @@ public:
1090 BitField<4, 4, ShaderProgram> program; 1090 BitField<4, 4, ShaderProgram> program;
1091 }; 1091 };
1092 u32 offset; 1092 u32 offset;
1093 INSERT_PADDING_WORDS(14); 1093 INSERT_UNION_PADDING_WORDS(14);
1094 } shader_config[MaxShaderProgram]; 1094 } shader_config[MaxShaderProgram];
1095 1095
1096 INSERT_PADDING_WORDS(0x60); 1096 INSERT_UNION_PADDING_WORDS(0x60);
1097 1097
1098 u32 firmware[0x20]; 1098 u32 firmware[0x20];
1099 1099
@@ -1110,7 +1110,7 @@ public:
1110 } 1110 }
1111 } const_buffer; 1111 } const_buffer;
1112 1112
1113 INSERT_PADDING_WORDS(0x10); 1113 INSERT_UNION_PADDING_WORDS(0x10);
1114 1114
1115 struct { 1115 struct {
1116 union { 1116 union {
@@ -1118,14 +1118,14 @@ public:
1118 BitField<0, 1, u32> valid; 1118 BitField<0, 1, u32> valid;
1119 BitField<4, 5, u32> index; 1119 BitField<4, 5, u32> index;
1120 }; 1120 };
1121 INSERT_PADDING_WORDS(7); 1121 INSERT_UNION_PADDING_WORDS(7);
1122 } cb_bind[MaxShaderStage]; 1122 } cb_bind[MaxShaderStage];
1123 1123
1124 INSERT_PADDING_WORDS(0x56); 1124 INSERT_UNION_PADDING_WORDS(0x56);
1125 1125
1126 u32 tex_cb_index; 1126 u32 tex_cb_index;
1127 1127
1128 INSERT_PADDING_WORDS(0x395); 1128 INSERT_UNION_PADDING_WORDS(0x395);
1129 1129
1130 struct { 1130 struct {
1131 /// Compressed address of a buffer that holds information about bound SSBOs. 1131 /// Compressed address of a buffer that holds information about bound SSBOs.
@@ -1137,14 +1137,14 @@ public:
1137 } 1137 }
1138 } ssbo_info; 1138 } ssbo_info;
1139 1139
1140 INSERT_PADDING_WORDS(0x11); 1140 INSERT_UNION_PADDING_WORDS(0x11);
1141 1141
1142 struct { 1142 struct {
1143 u32 address[MaxShaderStage]; 1143 u32 address[MaxShaderStage];
1144 u32 size[MaxShaderStage]; 1144 u32 size[MaxShaderStage];
1145 } tex_info_buffers; 1145 } tex_info_buffers;
1146 1146
1147 INSERT_PADDING_WORDS(0xCC); 1147 INSERT_UNION_PADDING_WORDS(0xCC);
1148 }; 1148 };
1149 std::array<u32, NUM_REGS> reg_array; 1149 std::array<u32, NUM_REGS> reg_array;
1150 }; 1150 };
diff --git a/src/video_core/engines/maxwell_dma.h b/src/video_core/engines/maxwell_dma.h
index 93808a9bb..4f40d1d1f 100644
--- a/src/video_core/engines/maxwell_dma.h
+++ b/src/video_core/engines/maxwell_dma.h
@@ -94,7 +94,7 @@ public:
94 94
95 union { 95 union {
96 struct { 96 struct {
97 INSERT_PADDING_WORDS(0xC0); 97 INSERT_UNION_PADDING_WORDS(0xC0);
98 98
99 struct { 99 struct {
100 union { 100 union {
@@ -112,7 +112,7 @@ public:
112 }; 112 };
113 } exec; 113 } exec;
114 114
115 INSERT_PADDING_WORDS(0x3F); 115 INSERT_UNION_PADDING_WORDS(0x3F);
116 116
117 struct { 117 struct {
118 u32 address_high; 118 u32 address_high;
@@ -139,7 +139,7 @@ public:
139 u32 x_count; 139 u32 x_count;
140 u32 y_count; 140 u32 y_count;
141 141
142 INSERT_PADDING_WORDS(0xB8); 142 INSERT_UNION_PADDING_WORDS(0xB8);
143 143
144 u32 const0; 144 u32 const0;
145 u32 const1; 145 u32 const1;
@@ -162,11 +162,11 @@ public:
162 162
163 Parameters dst_params; 163 Parameters dst_params;
164 164
165 INSERT_PADDING_WORDS(1); 165 INSERT_UNION_PADDING_WORDS(1);
166 166
167 Parameters src_params; 167 Parameters src_params;
168 168
169 INSERT_PADDING_WORDS(0x13); 169 INSERT_UNION_PADDING_WORDS(0x13);
170 }; 170 };
171 std::array<u32, NUM_REGS> reg_array; 171 std::array<u32, NUM_REGS> reg_array;
172 }; 172 };
diff --git a/src/video_core/engines/shader_header.h b/src/video_core/engines/shader_header.h
index e86a7f04a..bc80661d8 100644
--- a/src/video_core/engines/shader_header.h
+++ b/src/video_core/engines/shader_header.h
@@ -38,37 +38,37 @@ struct Header {
38 BitField<26, 1, u32> does_load_or_store; 38 BitField<26, 1, u32> does_load_or_store;
39 BitField<27, 1, u32> does_fp64; 39 BitField<27, 1, u32> does_fp64;
40 BitField<28, 4, u32> stream_out_mask; 40 BitField<28, 4, u32> stream_out_mask;
41 } common0; 41 } common0{};
42 42
43 union { 43 union {
44 BitField<0, 24, u32> shader_local_memory_low_size; 44 BitField<0, 24, u32> shader_local_memory_low_size;
45 BitField<24, 8, u32> per_patch_attribute_count; 45 BitField<24, 8, u32> per_patch_attribute_count;
46 } common1; 46 } common1{};
47 47
48 union { 48 union {
49 BitField<0, 24, u32> shader_local_memory_high_size; 49 BitField<0, 24, u32> shader_local_memory_high_size;
50 BitField<24, 8, u32> threads_per_input_primitive; 50 BitField<24, 8, u32> threads_per_input_primitive;
51 } common2; 51 } common2{};
52 52
53 union { 53 union {
54 BitField<0, 24, u32> shader_local_memory_crs_size; 54 BitField<0, 24, u32> shader_local_memory_crs_size;
55 BitField<24, 4, OutputTopology> output_topology; 55 BitField<24, 4, OutputTopology> output_topology;
56 BitField<28, 4, u32> reserved; 56 BitField<28, 4, u32> reserved;
57 } common3; 57 } common3{};
58 58
59 union { 59 union {
60 BitField<0, 12, u32> max_output_vertices; 60 BitField<0, 12, u32> max_output_vertices;
61 BitField<12, 8, u32> store_req_start; // NOTE: not used by geometry shaders. 61 BitField<12, 8, u32> store_req_start; // NOTE: not used by geometry shaders.
62 BitField<24, 4, u32> reserved; 62 BitField<24, 4, u32> reserved;
63 BitField<12, 8, u32> store_req_end; // NOTE: not used by geometry shaders. 63 BitField<12, 8, u32> store_req_end; // NOTE: not used by geometry shaders.
64 } common4; 64 } common4{};
65 65
66 union { 66 union {
67 struct { 67 struct {
68 INSERT_PADDING_BYTES(3); // ImapSystemValuesA 68 INSERT_UNION_PADDING_BYTES(3); // ImapSystemValuesA
69 INSERT_PADDING_BYTES(1); // ImapSystemValuesB 69 INSERT_UNION_PADDING_BYTES(1); // ImapSystemValuesB
70 INSERT_PADDING_BYTES(16); // ImapGenericVector[32] 70 INSERT_UNION_PADDING_BYTES(16); // ImapGenericVector[32]
71 INSERT_PADDING_BYTES(2); // ImapColor 71 INSERT_UNION_PADDING_BYTES(2); // ImapColor
72 union { 72 union {
73 BitField<0, 8, u16> clip_distances; 73 BitField<0, 8, u16> clip_distances;
74 BitField<8, 1, u16> point_sprite_s; 74 BitField<8, 1, u16> point_sprite_s;
@@ -79,20 +79,20 @@ struct Header {
79 BitField<14, 1, u16> instance_id; 79 BitField<14, 1, u16> instance_id;
80 BitField<15, 1, u16> vertex_id; 80 BitField<15, 1, u16> vertex_id;
81 }; 81 };
82 INSERT_PADDING_BYTES(5); // ImapFixedFncTexture[10] 82 INSERT_UNION_PADDING_BYTES(5); // ImapFixedFncTexture[10]
83 INSERT_PADDING_BYTES(1); // ImapReserved 83 INSERT_UNION_PADDING_BYTES(1); // ImapReserved
84 INSERT_PADDING_BYTES(3); // OmapSystemValuesA 84 INSERT_UNION_PADDING_BYTES(3); // OmapSystemValuesA
85 INSERT_PADDING_BYTES(1); // OmapSystemValuesB 85 INSERT_UNION_PADDING_BYTES(1); // OmapSystemValuesB
86 INSERT_PADDING_BYTES(16); // OmapGenericVector[32] 86 INSERT_UNION_PADDING_BYTES(16); // OmapGenericVector[32]
87 INSERT_PADDING_BYTES(2); // OmapColor 87 INSERT_UNION_PADDING_BYTES(2); // OmapColor
88 INSERT_PADDING_BYTES(2); // OmapSystemValuesC 88 INSERT_UNION_PADDING_BYTES(2); // OmapSystemValuesC
89 INSERT_PADDING_BYTES(5); // OmapFixedFncTexture[10] 89 INSERT_UNION_PADDING_BYTES(5); // OmapFixedFncTexture[10]
90 INSERT_PADDING_BYTES(1); // OmapReserved 90 INSERT_UNION_PADDING_BYTES(1); // OmapReserved
91 } vtg; 91 } vtg;
92 92
93 struct { 93 struct {
94 INSERT_PADDING_BYTES(3); // ImapSystemValuesA 94 INSERT_UNION_PADDING_BYTES(3); // ImapSystemValuesA
95 INSERT_PADDING_BYTES(1); // ImapSystemValuesB 95 INSERT_UNION_PADDING_BYTES(1); // ImapSystemValuesB
96 union { 96 union {
97 BitField<0, 2, AttributeUse> x; 97 BitField<0, 2, AttributeUse> x;
98 BitField<2, 2, AttributeUse> y; 98 BitField<2, 2, AttributeUse> y;
@@ -100,10 +100,10 @@ struct Header {
100 BitField<6, 2, AttributeUse> z; 100 BitField<6, 2, AttributeUse> z;
101 u8 raw; 101 u8 raw;
102 } imap_generic_vector[32]; 102 } imap_generic_vector[32];
103 INSERT_PADDING_BYTES(2); // ImapColor 103 INSERT_UNION_PADDING_BYTES(2); // ImapColor
104 INSERT_PADDING_BYTES(2); // ImapSystemValuesC 104 INSERT_UNION_PADDING_BYTES(2); // ImapSystemValuesC
105 INSERT_PADDING_BYTES(10); // ImapFixedFncTexture[10] 105 INSERT_UNION_PADDING_BYTES(10); // ImapFixedFncTexture[10]
106 INSERT_PADDING_BYTES(2); // ImapReserved 106 INSERT_UNION_PADDING_BYTES(2); // ImapReserved
107 struct { 107 struct {
108 u32 target; 108 u32 target;
109 union { 109 union {
@@ -139,6 +139,8 @@ struct Header {
139 return result; 139 return result;
140 } 140 }
141 } ps; 141 } ps;
142
143 std::array<u32, 0xF> raw{};
142 }; 144 };
143 145
144 u64 GetLocalMemorySize() const { 146 u64 GetLocalMemorySize() const {
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h
index dbca19f35..ecc338ae9 100644
--- a/src/video_core/gpu.h
+++ b/src/video_core/gpu.h
@@ -207,7 +207,7 @@ public:
207 207
208 union { 208 union {
209 struct { 209 struct {
210 INSERT_PADDING_WORDS(0x4); 210 INSERT_UNION_PADDING_WORDS(0x4);
211 struct { 211 struct {
212 u32 address_high; 212 u32 address_high;
213 u32 address_low; 213 u32 address_low;
@@ -220,12 +220,12 @@ public:
220 220
221 u32 semaphore_sequence; 221 u32 semaphore_sequence;
222 u32 semaphore_trigger; 222 u32 semaphore_trigger;
223 INSERT_PADDING_WORDS(0xC); 223 INSERT_UNION_PADDING_WORDS(0xC);
224 224
225 // The puser and the puller share the reference counter, the pusher only has read 225 // The puser and the puller share the reference counter, the pusher only has read
226 // access 226 // access
227 u32 reference_count; 227 u32 reference_count;
228 INSERT_PADDING_WORDS(0x5); 228 INSERT_UNION_PADDING_WORDS(0x5);
229 229
230 u32 semaphore_acquire; 230 u32 semaphore_acquire;
231 u32 semaphore_release; 231 u32 semaphore_release;
@@ -234,7 +234,7 @@ public:
234 BitField<4, 4, u32> operation; 234 BitField<4, 4, u32> operation;
235 BitField<8, 8, u32> id; 235 BitField<8, 8, u32> id;
236 } fence_action; 236 } fence_action;
237 INSERT_PADDING_WORDS(0xE2); 237 INSERT_UNION_PADDING_WORDS(0xE2);
238 238
239 // Puller state 239 // Puller state
240 u32 acquire_mode; 240 u32 acquire_mode;
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.cpp b/src/video_core/renderer_opengl/gl_buffer_cache.cpp
index f8a807c84..0375fca17 100644
--- a/src/video_core/renderer_opengl/gl_buffer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_buffer_cache.cpp
@@ -8,13 +8,17 @@
8 8
9#include "common/assert.h" 9#include "common/assert.h"
10#include "common/microprofile.h" 10#include "common/microprofile.h"
11#include "video_core/engines/maxwell_3d.h"
11#include "video_core/rasterizer_interface.h" 12#include "video_core/rasterizer_interface.h"
12#include "video_core/renderer_opengl/gl_buffer_cache.h" 13#include "video_core/renderer_opengl/gl_buffer_cache.h"
14#include "video_core/renderer_opengl/gl_device.h"
13#include "video_core/renderer_opengl/gl_rasterizer.h" 15#include "video_core/renderer_opengl/gl_rasterizer.h"
14#include "video_core/renderer_opengl/gl_resource_manager.h" 16#include "video_core/renderer_opengl/gl_resource_manager.h"
15 17
16namespace OpenGL { 18namespace OpenGL {
17 19
20using Maxwell = Tegra::Engines::Maxwell3D::Regs;
21
18MICROPROFILE_DEFINE(OpenGL_Buffer_Download, "OpenGL", "Buffer Download", MP_RGB(192, 192, 128)); 22MICROPROFILE_DEFINE(OpenGL_Buffer_Download, "OpenGL", "Buffer Download", MP_RGB(192, 192, 128));
19 23
20CachedBufferBlock::CachedBufferBlock(CacheAddr cache_addr, const std::size_t size) 24CachedBufferBlock::CachedBufferBlock(CacheAddr cache_addr, const std::size_t size)
@@ -26,11 +30,22 @@ CachedBufferBlock::CachedBufferBlock(CacheAddr cache_addr, const std::size_t siz
26CachedBufferBlock::~CachedBufferBlock() = default; 30CachedBufferBlock::~CachedBufferBlock() = default;
27 31
28OGLBufferCache::OGLBufferCache(RasterizerOpenGL& rasterizer, Core::System& system, 32OGLBufferCache::OGLBufferCache(RasterizerOpenGL& rasterizer, Core::System& system,
29 std::size_t stream_size) 33 const Device& device, std::size_t stream_size)
30 : VideoCommon::BufferCache<Buffer, GLuint, OGLStreamBuffer>{ 34 : GenericBufferCache{rasterizer, system, std::make_unique<OGLStreamBuffer>(stream_size, true)} {
31 rasterizer, system, std::make_unique<OGLStreamBuffer>(stream_size, true)} {} 35 if (!device.HasFastBufferSubData()) {
36 return;
37 }
38
39 static constexpr auto size = static_cast<GLsizeiptr>(Maxwell::MaxConstBufferSize);
40 glCreateBuffers(static_cast<GLsizei>(std::size(cbufs)), std::data(cbufs));
41 for (const GLuint cbuf : cbufs) {
42 glNamedBufferData(cbuf, size, nullptr, GL_STREAM_DRAW);
43 }
44}
32 45
33OGLBufferCache::~OGLBufferCache() = default; 46OGLBufferCache::~OGLBufferCache() {
47 glDeleteBuffers(static_cast<GLsizei>(std::size(cbufs)), std::data(cbufs));
48}
34 49
35Buffer OGLBufferCache::CreateBlock(CacheAddr cache_addr, std::size_t size) { 50Buffer OGLBufferCache::CreateBlock(CacheAddr cache_addr, std::size_t size) {
36 return std::make_shared<CachedBufferBlock>(cache_addr, size); 51 return std::make_shared<CachedBufferBlock>(cache_addr, size);
@@ -69,4 +84,12 @@ void OGLBufferCache::CopyBlock(const Buffer& src, const Buffer& dst, std::size_t
69 static_cast<GLsizeiptr>(size)); 84 static_cast<GLsizeiptr>(size));
70} 85}
71 86
87OGLBufferCache::BufferInfo OGLBufferCache::ConstBufferUpload(const void* raw_pointer,
88 std::size_t size) {
89 DEBUG_ASSERT(cbuf_cursor < std::size(cbufs));
90 const GLuint& cbuf = cbufs[cbuf_cursor++];
91 glNamedBufferSubData(cbuf, 0, static_cast<GLsizeiptr>(size), raw_pointer);
92 return {&cbuf, 0};
93}
94
72} // namespace OpenGL 95} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.h b/src/video_core/renderer_opengl/gl_buffer_cache.h
index 022e7bfa9..8c7145443 100644
--- a/src/video_core/renderer_opengl/gl_buffer_cache.h
+++ b/src/video_core/renderer_opengl/gl_buffer_cache.h
@@ -4,10 +4,12 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <array>
7#include <memory> 8#include <memory>
8 9
9#include "common/common_types.h" 10#include "common/common_types.h"
10#include "video_core/buffer_cache/buffer_cache.h" 11#include "video_core/buffer_cache/buffer_cache.h"
12#include "video_core/engines/maxwell_3d.h"
11#include "video_core/rasterizer_cache.h" 13#include "video_core/rasterizer_cache.h"
12#include "video_core/renderer_opengl/gl_resource_manager.h" 14#include "video_core/renderer_opengl/gl_resource_manager.h"
13#include "video_core/renderer_opengl/gl_stream_buffer.h" 15#include "video_core/renderer_opengl/gl_stream_buffer.h"
@@ -18,12 +20,14 @@ class System;
18 20
19namespace OpenGL { 21namespace OpenGL {
20 22
23class Device;
21class OGLStreamBuffer; 24class OGLStreamBuffer;
22class RasterizerOpenGL; 25class RasterizerOpenGL;
23 26
24class CachedBufferBlock; 27class CachedBufferBlock;
25 28
26using Buffer = std::shared_ptr<CachedBufferBlock>; 29using Buffer = std::shared_ptr<CachedBufferBlock>;
30using GenericBufferCache = VideoCommon::BufferCache<Buffer, GLuint, OGLStreamBuffer>;
27 31
28class CachedBufferBlock : public VideoCommon::BufferBlock { 32class CachedBufferBlock : public VideoCommon::BufferBlock {
29public: 33public:
@@ -38,14 +42,18 @@ private:
38 OGLBuffer gl_buffer{}; 42 OGLBuffer gl_buffer{};
39}; 43};
40 44
41class OGLBufferCache final : public VideoCommon::BufferCache<Buffer, GLuint, OGLStreamBuffer> { 45class OGLBufferCache final : public GenericBufferCache {
42public: 46public:
43 explicit OGLBufferCache(RasterizerOpenGL& rasterizer, Core::System& system, 47 explicit OGLBufferCache(RasterizerOpenGL& rasterizer, Core::System& system,
44 std::size_t stream_size); 48 const Device& device, std::size_t stream_size);
45 ~OGLBufferCache(); 49 ~OGLBufferCache();
46 50
47 const GLuint* GetEmptyBuffer(std::size_t) override; 51 const GLuint* GetEmptyBuffer(std::size_t) override;
48 52
53 void Acquire() noexcept {
54 cbuf_cursor = 0;
55 }
56
49protected: 57protected:
50 Buffer CreateBlock(CacheAddr cache_addr, std::size_t size) override; 58 Buffer CreateBlock(CacheAddr cache_addr, std::size_t size) override;
51 59
@@ -61,6 +69,14 @@ protected:
61 69
62 void CopyBlock(const Buffer& src, const Buffer& dst, std::size_t src_offset, 70 void CopyBlock(const Buffer& src, const Buffer& dst, std::size_t src_offset,
63 std::size_t dst_offset, std::size_t size) override; 71 std::size_t dst_offset, std::size_t size) override;
72
73 BufferInfo ConstBufferUpload(const void* raw_pointer, std::size_t size) override;
74
75private:
76 std::size_t cbuf_cursor = 0;
77 std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::MaxConstBuffers *
78 Tegra::Engines::Maxwell3D::Regs::MaxShaderProgram>
79 cbufs;
64}; 80};
65 81
66} // namespace OpenGL 82} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp
index 64de7e425..c65b24c69 100644
--- a/src/video_core/renderer_opengl/gl_device.cpp
+++ b/src/video_core/renderer_opengl/gl_device.cpp
@@ -51,8 +51,11 @@ bool HasExtension(const std::vector<std::string_view>& images, std::string_view
51} // Anonymous namespace 51} // Anonymous namespace
52 52
53Device::Device() { 53Device::Device() {
54 const std::string_view vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
54 const std::vector extensions = GetExtensions(); 55 const std::vector extensions = GetExtensions();
55 56
57 const bool is_nvidia = vendor == "NVIDIA Corporation";
58
56 uniform_buffer_alignment = GetInteger<std::size_t>(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT); 59 uniform_buffer_alignment = GetInteger<std::size_t>(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT);
57 shader_storage_alignment = GetInteger<std::size_t>(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT); 60 shader_storage_alignment = GetInteger<std::size_t>(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT);
58 max_vertex_attributes = GetInteger<u32>(GL_MAX_VERTEX_ATTRIBS); 61 max_vertex_attributes = GetInteger<u32>(GL_MAX_VERTEX_ATTRIBS);
@@ -64,6 +67,7 @@ Device::Device() {
64 has_variable_aoffi = TestVariableAoffi(); 67 has_variable_aoffi = TestVariableAoffi();
65 has_component_indexing_bug = TestComponentIndexingBug(); 68 has_component_indexing_bug = TestComponentIndexingBug();
66 has_precise_bug = TestPreciseBug(); 69 has_precise_bug = TestPreciseBug();
70 has_fast_buffer_sub_data = is_nvidia;
67 71
68 LOG_INFO(Render_OpenGL, "Renderer_VariableAOFFI: {}", has_variable_aoffi); 72 LOG_INFO(Render_OpenGL, "Renderer_VariableAOFFI: {}", has_variable_aoffi);
69 LOG_INFO(Render_OpenGL, "Renderer_ComponentIndexingBug: {}", has_component_indexing_bug); 73 LOG_INFO(Render_OpenGL, "Renderer_ComponentIndexingBug: {}", has_component_indexing_bug);
diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h
index bb273c3d6..bf35bd0b6 100644
--- a/src/video_core/renderer_opengl/gl_device.h
+++ b/src/video_core/renderer_opengl/gl_device.h
@@ -54,6 +54,10 @@ public:
54 return has_precise_bug; 54 return has_precise_bug;
55 } 55 }
56 56
57 bool HasFastBufferSubData() const {
58 return has_fast_buffer_sub_data;
59 }
60
57private: 61private:
58 static bool TestVariableAoffi(); 62 static bool TestVariableAoffi();
59 static bool TestComponentIndexingBug(); 63 static bool TestComponentIndexingBug();
@@ -69,6 +73,7 @@ private:
69 bool has_variable_aoffi{}; 73 bool has_variable_aoffi{};
70 bool has_component_indexing_bug{}; 74 bool has_component_indexing_bug{};
71 bool has_precise_bug{}; 75 bool has_precise_bug{};
76 bool has_fast_buffer_sub_data{};
72}; 77};
73 78
74} // namespace OpenGL 79} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 6a4d2c83a..e560d70d5 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -67,7 +67,7 @@ static std::size_t GetConstBufferSize(const Tegra::Engines::ConstBufferInfo& buf
67RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window, 67RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window,
68 ScreenInfo& info) 68 ScreenInfo& info)
69 : texture_cache{system, *this, device}, shader_cache{*this, system, emu_window, device}, 69 : texture_cache{system, *this, device}, shader_cache{*this, system, emu_window, device},
70 system{system}, screen_info{info}, buffer_cache{*this, system, STREAM_BUFFER_SIZE} { 70 system{system}, screen_info{info}, buffer_cache{*this, system, device, STREAM_BUFFER_SIZE} {
71 shader_program_manager = std::make_unique<GLShader::ProgramManager>(); 71 shader_program_manager = std::make_unique<GLShader::ProgramManager>();
72 state.draw.shader_program = 0; 72 state.draw.shader_program = 0;
73 state.Apply(); 73 state.Apply();
@@ -558,6 +558,8 @@ void RasterizerOpenGL::DrawPrelude() {
558 SyncPolygonOffset(); 558 SyncPolygonOffset();
559 SyncAlphaTest(); 559 SyncAlphaTest();
560 560
561 buffer_cache.Acquire();
562
561 // Draw the vertex batch 563 // Draw the vertex batch
562 const bool is_indexed = accelerate_draw == AccelDraw::Indexed; 564 const bool is_indexed = accelerate_draw == AccelDraw::Indexed;
563 565
@@ -879,7 +881,8 @@ void RasterizerOpenGL::SetupConstBuffer(const Tegra::Engines::ConstBufferInfo& b
879 const std::size_t size = Common::AlignUp(GetConstBufferSize(buffer, entry), sizeof(GLvec4)); 881 const std::size_t size = Common::AlignUp(GetConstBufferSize(buffer, entry), sizeof(GLvec4));
880 882
881 const auto alignment = device.GetUniformBufferAlignment(); 883 const auto alignment = device.GetUniformBufferAlignment();
882 const auto [cbuf, offset] = buffer_cache.UploadMemory(buffer.address, size, alignment); 884 const auto [cbuf, offset] = buffer_cache.UploadMemory(buffer.address, size, alignment, false,
885 device.HasFastBufferSubData());
883 bind_ubo_pushbuffer.Push(cbuf, offset, size); 886 bind_ubo_pushbuffer.Push(cbuf, offset, size);
884} 887}
885 888
@@ -935,10 +938,9 @@ TextureBufferUsage RasterizerOpenGL::SetupDrawTextures(Maxwell::ShaderStage stag
935 if (!entry.IsBindless()) { 938 if (!entry.IsBindless()) {
936 return maxwell3d.GetStageTexture(stage, entry.GetOffset()); 939 return maxwell3d.GetStageTexture(stage, entry.GetOffset());
937 } 940 }
938 const auto cbuf = entry.GetBindlessCBuf(); 941 const auto shader_type = static_cast<Tegra::Engines::ShaderType>(stage);
939 Tegra::Texture::TextureHandle tex_handle; 942 const Tegra::Texture::TextureHandle tex_handle =
940 Tegra::Engines::ShaderType shader_type = static_cast<Tegra::Engines::ShaderType>(stage); 943 maxwell3d.AccessConstBuffer32(shader_type, entry.GetBuffer(), entry.GetOffset());
941 tex_handle.raw = maxwell3d.AccessConstBuffer32(shader_type, cbuf.first, cbuf.second);
942 return maxwell3d.GetTextureInfo(tex_handle); 944 return maxwell3d.GetTextureInfo(tex_handle);
943 }(); 945 }();
944 946
@@ -966,10 +968,8 @@ TextureBufferUsage RasterizerOpenGL::SetupComputeTextures(const Shader& kernel)
966 if (!entry.IsBindless()) { 968 if (!entry.IsBindless()) {
967 return compute.GetTexture(entry.GetOffset()); 969 return compute.GetTexture(entry.GetOffset());
968 } 970 }
969 const auto cbuf = entry.GetBindlessCBuf(); 971 const Tegra::Texture::TextureHandle tex_handle = compute.AccessConstBuffer32(
970 Tegra::Texture::TextureHandle tex_handle; 972 Tegra::Engines::ShaderType::Compute, entry.GetBuffer(), entry.GetOffset());
971 tex_handle.raw = compute.AccessConstBuffer32(Tegra::Engines::ShaderType::Compute,
972 cbuf.first, cbuf.second);
973 return compute.GetTextureInfo(tex_handle); 973 return compute.GetTextureInfo(tex_handle);
974 }(); 974 }();
975 975
@@ -1012,10 +1012,8 @@ void RasterizerOpenGL::SetupComputeImages(const Shader& shader) {
1012 if (!entry.IsBindless()) { 1012 if (!entry.IsBindless()) {
1013 return compute.GetTexture(entry.GetOffset()).tic; 1013 return compute.GetTexture(entry.GetOffset()).tic;
1014 } 1014 }
1015 const auto cbuf = entry.GetBindlessCBuf(); 1015 const Tegra::Texture::TextureHandle tex_handle = compute.AccessConstBuffer32(
1016 Tegra::Texture::TextureHandle tex_handle; 1016 Tegra::Engines::ShaderType::Compute, entry.GetBuffer(), entry.GetOffset());
1017 tex_handle.raw = compute.AccessConstBuffer32(Tegra::Engines::ShaderType::Compute,
1018 cbuf.first, cbuf.second);
1019 return compute.GetTextureInfo(tex_handle).tic; 1017 return compute.GetTextureInfo(tex_handle).tic;
1020 }(); 1018 }();
1021 SetupImage(bindpoint, tic, entry); 1019 SetupImage(bindpoint, tic, entry);
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 8a514cb8a..0ce59a852 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -735,7 +735,7 @@ private:
735 735
736 void DeclareImages() { 736 void DeclareImages() {
737 const auto& images{ir.GetImages()}; 737 const auto& images{ir.GetImages()};
738 for (const auto& [offset, image] : images) { 738 for (const auto& image : images) {
739 std::string qualifier = "coherent volatile"; 739 std::string qualifier = "coherent volatile";
740 if (image.IsRead() && !image.IsWritten()) { 740 if (image.IsRead() && !image.IsWritten()) {
741 qualifier += " readonly"; 741 qualifier += " readonly";
@@ -2466,16 +2466,16 @@ ShaderEntries GetEntries(const VideoCommon::Shader::ShaderIR& ir) {
2466 entries.const_buffers.emplace_back(cbuf.second.GetMaxOffset(), cbuf.second.IsIndirect(), 2466 entries.const_buffers.emplace_back(cbuf.second.GetMaxOffset(), cbuf.second.IsIndirect(),
2467 cbuf.first); 2467 cbuf.first);
2468 } 2468 }
2469 for (const auto& [base, usage] : ir.GetGlobalMemory()) {
2470 entries.global_memory_entries.emplace_back(base.cbuf_index, base.cbuf_offset, usage.is_read,
2471 usage.is_written);
2472 }
2469 for (const auto& sampler : ir.GetSamplers()) { 2473 for (const auto& sampler : ir.GetSamplers()) {
2470 entries.samplers.emplace_back(sampler); 2474 entries.samplers.emplace_back(sampler);
2471 } 2475 }
2472 for (const auto& [offset, image] : ir.GetImages()) { 2476 for (const auto& image : ir.GetImages()) {
2473 entries.images.emplace_back(image); 2477 entries.images.emplace_back(image);
2474 } 2478 }
2475 for (const auto& [base, usage] : ir.GetGlobalMemory()) {
2476 entries.global_memory_entries.emplace_back(base.cbuf_index, base.cbuf_offset, usage.is_read,
2477 usage.is_written);
2478 }
2479 entries.clip_distances = ir.GetClipDistances(); 2479 entries.clip_distances = ir.GetClipDistances();
2480 entries.shader_length = ir.GetLength(); 2480 entries.shader_length = ir.GetLength();
2481 return entries; 2481 return entries;
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.h b/src/video_core/renderer_opengl/gl_shader_decompiler.h
index fead2a51e..b1e75e6cc 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.h
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.h
@@ -82,10 +82,9 @@ private:
82 82
83struct ShaderEntries { 83struct ShaderEntries {
84 std::vector<ConstBufferEntry> const_buffers; 84 std::vector<ConstBufferEntry> const_buffers;
85 std::vector<GlobalMemoryEntry> global_memory_entries;
85 std::vector<SamplerEntry> samplers; 86 std::vector<SamplerEntry> samplers;
86 std::vector<SamplerEntry> bindless_samplers;
87 std::vector<ImageEntry> images; 87 std::vector<ImageEntry> images;
88 std::vector<GlobalMemoryEntry> global_memory_entries;
89 std::array<bool, Maxwell::NumClipDistances> clip_distances{}; 88 std::array<bool, Maxwell::NumClipDistances> clip_distances{};
90 std::size_t shader_length{}; 89 std::size_t shader_length{};
91}; 90};
diff --git a/src/video_core/shader/control_flow.cpp b/src/video_core/shader/control_flow.cpp
index d47c63d9f..b427ac873 100644
--- a/src/video_core/shader/control_flow.cpp
+++ b/src/video_core/shader/control_flow.cpp
@@ -16,7 +16,9 @@
16#include "video_core/shader/shader_ir.h" 16#include "video_core/shader/shader_ir.h"
17 17
18namespace VideoCommon::Shader { 18namespace VideoCommon::Shader {
19
19namespace { 20namespace {
21
20using Tegra::Shader::Instruction; 22using Tegra::Shader::Instruction;
21using Tegra::Shader::OpCode; 23using Tegra::Shader::OpCode;
22 24
@@ -68,15 +70,15 @@ struct CFGRebuildState {
68 const ProgramCode& program_code; 70 const ProgramCode& program_code;
69 ConstBufferLocker& locker; 71 ConstBufferLocker& locker;
70 u32 start{}; 72 u32 start{};
71 std::vector<BlockInfo> block_info{}; 73 std::vector<BlockInfo> block_info;
72 std::list<u32> inspect_queries{}; 74 std::list<u32> inspect_queries;
73 std::list<Query> queries{}; 75 std::list<Query> queries;
74 std::unordered_map<u32, u32> registered{}; 76 std::unordered_map<u32, u32> registered;
75 std::set<u32> labels{}; 77 std::set<u32> labels;
76 std::map<u32, u32> ssy_labels{}; 78 std::map<u32, u32> ssy_labels;
77 std::map<u32, u32> pbk_labels{}; 79 std::map<u32, u32> pbk_labels;
78 std::unordered_map<u32, BlockStack> stacks{}; 80 std::unordered_map<u32, BlockStack> stacks;
79 ASTManager* manager; 81 ASTManager* manager{};
80}; 82};
81 83
82enum class BlockCollision : u32 { None, Found, Inside }; 84enum class BlockCollision : u32 { None, Found, Inside };
@@ -109,7 +111,7 @@ BlockInfo& CreateBlockInfo(CFGRebuildState& state, u32 start, u32 end) {
109} 111}
110 112
111Pred GetPredicate(u32 index, bool negated) { 113Pred GetPredicate(u32 index, bool negated) {
112 return static_cast<Pred>(index + (negated ? 8 : 0)); 114 return static_cast<Pred>(static_cast<u64>(index) + (negated ? 8ULL : 0ULL));
113} 115}
114 116
115/** 117/**
@@ -136,15 +138,13 @@ struct BranchIndirectInfo {
136 s32 relative_position{}; 138 s32 relative_position{};
137}; 139};
138 140
139std::optional<BranchIndirectInfo> TrackBranchIndirectInfo(const CFGRebuildState& state, 141struct BufferInfo {
140 u32 start_address, u32 current_position) { 142 u32 index;
141 const u32 shader_start = state.start; 143 u32 offset;
142 u32 pos = current_position; 144};
143 BranchIndirectInfo result{};
144 u64 track_register = 0;
145 145
146 // Step 0 Get BRX Info 146std::optional<std::pair<s32, u64>> GetBRXInfo(const CFGRebuildState& state, u32& pos) {
147 const Instruction instr = {state.program_code[pos]}; 147 const Instruction instr = state.program_code[pos];
148 const auto opcode = OpCode::Decode(instr); 148 const auto opcode = OpCode::Decode(instr);
149 if (opcode->get().GetId() != OpCode::Id::BRX) { 149 if (opcode->get().GetId() != OpCode::Id::BRX) {
150 return std::nullopt; 150 return std::nullopt;
@@ -152,86 +152,94 @@ std::optional<BranchIndirectInfo> TrackBranchIndirectInfo(const CFGRebuildState&
152 if (instr.brx.constant_buffer != 0) { 152 if (instr.brx.constant_buffer != 0) {
153 return std::nullopt; 153 return std::nullopt;
154 } 154 }
155 track_register = instr.gpr8.Value(); 155 --pos;
156 result.relative_position = instr.brx.GetBranchExtend(); 156 return std::make_pair(instr.brx.GetBranchExtend(), instr.gpr8.Value());
157 pos--; 157}
158 bool found_track = false;
159 158
160 // Step 1 Track LDC 159template <typename Result, typename TestCallable, typename PackCallable>
161 while (pos >= shader_start) { 160// requires std::predicate<TestCallable, Instruction, const OpCode::Matcher&>
162 if (IsSchedInstruction(pos, shader_start)) { 161// requires std::invocable<PackCallable, Instruction, const OpCode::Matcher&>
163 pos--; 162std::optional<Result> TrackInstruction(const CFGRebuildState& state, u32& pos, TestCallable test,
163 PackCallable pack) {
164 for (; pos >= state.start; --pos) {
165 if (IsSchedInstruction(pos, state.start)) {
164 continue; 166 continue;
165 } 167 }
166 const Instruction instr = {state.program_code[pos]}; 168 const Instruction instr = state.program_code[pos];
167 const auto opcode = OpCode::Decode(instr); 169 const auto opcode = OpCode::Decode(instr);
168 if (opcode->get().GetId() == OpCode::Id::LD_C) { 170 if (!opcode) {
169 if (instr.gpr0.Value() == track_register && 171 continue;
170 instr.ld_c.type.Value() == Tegra::Shader::UniformType::Single) { 172 }
171 result.buffer = instr.cbuf36.index.Value(); 173 if (test(instr, opcode->get())) {
172 result.offset = static_cast<u32>(instr.cbuf36.GetOffset()); 174 --pos;
173 track_register = instr.gpr8.Value(); 175 return std::make_optional(pack(instr, opcode->get()));
174 pos--;
175 found_track = true;
176 break;
177 }
178 } 176 }
179 pos--;
180 } 177 }
178 return std::nullopt;
179}
181 180
182 if (!found_track) { 181std::optional<std::pair<BufferInfo, u64>> TrackLDC(const CFGRebuildState& state, u32& pos,
183 return std::nullopt; 182 u64 brx_tracked_register) {
184 } 183 return TrackInstruction<std::pair<BufferInfo, u64>>(
185 found_track = false; 184 state, pos,
185 [brx_tracked_register](auto instr, const auto& opcode) {
186 return opcode.GetId() == OpCode::Id::LD_C &&
187 instr.gpr0.Value() == brx_tracked_register &&
188 instr.ld_c.type.Value() == Tegra::Shader::UniformType::Single;
189 },
190 [](auto instr, const auto& opcode) {
191 const BufferInfo info = {static_cast<u32>(instr.cbuf36.index.Value()),
192 static_cast<u32>(instr.cbuf36.GetOffset())};
193 return std::make_pair(info, instr.gpr8.Value());
194 });
195}
186 196
187 // Step 2 Track SHL 197std::optional<u64> TrackSHLRegister(const CFGRebuildState& state, u32& pos,
188 while (pos >= shader_start) { 198 u64 ldc_tracked_register) {
189 if (IsSchedInstruction(pos, shader_start)) { 199 return TrackInstruction<u64>(state, pos,
190 pos--; 200 [ldc_tracked_register](auto instr, const auto& opcode) {
191 continue; 201 return opcode.GetId() == OpCode::Id::SHL_IMM &&
192 } 202 instr.gpr0.Value() == ldc_tracked_register;
193 const Instruction instr = state.program_code[pos]; 203 },
194 const auto opcode = OpCode::Decode(instr); 204 [](auto instr, const auto&) { return instr.gpr8.Value(); });
195 if (opcode->get().GetId() == OpCode::Id::SHL_IMM) { 205}
196 if (instr.gpr0.Value() == track_register) { 206
197 track_register = instr.gpr8.Value(); 207std::optional<u32> TrackIMNMXValue(const CFGRebuildState& state, u32& pos,
198 pos--; 208 u64 shl_tracked_register) {
199 found_track = true; 209 return TrackInstruction<u32>(state, pos,
200 break; 210 [shl_tracked_register](auto instr, const auto& opcode) {
201 } 211 return opcode.GetId() == OpCode::Id::IMNMX_IMM &&
202 } 212 instr.gpr0.Value() == shl_tracked_register;
203 pos--; 213 },
214 [](auto instr, const auto&) {
215 return static_cast<u32>(instr.alu.GetSignedImm20_20() + 1);
216 });
217}
218
219std::optional<BranchIndirectInfo> TrackBranchIndirectInfo(const CFGRebuildState& state, u32 pos) {
220 const auto brx_info = GetBRXInfo(state, pos);
221 if (!brx_info) {
222 return std::nullopt;
204 } 223 }
224 const auto [relative_position, brx_tracked_register] = *brx_info;
205 225
206 if (!found_track) { 226 const auto ldc_info = TrackLDC(state, pos, brx_tracked_register);
227 if (!ldc_info) {
207 return std::nullopt; 228 return std::nullopt;
208 } 229 }
209 found_track = false; 230 const auto [buffer_info, ldc_tracked_register] = *ldc_info;
210 231
211 // Step 3 Track IMNMX 232 const auto shl_tracked_register = TrackSHLRegister(state, pos, ldc_tracked_register);
212 while (pos >= shader_start) { 233 if (!shl_tracked_register) {
213 if (IsSchedInstruction(pos, shader_start)) { 234 return std::nullopt;
214 pos--;
215 continue;
216 }
217 const Instruction instr = state.program_code[pos];
218 const auto opcode = OpCode::Decode(instr);
219 if (opcode->get().GetId() == OpCode::Id::IMNMX_IMM) {
220 if (instr.gpr0.Value() == track_register) {
221 track_register = instr.gpr8.Value();
222 result.entries = instr.alu.GetSignedImm20_20() + 1;
223 pos--;
224 found_track = true;
225 break;
226 }
227 }
228 pos--;
229 } 235 }
230 236
231 if (!found_track) { 237 const auto entries = TrackIMNMXValue(state, pos, *shl_tracked_register);
238 if (!entries) {
232 return std::nullopt; 239 return std::nullopt;
233 } 240 }
234 return result; 241
242 return BranchIndirectInfo{buffer_info.index, buffer_info.offset, *entries, relative_position};
235} 243}
236 244
237std::pair<ParseResult, ParseInfo> ParseCode(CFGRebuildState& state, u32 address) { 245std::pair<ParseResult, ParseInfo> ParseCode(CFGRebuildState& state, u32 address) {
@@ -420,30 +428,30 @@ std::pair<ParseResult, ParseInfo> ParseCode(CFGRebuildState& state, u32 address)
420 break; 428 break;
421 } 429 }
422 case OpCode::Id::BRX: { 430 case OpCode::Id::BRX: {
423 auto tmp = TrackBranchIndirectInfo(state, address, offset); 431 const auto tmp = TrackBranchIndirectInfo(state, offset);
424 if (tmp) { 432 if (!tmp) {
425 auto result = *tmp;
426 std::vector<CaseBranch> branches{};
427 s32 pc_target = offset + result.relative_position;
428 for (u32 i = 0; i < result.entries; i++) {
429 auto k = state.locker.ObtainKey(result.buffer, result.offset + i * 4);
430 if (!k) {
431 return {ParseResult::AbnormalFlow, parse_info};
432 }
433 u32 value = *k;
434 u32 target = static_cast<u32>((value >> 3) + pc_target);
435 insert_label(state, target);
436 branches.emplace_back(value, target);
437 }
438 parse_info.end_address = offset;
439 parse_info.branch_info = MakeBranchInfo<MultiBranch>(
440 static_cast<u32>(instr.gpr8.Value()), std::move(branches));
441
442 return {ParseResult::ControlCaught, parse_info};
443 } else {
444 LOG_WARNING(HW_GPU, "BRX Track Unsuccesful"); 433 LOG_WARNING(HW_GPU, "BRX Track Unsuccesful");
434 return {ParseResult::AbnormalFlow, parse_info};
445 } 435 }
446 return {ParseResult::AbnormalFlow, parse_info}; 436
437 const auto result = *tmp;
438 const s32 pc_target = offset + result.relative_position;
439 std::vector<CaseBranch> branches;
440 for (u32 i = 0; i < result.entries; i++) {
441 auto key = state.locker.ObtainKey(result.buffer, result.offset + i * 4);
442 if (!key) {
443 return {ParseResult::AbnormalFlow, parse_info};
444 }
445 u32 value = *key;
446 u32 target = static_cast<u32>((value >> 3) + pc_target);
447 insert_label(state, target);
448 branches.emplace_back(value, target);
449 }
450 parse_info.end_address = offset;
451 parse_info.branch_info = MakeBranchInfo<MultiBranch>(
452 static_cast<u32>(instr.gpr8.Value()), std::move(branches));
453
454 return {ParseResult::ControlCaught, parse_info};
447 } 455 }
448 default: 456 default:
449 break; 457 break;
diff --git a/src/video_core/shader/decode/arithmetic.cpp b/src/video_core/shader/decode/arithmetic.cpp
index 1473c282a..fcedd2af6 100644
--- a/src/video_core/shader/decode/arithmetic.cpp
+++ b/src/video_core/shader/decode/arithmetic.cpp
@@ -43,12 +43,12 @@ u32 ShaderIR::DecodeArithmetic(NodeBlock& bb, u32 pc) {
43 case OpCode::Id::FMUL_IMM: { 43 case OpCode::Id::FMUL_IMM: {
44 // FMUL does not have 'abs' bits and only the second operand has a 'neg' bit. 44 // FMUL does not have 'abs' bits and only the second operand has a 'neg' bit.
45 if (instr.fmul.tab5cb8_2 != 0) { 45 if (instr.fmul.tab5cb8_2 != 0) {
46 LOG_WARNING(HW_GPU, "FMUL tab5cb8_2({}) is not implemented", 46 LOG_DEBUG(HW_GPU, "FMUL tab5cb8_2({}) is not implemented",
47 instr.fmul.tab5cb8_2.Value()); 47 instr.fmul.tab5cb8_2.Value());
48 } 48 }
49 if (instr.fmul.tab5c68_0 != 1) { 49 if (instr.fmul.tab5c68_0 != 1) {
50 LOG_WARNING(HW_GPU, "FMUL tab5cb8_0({}) is not implemented", 50 LOG_DEBUG(HW_GPU, "FMUL tab5cb8_0({}) is not implemented",
51 instr.fmul.tab5c68_0.Value()); 51 instr.fmul.tab5c68_0.Value());
52 } 52 }
53 53
54 op_b = GetOperandAbsNegFloat(op_b, false, instr.fmul.negate_b); 54 op_b = GetOperandAbsNegFloat(op_b, false, instr.fmul.negate_b);
@@ -144,10 +144,11 @@ u32 ShaderIR::DecodeArithmetic(NodeBlock& bb, u32 pc) {
144 case OpCode::Id::RRO_C: 144 case OpCode::Id::RRO_C:
145 case OpCode::Id::RRO_R: 145 case OpCode::Id::RRO_R:
146 case OpCode::Id::RRO_IMM: { 146 case OpCode::Id::RRO_IMM: {
147 LOG_DEBUG(HW_GPU, "(STUBBED) RRO used");
148
147 // Currently RRO is only implemented as a register move. 149 // Currently RRO is only implemented as a register move.
148 op_b = GetOperandAbsNegFloat(op_b, instr.alu.abs_b, instr.alu.negate_b); 150 op_b = GetOperandAbsNegFloat(op_b, instr.alu.abs_b, instr.alu.negate_b);
149 SetRegister(bb, instr.gpr0, op_b); 151 SetRegister(bb, instr.gpr0, op_b);
150 LOG_WARNING(HW_GPU, "RRO instruction is incomplete");
151 break; 152 break;
152 } 153 }
153 default: 154 default:
diff --git a/src/video_core/shader/decode/arithmetic_half.cpp b/src/video_core/shader/decode/arithmetic_half.cpp
index b06cbe441..ee7d9a29d 100644
--- a/src/video_core/shader/decode/arithmetic_half.cpp
+++ b/src/video_core/shader/decode/arithmetic_half.cpp
@@ -21,8 +21,8 @@ u32 ShaderIR::DecodeArithmeticHalf(NodeBlock& bb, u32 pc) {
21 21
22 if (opcode->get().GetId() == OpCode::Id::HADD2_C || 22 if (opcode->get().GetId() == OpCode::Id::HADD2_C ||
23 opcode->get().GetId() == OpCode::Id::HADD2_R) { 23 opcode->get().GetId() == OpCode::Id::HADD2_R) {
24 if (instr.alu_half.ftz != 0) { 24 if (instr.alu_half.ftz == 0) {
25 LOG_WARNING(HW_GPU, "{} FTZ not implemented", opcode->get().GetName()); 25 LOG_DEBUG(HW_GPU, "{} without FTZ is not implemented", opcode->get().GetName());
26 } 26 }
27 } 27 }
28 28
diff --git a/src/video_core/shader/decode/arithmetic_half_immediate.cpp b/src/video_core/shader/decode/arithmetic_half_immediate.cpp
index 6466fc011..d179b9873 100644
--- a/src/video_core/shader/decode/arithmetic_half_immediate.cpp
+++ b/src/video_core/shader/decode/arithmetic_half_immediate.cpp
@@ -19,12 +19,12 @@ u32 ShaderIR::DecodeArithmeticHalfImmediate(NodeBlock& bb, u32 pc) {
19 const auto opcode = OpCode::Decode(instr); 19 const auto opcode = OpCode::Decode(instr);
20 20
21 if (opcode->get().GetId() == OpCode::Id::HADD2_IMM) { 21 if (opcode->get().GetId() == OpCode::Id::HADD2_IMM) {
22 if (instr.alu_half_imm.ftz != 0) { 22 if (instr.alu_half_imm.ftz == 0) {
23 LOG_WARNING(HW_GPU, "{} FTZ not implemented", opcode->get().GetName()); 23 LOG_DEBUG(HW_GPU, "{} without FTZ is not implemented", opcode->get().GetName());
24 } 24 }
25 } else { 25 } else {
26 if (instr.alu_half_imm.precision != Tegra::Shader::HalfPrecision::None) { 26 if (instr.alu_half_imm.precision != Tegra::Shader::HalfPrecision::FTZ) {
27 LOG_WARNING(HW_GPU, "{} FTZ not implemented", opcode->get().GetName()); 27 LOG_DEBUG(HW_GPU, "{} without FTZ is not implemented", opcode->get().GetName());
28 } 28 }
29 } 29 }
30 30
diff --git a/src/video_core/shader/decode/ffma.cpp b/src/video_core/shader/decode/ffma.cpp
index ca2f39e8d..5973588d6 100644
--- a/src/video_core/shader/decode/ffma.cpp
+++ b/src/video_core/shader/decode/ffma.cpp
@@ -19,10 +19,10 @@ u32 ShaderIR::DecodeFfma(NodeBlock& bb, u32 pc) {
19 19
20 UNIMPLEMENTED_IF_MSG(instr.ffma.cc != 0, "FFMA cc not implemented"); 20 UNIMPLEMENTED_IF_MSG(instr.ffma.cc != 0, "FFMA cc not implemented");
21 if (instr.ffma.tab5980_0 != 1) { 21 if (instr.ffma.tab5980_0 != 1) {
22 LOG_WARNING(HW_GPU, "FFMA tab5980_0({}) not implemented", instr.ffma.tab5980_0.Value()); 22 LOG_DEBUG(HW_GPU, "FFMA tab5980_0({}) not implemented", instr.ffma.tab5980_0.Value());
23 } 23 }
24 if (instr.ffma.tab5980_1 != 0) { 24 if (instr.ffma.tab5980_1 != 0) {
25 LOG_WARNING(HW_GPU, "FFMA tab5980_1({}) not implemented", instr.ffma.tab5980_1.Value()); 25 LOG_DEBUG(HW_GPU, "FFMA tab5980_1({}) not implemented", instr.ffma.tab5980_1.Value());
26 } 26 }
27 27
28 const Node op_a = GetRegister(instr.gpr8); 28 const Node op_a = GetRegister(instr.gpr8);
diff --git a/src/video_core/shader/decode/half_set.cpp b/src/video_core/shader/decode/half_set.cpp
index 48ca7a4af..848e46874 100644
--- a/src/video_core/shader/decode/half_set.cpp
+++ b/src/video_core/shader/decode/half_set.cpp
@@ -20,8 +20,8 @@ u32 ShaderIR::DecodeHalfSet(NodeBlock& bb, u32 pc) {
20 const Instruction instr = {program_code[pc]}; 20 const Instruction instr = {program_code[pc]};
21 const auto opcode = OpCode::Decode(instr); 21 const auto opcode = OpCode::Decode(instr);
22 22
23 if (instr.hset2.ftz != 0) { 23 if (instr.hset2.ftz == 0) {
24 LOG_WARNING(HW_GPU, "{} FTZ not implemented", opcode->get().GetName()); 24 LOG_DEBUG(HW_GPU, "{} without FTZ is not implemented", opcode->get().GetName());
25 } 25 }
26 26
27 Node op_a = UnpackHalfFloat(GetRegister(instr.gpr8), instr.hset2.type_a); 27 Node op_a = UnpackHalfFloat(GetRegister(instr.gpr8), instr.hset2.type_a);
diff --git a/src/video_core/shader/decode/half_set_predicate.cpp b/src/video_core/shader/decode/half_set_predicate.cpp
index fec8f2dbe..310655619 100644
--- a/src/video_core/shader/decode/half_set_predicate.cpp
+++ b/src/video_core/shader/decode/half_set_predicate.cpp
@@ -19,7 +19,9 @@ u32 ShaderIR::DecodeHalfSetPredicate(NodeBlock& bb, u32 pc) {
19 const Instruction instr = {program_code[pc]}; 19 const Instruction instr = {program_code[pc]};
20 const auto opcode = OpCode::Decode(instr); 20 const auto opcode = OpCode::Decode(instr);
21 21
22 LOG_DEBUG(HW_GPU, "ftz={}", static_cast<u32>(instr.hsetp2.ftz)); 22 if (instr.hsetp2.ftz != 0) {
23 LOG_DEBUG(HW_GPU, "{} without FTZ is not implemented", opcode->get().GetName());
24 }
23 25
24 Node op_a = UnpackHalfFloat(GetRegister(instr.gpr8), instr.hsetp2.type_a); 26 Node op_a = UnpackHalfFloat(GetRegister(instr.gpr8), instr.hsetp2.type_a);
25 op_a = GetOperandAbsNegHalf(op_a, instr.hsetp2.abs_a, instr.hsetp2.negate_a); 27 op_a = GetOperandAbsNegHalf(op_a, instr.hsetp2.abs_a, instr.hsetp2.negate_a);
diff --git a/src/video_core/shader/decode/image.cpp b/src/video_core/shader/decode/image.cpp
index b02d2cb95..d2fe4ec5d 100644
--- a/src/video_core/shader/decode/image.cpp
+++ b/src/video_core/shader/decode/image.cpp
@@ -143,39 +143,37 @@ u32 ShaderIR::DecodeImage(NodeBlock& bb, u32 pc) {
143} 143}
144 144
145Image& ShaderIR::GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type) { 145Image& ShaderIR::GetImage(Tegra::Shader::Image image, Tegra::Shader::ImageType type) {
146 const auto offset{static_cast<std::size_t>(image.index.Value())}; 146 const auto offset = static_cast<u32>(image.index.Value());
147 if (const auto existing_image = TryUseExistingImage(offset, type)) { 147
148 return *existing_image; 148 const auto it =
149 std::find_if(std::begin(used_images), std::end(used_images),
150 [offset](const Image& entry) { return entry.GetOffset() == offset; });
151 if (it != std::end(used_images)) {
152 ASSERT(!it->IsBindless() && it->GetType() == it->GetType());
153 return *it;
149 } 154 }
150 155
151 const std::size_t next_index{used_images.size()}; 156 const auto next_index = static_cast<u32>(used_images.size());
152 return used_images.emplace(offset, Image{offset, next_index, type}).first->second; 157 return used_images.emplace_back(next_index, offset, type);
153} 158}
154 159
155Image& ShaderIR::GetBindlessImage(Tegra::Shader::Register reg, Tegra::Shader::ImageType type) { 160Image& ShaderIR::GetBindlessImage(Tegra::Shader::Register reg, Tegra::Shader::ImageType type) {
156 const Node image_register{GetRegister(reg)}; 161 const Node image_register = GetRegister(reg);
157 const auto [base_image, cbuf_index, cbuf_offset]{ 162 const auto [base_image, buffer, offset] =
158 TrackCbuf(image_register, global_code, static_cast<s64>(global_code.size()))}; 163 TrackCbuf(image_register, global_code, static_cast<s64>(global_code.size()));
159 const auto cbuf_key{(static_cast<u64>(cbuf_index) << 32) | static_cast<u64>(cbuf_offset)}; 164
160 165 const auto it =
161 if (const auto image = TryUseExistingImage(cbuf_key, type)) { 166 std::find_if(std::begin(used_images), std::end(used_images),
162 return *image; 167 [buffer = buffer, offset = offset](const Image& entry) {
163 } 168 return entry.GetBuffer() == buffer && entry.GetOffset() == offset;
164 169 });
165 const std::size_t next_index{used_images.size()}; 170 if (it != std::end(used_images)) {
166 return used_images.emplace(cbuf_key, Image{cbuf_index, cbuf_offset, next_index, type}) 171 ASSERT(it->IsBindless() && it->GetType() == it->GetType());
167 .first->second; 172 return *it;
168}
169
170Image* ShaderIR::TryUseExistingImage(u64 offset, Tegra::Shader::ImageType type) {
171 auto it = used_images.find(offset);
172 if (it == used_images.end()) {
173 return nullptr;
174 } 173 }
175 auto& image = it->second;
176 ASSERT(image.GetType() == type);
177 174
178 return &image; 175 const auto next_index = static_cast<u32>(used_images.size());
176 return used_images.emplace_back(next_index, offset, buffer, type);
179} 177}
180 178
181} // namespace VideoCommon::Shader 179} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp
index 0599ef34f..bb926a132 100644
--- a/src/video_core/shader/decode/texture.cpp
+++ b/src/video_core/shader/decode/texture.cpp
@@ -44,10 +44,6 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
44 bool is_bindless = false; 44 bool is_bindless = false;
45 switch (opcode->get().GetId()) { 45 switch (opcode->get().GetId()) {
46 case OpCode::Id::TEX: { 46 case OpCode::Id::TEX: {
47 if (instr.tex.UsesMiscMode(TextureMiscMode::NODEP)) {
48 LOG_WARNING(HW_GPU, "TEX.NODEP implementation is incomplete");
49 }
50
51 const TextureType texture_type{instr.tex.texture_type}; 47 const TextureType texture_type{instr.tex.texture_type};
52 const bool is_array = instr.tex.array != 0; 48 const bool is_array = instr.tex.array != 0;
53 const bool is_aoffi = instr.tex.UsesMiscMode(TextureMiscMode::AOFFI); 49 const bool is_aoffi = instr.tex.UsesMiscMode(TextureMiscMode::AOFFI);
@@ -62,10 +58,6 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
62 UNIMPLEMENTED_IF_MSG(instr.tex.UsesMiscMode(TextureMiscMode::AOFFI), 58 UNIMPLEMENTED_IF_MSG(instr.tex.UsesMiscMode(TextureMiscMode::AOFFI),
63 "AOFFI is not implemented"); 59 "AOFFI is not implemented");
64 60
65 if (instr.tex.UsesMiscMode(TextureMiscMode::NODEP)) {
66 LOG_WARNING(HW_GPU, "TEX.NODEP implementation is incomplete");
67 }
68
69 const TextureType texture_type{instr.tex_b.texture_type}; 61 const TextureType texture_type{instr.tex_b.texture_type};
70 const bool is_array = instr.tex_b.array != 0; 62 const bool is_array = instr.tex_b.array != 0;
71 const bool is_aoffi = instr.tex.UsesMiscMode(TextureMiscMode::AOFFI); 63 const bool is_aoffi = instr.tex.UsesMiscMode(TextureMiscMode::AOFFI);
@@ -82,10 +74,6 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
82 const bool depth_compare = instr.texs.UsesMiscMode(TextureMiscMode::DC); 74 const bool depth_compare = instr.texs.UsesMiscMode(TextureMiscMode::DC);
83 const auto process_mode = instr.texs.GetTextureProcessMode(); 75 const auto process_mode = instr.texs.GetTextureProcessMode();
84 76
85 if (instr.texs.UsesMiscMode(TextureMiscMode::NODEP)) {
86 LOG_WARNING(HW_GPU, "TEXS.NODEP implementation is incomplete");
87 }
88
89 const Node4 components = 77 const Node4 components =
90 GetTexsCode(instr, texture_type, process_mode, depth_compare, is_array); 78 GetTexsCode(instr, texture_type, process_mode, depth_compare, is_array);
91 79
@@ -107,10 +95,6 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
107 UNIMPLEMENTED_IF_MSG(instr.tld4.UsesMiscMode(TextureMiscMode::PTP), 95 UNIMPLEMENTED_IF_MSG(instr.tld4.UsesMiscMode(TextureMiscMode::PTP),
108 "PTP is not implemented"); 96 "PTP is not implemented");
109 97
110 if (instr.tld4.UsesMiscMode(TextureMiscMode::NODEP)) {
111 LOG_WARNING(HW_GPU, "TLD4.NODEP implementation is incomplete");
112 }
113
114 const auto texture_type = instr.tld4.texture_type.Value(); 98 const auto texture_type = instr.tld4.texture_type.Value();
115 const bool depth_compare = is_bindless ? instr.tld4_b.UsesMiscMode(TextureMiscMode::DC) 99 const bool depth_compare = is_bindless ? instr.tld4_b.UsesMiscMode(TextureMiscMode::DC)
116 : instr.tld4.UsesMiscMode(TextureMiscMode::DC); 100 : instr.tld4.UsesMiscMode(TextureMiscMode::DC);
@@ -119,15 +103,12 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
119 : instr.tld4.UsesMiscMode(TextureMiscMode::AOFFI); 103 : instr.tld4.UsesMiscMode(TextureMiscMode::AOFFI);
120 WriteTexInstructionFloat( 104 WriteTexInstructionFloat(
121 bb, instr, 105 bb, instr,
122 GetTld4Code(instr, texture_type, depth_compare, is_array, is_aoffi, is_bindless), true); 106 GetTld4Code(instr, texture_type, depth_compare, is_array, is_aoffi, is_bindless));
123 break; 107 break;
124 } 108 }
125 case OpCode::Id::TLD4S: { 109 case OpCode::Id::TLD4S: {
126 UNIMPLEMENTED_IF_MSG(instr.tld4s.UsesMiscMode(TextureMiscMode::AOFFI), 110 UNIMPLEMENTED_IF_MSG(instr.tld4s.UsesMiscMode(TextureMiscMode::AOFFI),
127 "AOFFI is not implemented"); 111 "AOFFI is not implemented");
128 if (instr.tld4s.UsesMiscMode(TextureMiscMode::NODEP)) {
129 LOG_WARNING(HW_GPU, "TLD4S.NODEP implementation is incomplete");
130 }
131 112
132 const bool depth_compare = instr.tld4s.UsesMiscMode(TextureMiscMode::DC); 113 const bool depth_compare = instr.tld4s.UsesMiscMode(TextureMiscMode::DC);
133 const Node op_a = GetRegister(instr.gpr8); 114 const Node op_a = GetRegister(instr.gpr8);
@@ -164,10 +145,6 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
164 is_bindless = true; 145 is_bindless = true;
165 [[fallthrough]]; 146 [[fallthrough]];
166 case OpCode::Id::TXQ: { 147 case OpCode::Id::TXQ: {
167 if (instr.txq.UsesMiscMode(TextureMiscMode::NODEP)) {
168 LOG_WARNING(HW_GPU, "TXQ.NODEP implementation is incomplete");
169 }
170
171 // TODO: The new commits on the texture refactor, change the way samplers work. 148 // TODO: The new commits on the texture refactor, change the way samplers work.
172 // Sadly, not all texture instructions specify the type of texture their sampler 149 // Sadly, not all texture instructions specify the type of texture their sampler
173 // uses. This must be fixed at a later instance. 150 // uses. This must be fixed at a later instance.
@@ -205,10 +182,6 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
205 UNIMPLEMENTED_IF_MSG(instr.tmml.UsesMiscMode(Tegra::Shader::TextureMiscMode::NDV), 182 UNIMPLEMENTED_IF_MSG(instr.tmml.UsesMiscMode(Tegra::Shader::TextureMiscMode::NDV),
206 "NDV is not implemented"); 183 "NDV is not implemented");
207 184
208 if (instr.tmml.UsesMiscMode(TextureMiscMode::NODEP)) {
209 LOG_WARNING(HW_GPU, "TMML.NODEP implementation is incomplete");
210 }
211
212 auto texture_type = instr.tmml.texture_type.Value(); 185 auto texture_type = instr.tmml.texture_type.Value();
213 const bool is_array = instr.tmml.array != 0; 186 const bool is_array = instr.tmml.array != 0;
214 const auto& sampler = 187 const auto& sampler =
@@ -254,25 +227,17 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
254 UNIMPLEMENTED_IF_MSG(instr.tld.ms, "MS is not implemented"); 227 UNIMPLEMENTED_IF_MSG(instr.tld.ms, "MS is not implemented");
255 UNIMPLEMENTED_IF_MSG(instr.tld.cl, "CL is not implemented"); 228 UNIMPLEMENTED_IF_MSG(instr.tld.cl, "CL is not implemented");
256 229
257 if (instr.tld.nodep_flag) {
258 LOG_WARNING(HW_GPU, "TLD.NODEP implementation is incomplete");
259 }
260
261 WriteTexInstructionFloat(bb, instr, GetTldCode(instr)); 230 WriteTexInstructionFloat(bb, instr, GetTldCode(instr));
262 break; 231 break;
263 } 232 }
264 case OpCode::Id::TLDS: { 233 case OpCode::Id::TLDS: {
265 const Tegra::Shader::TextureType texture_type{instr.tlds.GetTextureType()}; 234 const TextureType texture_type{instr.tlds.GetTextureType()};
266 const bool is_array{instr.tlds.IsArrayTexture()}; 235 const bool is_array{instr.tlds.IsArrayTexture()};
267 236
268 UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(TextureMiscMode::AOFFI), 237 UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(TextureMiscMode::AOFFI),
269 "AOFFI is not implemented"); 238 "AOFFI is not implemented");
270 UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(TextureMiscMode::MZ), "MZ is not implemented"); 239 UNIMPLEMENTED_IF_MSG(instr.tlds.UsesMiscMode(TextureMiscMode::MZ), "MZ is not implemented");
271 240
272 if (instr.tlds.UsesMiscMode(TextureMiscMode::NODEP)) {
273 LOG_WARNING(HW_GPU, "TLDS.NODEP implementation is incomplete");
274 }
275
276 const Node4 components = GetTldsCode(instr, texture_type, is_array); 241 const Node4 components = GetTldsCode(instr, texture_type, is_array);
277 242
278 if (instr.tlds.fp32_flag) { 243 if (instr.tlds.fp32_flag) {
@@ -293,84 +258,86 @@ const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler,
293 std::optional<SamplerInfo> sampler_info) { 258 std::optional<SamplerInfo> sampler_info) {
294 const auto offset = static_cast<u32>(sampler.index.Value()); 259 const auto offset = static_cast<u32>(sampler.index.Value());
295 260
296 Tegra::Shader::TextureType type; 261 TextureType type;
297 bool is_array; 262 bool is_array;
298 bool is_shadow; 263 bool is_shadow;
299 if (sampler_info) { 264 if (sampler_info) {
300 type = sampler_info->type; 265 type = sampler_info->type;
301 is_array = sampler_info->is_array; 266 is_array = sampler_info->is_array;
302 is_shadow = sampler_info->is_shadow; 267 is_shadow = sampler_info->is_shadow;
303 } else if (auto sampler = locker.ObtainBoundSampler(offset); sampler) { 268 } else if (const auto sampler = locker.ObtainBoundSampler(offset)) {
304 type = sampler->texture_type.Value(); 269 type = sampler->texture_type.Value();
305 is_array = sampler->is_array.Value() != 0; 270 is_array = sampler->is_array.Value() != 0;
306 is_shadow = sampler->is_shadow.Value() != 0; 271 is_shadow = sampler->is_shadow.Value() != 0;
307 } else { 272 } else {
308 type = Tegra::Shader::TextureType::Texture2D; 273 LOG_WARNING(HW_GPU, "Unknown sampler info");
274 type = TextureType::Texture2D;
309 is_array = false; 275 is_array = false;
310 is_shadow = false; 276 is_shadow = false;
311 } 277 }
312 278
313 // If this sampler has already been used, return the existing mapping. 279 // If this sampler has already been used, return the existing mapping.
314 const auto itr = 280 const auto it =
315 std::find_if(used_samplers.begin(), used_samplers.end(), 281 std::find_if(used_samplers.begin(), used_samplers.end(),
316 [&](const Sampler& entry) { return entry.GetOffset() == offset; }); 282 [offset](const Sampler& entry) { return entry.GetOffset() == offset; });
317 if (itr != used_samplers.end()) { 283 if (it != used_samplers.end()) {
318 ASSERT(itr->GetType() == type && itr->IsArray() == is_array && 284 ASSERT(!it->IsBindless() && it->GetType() == type && it->IsArray() == is_array &&
319 itr->IsShadow() == is_shadow); 285 it->IsShadow() == is_shadow);
320 return *itr; 286 return *it;
321 } 287 }
322 288
323 // Otherwise create a new mapping for this sampler 289 // Otherwise create a new mapping for this sampler
324 const std::size_t next_index = used_samplers.size(); 290 const auto next_index = static_cast<u32>(used_samplers.size());
325 const Sampler entry{offset, next_index, type, is_array, is_shadow}; 291 return used_samplers.emplace_back(Sampler(next_index, offset, type, is_array, is_shadow));
326 return *used_samplers.emplace(entry).first; 292}
327} // namespace VideoCommon::Shader
328 293
329const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg, 294const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg,
330 std::optional<SamplerInfo> sampler_info) { 295 std::optional<SamplerInfo> sampler_info) {
331 const Node sampler_register = GetRegister(reg); 296 const Node sampler_register = GetRegister(reg);
332 const auto [base_sampler, cbuf_index, cbuf_offset] = 297 const auto [base_sampler, buffer, offset] =
333 TrackCbuf(sampler_register, global_code, static_cast<s64>(global_code.size())); 298 TrackCbuf(sampler_register, global_code, static_cast<s64>(global_code.size()));
334 ASSERT(base_sampler != nullptr); 299 ASSERT(base_sampler != nullptr);
335 const auto cbuf_key = (static_cast<u64>(cbuf_index) << 32) | static_cast<u64>(cbuf_offset); 300
336 Tegra::Shader::TextureType type; 301 TextureType type;
337 bool is_array; 302 bool is_array;
338 bool is_shadow; 303 bool is_shadow;
339 if (sampler_info) { 304 if (sampler_info) {
340 type = sampler_info->type; 305 type = sampler_info->type;
341 is_array = sampler_info->is_array; 306 is_array = sampler_info->is_array;
342 is_shadow = sampler_info->is_shadow; 307 is_shadow = sampler_info->is_shadow;
343 } else if (auto sampler = locker.ObtainBindlessSampler(cbuf_index, cbuf_offset); sampler) { 308 } else if (const auto sampler = locker.ObtainBindlessSampler(buffer, offset)) {
344 type = sampler->texture_type.Value(); 309 type = sampler->texture_type.Value();
345 is_array = sampler->is_array.Value() != 0; 310 is_array = sampler->is_array.Value() != 0;
346 is_shadow = sampler->is_shadow.Value() != 0; 311 is_shadow = sampler->is_shadow.Value() != 0;
347 } else { 312 } else {
348 type = Tegra::Shader::TextureType::Texture2D; 313 LOG_WARNING(HW_GPU, "Unknown sampler info");
314 type = TextureType::Texture2D;
349 is_array = false; 315 is_array = false;
350 is_shadow = false; 316 is_shadow = false;
351 } 317 }
352 318
353 // If this sampler has already been used, return the existing mapping. 319 // If this sampler has already been used, return the existing mapping.
354 const auto itr = 320 const auto it =
355 std::find_if(used_samplers.begin(), used_samplers.end(), 321 std::find_if(used_samplers.begin(), used_samplers.end(),
356 [&](const Sampler& entry) { return entry.GetOffset() == cbuf_key; }); 322 [buffer = buffer, offset = offset](const Sampler& entry) {
357 if (itr != used_samplers.end()) { 323 return entry.GetBuffer() == buffer && entry.GetOffset() == offset;
358 ASSERT(itr->GetType() == type && itr->IsArray() == is_array && 324 });
359 itr->IsShadow() == is_shadow); 325 if (it != used_samplers.end()) {
360 return *itr; 326 ASSERT(it->IsBindless() && it->GetType() == type && it->IsArray() == is_array &&
327 it->IsShadow() == is_shadow);
328 return *it;
361 } 329 }
362 330
363 // Otherwise create a new mapping for this sampler 331 // Otherwise create a new mapping for this sampler
364 const std::size_t next_index = used_samplers.size(); 332 const auto next_index = static_cast<u32>(used_samplers.size());
365 const Sampler entry{cbuf_index, cbuf_offset, next_index, type, is_array, is_shadow}; 333 return used_samplers.emplace_back(
366 return *used_samplers.emplace(entry).first; 334 Sampler(next_index, offset, buffer, type, is_array, is_shadow));
367} 335}
368 336
369void ShaderIR::WriteTexInstructionFloat(NodeBlock& bb, Instruction instr, const Node4& components, 337void ShaderIR::WriteTexInstructionFloat(NodeBlock& bb, Instruction instr, const Node4& components) {
370 bool is_tld4) {
371 u32 dest_elem = 0; 338 u32 dest_elem = 0;
372 for (u32 elem = 0; elem < 4; ++elem) { 339 for (u32 elem = 0; elem < 4; ++elem) {
373 if (!is_tld4 && !instr.tex.IsComponentEnabled(elem)) { 340 if (!instr.tex.IsComponentEnabled(elem)) {
374 // Skip disabled components 341 // Skip disabled components
375 continue; 342 continue;
376 } 343 }
diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h
index 447fb5c1d..4300d9ff4 100644
--- a/src/video_core/shader/node.h
+++ b/src/video_core/shader/node.h
@@ -230,62 +230,49 @@ using NodeBlock = std::vector<Node>;
230class Sampler { 230class Sampler {
231public: 231public:
232 /// This constructor is for bound samplers 232 /// This constructor is for bound samplers
233 explicit Sampler(std::size_t offset, std::size_t index, Tegra::Shader::TextureType type, 233 constexpr explicit Sampler(u32 index, u32 offset, Tegra::Shader::TextureType type,
234 bool is_array, bool is_shadow) 234 bool is_array, bool is_shadow)
235 : offset{offset}, index{index}, type{type}, is_array{is_array}, is_shadow{is_shadow}, 235 : index{index}, offset{offset}, type{type}, is_array{is_array}, is_shadow{is_shadow} {}
236 is_bindless{false} {}
237 236
238 /// This constructor is for bindless samplers 237 /// This constructor is for bindless samplers
239 explicit Sampler(u32 cbuf_index, u32 cbuf_offset, std::size_t index, 238 constexpr explicit Sampler(u32 index, u32 offset, u32 buffer, Tegra::Shader::TextureType type,
240 Tegra::Shader::TextureType type, bool is_array, bool is_shadow) 239 bool is_array, bool is_shadow)
241 : offset{(static_cast<u64>(cbuf_index) << 32) | cbuf_offset}, index{index}, type{type}, 240 : index{index}, offset{offset}, buffer{buffer}, type{type}, is_array{is_array},
242 is_array{is_array}, is_shadow{is_shadow}, is_bindless{true} {} 241 is_shadow{is_shadow}, is_bindless{true} {}
243 242
244 /// This constructor is for serialization/deserialization 243 constexpr u32 GetIndex() const {
245 explicit Sampler(std::size_t offset, std::size_t index, Tegra::Shader::TextureType type, 244 return index;
246 bool is_array, bool is_shadow, bool is_bindless) 245 }
247 : offset{offset}, index{index}, type{type}, is_array{is_array}, is_shadow{is_shadow}, 246
248 is_bindless{is_bindless} {} 247 constexpr u32 GetOffset() const {
249
250 std::size_t GetOffset() const {
251 return offset; 248 return offset;
252 } 249 }
253 250
254 std::size_t GetIndex() const { 251 constexpr u32 GetBuffer() const {
255 return index; 252 return buffer;
256 } 253 }
257 254
258 Tegra::Shader::TextureType GetType() const { 255 constexpr Tegra::Shader::TextureType GetType() const {
259 return type; 256 return type;
260 } 257 }
261 258
262 bool IsArray() const { 259 constexpr bool IsArray() const {
263 return is_array; 260 return is_array;
264 } 261 }
265 262
266 bool IsShadow() const { 263 constexpr bool IsShadow() const {
267 return is_shadow; 264 return is_shadow;
268 } 265 }
269 266
270 bool IsBindless() const { 267 constexpr bool IsBindless() const {
271 return is_bindless; 268 return is_bindless;
272 } 269 }
273 270
274 std::pair<u32, u32> GetBindlessCBuf() const {
275 return {static_cast<u32>(offset >> 32), static_cast<u32>(offset)};
276 }
277
278 bool operator<(const Sampler& rhs) const {
279 return std::tie(index, offset, type, is_array, is_shadow, is_bindless) <
280 std::tie(rhs.index, rhs.offset, rhs.type, rhs.is_array, rhs.is_shadow,
281 rhs.is_bindless);
282 }
283
284private: 271private:
285 /// Offset in TSC memory from which to read the sampler object, as specified by the sampling 272 u32 index{}; ///< Emulated index given for the this sampler.
286 /// instruction. 273 u32 offset{}; ///< Offset in the const buffer from where the sampler is being read.
287 std::size_t offset{}; 274 u32 buffer{}; ///< Buffer where the bindless sampler is being read (unused on bound samplers).
288 std::size_t index{}; ///< Value used to index into the generated GLSL sampler array. 275
289 Tegra::Shader::TextureType type{}; ///< The type used to sample this texture (Texture2D, etc) 276 Tegra::Shader::TextureType type{}; ///< The type used to sample this texture (Texture2D, etc)
290 bool is_array{}; ///< Whether the texture is being sampled as an array texture or not. 277 bool is_array{}; ///< Whether the texture is being sampled as an array texture or not.
291 bool is_shadow{}; ///< Whether the texture is being sampled as a depth texture or not. 278 bool is_shadow{}; ///< Whether the texture is being sampled as a depth texture or not.
@@ -294,18 +281,13 @@ private:
294 281
295class Image final { 282class Image final {
296public: 283public:
297 constexpr explicit Image(std::size_t offset, std::size_t index, Tegra::Shader::ImageType type) 284 /// This constructor is for bound images
298 : offset{offset}, index{index}, type{type}, is_bindless{false} {} 285 constexpr explicit Image(u32 index, u32 offset, Tegra::Shader::ImageType type)
299 286 : index{index}, offset{offset}, type{type} {}
300 constexpr explicit Image(u32 cbuf_index, u32 cbuf_offset, std::size_t index,
301 Tegra::Shader::ImageType type)
302 : offset{(static_cast<u64>(cbuf_index) << 32) | cbuf_offset}, index{index}, type{type},
303 is_bindless{true} {}
304 287
305 constexpr explicit Image(std::size_t offset, std::size_t index, Tegra::Shader::ImageType type, 288 /// This constructor is for bindless samplers
306 bool is_bindless, bool is_written, bool is_read, bool is_atomic) 289 constexpr explicit Image(u32 index, u32 offset, u32 buffer, Tegra::Shader::ImageType type)
307 : offset{offset}, index{index}, type{type}, is_bindless{is_bindless}, 290 : index{index}, offset{offset}, buffer{buffer}, type{type}, is_bindless{true} {}
308 is_written{is_written}, is_read{is_read}, is_atomic{is_atomic} {}
309 291
310 void MarkWrite() { 292 void MarkWrite() {
311 is_written = true; 293 is_written = true;
@@ -321,12 +303,16 @@ public:
321 is_atomic = true; 303 is_atomic = true;
322 } 304 }
323 305
324 constexpr std::size_t GetOffset() const { 306 constexpr u32 GetIndex() const {
307 return index;
308 }
309
310 constexpr u32 GetOffset() const {
325 return offset; 311 return offset;
326 } 312 }
327 313
328 constexpr std::size_t GetIndex() const { 314 constexpr u32 GetBuffer() const {
329 return index; 315 return buffer;
330 } 316 }
331 317
332 constexpr Tegra::Shader::ImageType GetType() const { 318 constexpr Tegra::Shader::ImageType GetType() const {
@@ -349,18 +335,11 @@ public:
349 return is_atomic; 335 return is_atomic;
350 } 336 }
351 337
352 constexpr std::pair<u32, u32> GetBindlessCBuf() const {
353 return {static_cast<u32>(offset >> 32), static_cast<u32>(offset)};
354 }
355
356 constexpr bool operator<(const Image& rhs) const {
357 return std::tie(offset, index, type, is_bindless) <
358 std::tie(rhs.offset, rhs.index, rhs.type, rhs.is_bindless);
359 }
360
361private: 338private:
362 u64 offset{}; 339 u32 index{};
363 std::size_t index{}; 340 u32 offset{};
341 u32 buffer{};
342
364 Tegra::Shader::ImageType type{}; 343 Tegra::Shader::ImageType type{};
365 bool is_bindless{}; 344 bool is_bindless{};
366 bool is_written{}; 345 bool is_written{};
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h
index 7582999a5..26c8fde22 100644
--- a/src/video_core/shader/shader_ir.h
+++ b/src/video_core/shader/shader_ir.h
@@ -5,6 +5,7 @@
5#pragma once 5#pragma once
6 6
7#include <array> 7#include <array>
8#include <list>
8#include <map> 9#include <map>
9#include <optional> 10#include <optional>
10#include <set> 11#include <set>
@@ -95,11 +96,11 @@ public:
95 return used_cbufs; 96 return used_cbufs;
96 } 97 }
97 98
98 const std::set<Sampler>& GetSamplers() const { 99 const std::list<Sampler>& GetSamplers() const {
99 return used_samplers; 100 return used_samplers;
100 } 101 }
101 102
102 const std::map<u64, Image>& GetImages() const { 103 const std::list<Image>& GetImages() const {
103 return used_images; 104 return used_images;
104 } 105 }
105 106
@@ -316,9 +317,6 @@ private:
316 /// Access a bindless image sampler. 317 /// Access a bindless image sampler.
317 Image& GetBindlessImage(Tegra::Shader::Register reg, Tegra::Shader::ImageType type); 318 Image& GetBindlessImage(Tegra::Shader::Register reg, Tegra::Shader::ImageType type);
318 319
319 /// Tries to access an existing image, updating it's state as needed
320 Image* TryUseExistingImage(u64 offset, Tegra::Shader::ImageType type);
321
322 /// Extracts a sequence of bits from a node 320 /// Extracts a sequence of bits from a node
323 Node BitfieldExtract(Node value, u32 offset, u32 bits); 321 Node BitfieldExtract(Node value, u32 offset, u32 bits);
324 322
@@ -326,7 +324,7 @@ private:
326 Node BitfieldInsert(Node base, Node insert, u32 offset, u32 bits); 324 Node BitfieldInsert(Node base, Node insert, u32 offset, u32 bits);
327 325
328 void WriteTexInstructionFloat(NodeBlock& bb, Tegra::Shader::Instruction instr, 326 void WriteTexInstructionFloat(NodeBlock& bb, Tegra::Shader::Instruction instr,
329 const Node4& components, bool is_tld4 = false); 327 const Node4& components);
330 328
331 void WriteTexsInstructionFloat(NodeBlock& bb, Tegra::Shader::Instruction instr, 329 void WriteTexsInstructionFloat(NodeBlock& bb, Tegra::Shader::Instruction instr,
332 const Node4& components, bool ignore_mask = false); 330 const Node4& components, bool ignore_mask = false);
@@ -402,8 +400,8 @@ private:
402 std::set<Tegra::Shader::Attribute::Index> used_input_attributes; 400 std::set<Tegra::Shader::Attribute::Index> used_input_attributes;
403 std::set<Tegra::Shader::Attribute::Index> used_output_attributes; 401 std::set<Tegra::Shader::Attribute::Index> used_output_attributes;
404 std::map<u32, ConstBuffer> used_cbufs; 402 std::map<u32, ConstBuffer> used_cbufs;
405 std::set<Sampler> used_samplers; 403 std::list<Sampler> used_samplers;
406 std::map<u64, Image> used_images; 404 std::list<Image> used_images;
407 std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances> used_clip_distances{}; 405 std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances> used_clip_distances{};
408 std::map<GlobalMemoryBase, GlobalMemoryUsage> used_global_memory; 406 std::map<GlobalMemoryBase, GlobalMemoryUsage> used_global_memory;
409 bool uses_layer{}; 407 bool uses_layer{};
diff --git a/src/video_core/textures/texture.h b/src/video_core/textures/texture.h
index 0429af9c1..27c8ce975 100644
--- a/src/video_core/textures/texture.h
+++ b/src/video_core/textures/texture.h
@@ -132,6 +132,8 @@ enum class SwizzleSource : u32 {
132}; 132};
133 133
134union TextureHandle { 134union TextureHandle {
135 TextureHandle(u32 raw) : raw{raw} {}
136
135 u32 raw; 137 u32 raw;
136 BitField<0, 20, u32> tic_id; 138 BitField<0, 20, u32> tic_id;
137 BitField<20, 12, u32> tsc_id; 139 BitField<20, 12, u32> tsc_id;
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index c5b9aa08f..188f798c0 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -172,17 +172,6 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeWaitObject::GetChildren() con
172 return list; 172 return list;
173} 173}
174 174
175QString WaitTreeWaitObject::GetResetTypeQString(Kernel::ResetType reset_type) {
176 switch (reset_type) {
177 case Kernel::ResetType::Automatic:
178 return tr("automatic reset");
179 case Kernel::ResetType::Manual:
180 return tr("manual reset");
181 }
182 UNREACHABLE();
183 return {};
184}
185
186WaitTreeObjectList::WaitTreeObjectList( 175WaitTreeObjectList::WaitTreeObjectList(
187 const std::vector<Kernel::SharedPtr<Kernel::WaitObject>>& list, bool w_all) 176 const std::vector<Kernel::SharedPtr<Kernel::WaitObject>>& list, bool w_all)
188 : object_list(list), wait_all(w_all) {} 177 : object_list(list), wait_all(w_all) {}
@@ -336,16 +325,6 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const {
336WaitTreeEvent::WaitTreeEvent(const Kernel::ReadableEvent& object) : WaitTreeWaitObject(object) {} 325WaitTreeEvent::WaitTreeEvent(const Kernel::ReadableEvent& object) : WaitTreeWaitObject(object) {}
337WaitTreeEvent::~WaitTreeEvent() = default; 326WaitTreeEvent::~WaitTreeEvent() = default;
338 327
339std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeEvent::GetChildren() const {
340 std::vector<std::unique_ptr<WaitTreeItem>> list(WaitTreeWaitObject::GetChildren());
341
342 list.push_back(std::make_unique<WaitTreeText>(
343 tr("reset type = %1")
344 .arg(GetResetTypeQString(
345 static_cast<const Kernel::ReadableEvent&>(object).GetResetType()))));
346 return list;
347}
348
349WaitTreeThreadList::WaitTreeThreadList(const std::vector<Kernel::SharedPtr<Kernel::Thread>>& list) 328WaitTreeThreadList::WaitTreeThreadList(const std::vector<Kernel::SharedPtr<Kernel::Thread>>& list)
350 : thread_list(list) {} 329 : thread_list(list) {}
351WaitTreeThreadList::~WaitTreeThreadList() = default; 330WaitTreeThreadList::~WaitTreeThreadList() = default;
diff --git a/src/yuzu/debugger/wait_tree.h b/src/yuzu/debugger/wait_tree.h
index 62886609d..f2b13be24 100644
--- a/src/yuzu/debugger/wait_tree.h
+++ b/src/yuzu/debugger/wait_tree.h
@@ -111,8 +111,6 @@ public:
111 111
112protected: 112protected:
113 const Kernel::WaitObject& object; 113 const Kernel::WaitObject& object;
114
115 static QString GetResetTypeQString(Kernel::ResetType reset_type);
116}; 114};
117 115
118class WaitTreeObjectList : public WaitTreeExpandableItem { 116class WaitTreeObjectList : public WaitTreeExpandableItem {
@@ -146,8 +144,6 @@ class WaitTreeEvent : public WaitTreeWaitObject {
146public: 144public:
147 explicit WaitTreeEvent(const Kernel::ReadableEvent& object); 145 explicit WaitTreeEvent(const Kernel::ReadableEvent& object);
148 ~WaitTreeEvent() override; 146 ~WaitTreeEvent() override;
149
150 std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
151}; 147};
152 148
153class WaitTreeThreadList : public WaitTreeExpandableItem { 149class WaitTreeThreadList : public WaitTreeExpandableItem {
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index d6bb18d24..160613ee1 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -1839,6 +1839,10 @@ void GMainWindow::OnLoadAmiibo() {
1839 return; 1839 return;
1840 } 1840 }
1841 1841
1842 LoadAmiibo(filename);
1843}
1844
1845void GMainWindow::LoadAmiibo(const QString& filename) {
1842 Core::System& system{Core::System::GetInstance()}; 1846 Core::System& system{Core::System::GetInstance()};
1843 Service::SM::ServiceManager& sm = system.ServiceManager(); 1847 Service::SM::ServiceManager& sm = system.ServiceManager();
1844 auto nfc = sm.GetService<Service::NFP::Module::Interface>("nfp:user"); 1848 auto nfc = sm.GetService<Service::NFP::Module::Interface>("nfp:user");
@@ -2189,10 +2193,19 @@ static bool IsSingleFileDropEvent(QDropEvent* event) {
2189} 2193}
2190 2194
2191void GMainWindow::dropEvent(QDropEvent* event) { 2195void GMainWindow::dropEvent(QDropEvent* event) {
2192 if (IsSingleFileDropEvent(event) && ConfirmChangeGame()) { 2196 if (!IsSingleFileDropEvent(event)) {
2193 const QMimeData* mimeData = event->mimeData(); 2197 return;
2194 QString filename = mimeData->urls().at(0).toLocalFile(); 2198 }
2195 BootGame(filename); 2199
2200 const QMimeData* mime_data = event->mimeData();
2201 const QString filename = mime_data->urls().at(0).toLocalFile();
2202
2203 if (emulation_running && QFileInfo(filename).suffix() == QStringLiteral("bin")) {
2204 LoadAmiibo(filename);
2205 } else {
2206 if (ConfirmChangeGame()) {
2207 BootGame(filename);
2208 }
2196 } 2209 }
2197} 2210}
2198 2211
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index fd4b9ccf5..7f46bea2b 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -142,6 +142,7 @@ private:
142 142
143 void ShowTelemetryCallout(); 143 void ShowTelemetryCallout();
144 void SetDiscordEnabled(bool state); 144 void SetDiscordEnabled(bool state);
145 void LoadAmiibo(const QString& filename);
145 146
146 void SelectAndSetCurrentUser(); 147 void SelectAndSetCurrentUser();
147 148