summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--externals/CMakeLists.txt4
m---------externals/fmt0
-rw-r--r--src/common/file_util.cpp9
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp32
-rw-r--r--src/core/hle/kernel/hle_ipc.h12
-rw-r--r--src/core/hle/kernel/memory/slab_heap.h4
-rw-r--r--src/core/hle/service/am/am.cpp4
-rw-r--r--src/core/hle/service/audio/audren_u.cpp2
-rw-r--r--src/core/hle/service/es/es.cpp1
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp2
-rw-r--r--src/core/hle/service/time/standard_network_system_clock_core.h2
-rw-r--r--src/core/hle/service/time/steady_clock_core.h1
-rw-r--r--src/core/hle/service/time/system_clock_context_update_callback.h2
-rw-r--r--src/core/hle/service/time/system_clock_core.cpp2
-rw-r--r--src/core/hle/service/time/system_clock_core.h2
-rw-r--r--src/core/loader/nso.cpp2
-rw-r--r--src/video_core/dma_pusher.cpp4
-rw-r--r--src/video_core/dma_pusher.h11
-rw-r--r--src/video_core/gpu.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp1
-rw-r--r--src/video_core/renderer_opengl/maxwell_to_gl.h2
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.cpp6
-rw-r--r--src/video_core/renderer_vulkan/shaders/quad_indexed.comp50
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pass.cpp205
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pass.h19
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp17
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.h1
-rw-r--r--src/video_core/shader/track.cpp11
-rw-r--r--src/video_core/texture_cache/format_lookup_table.cpp6
-rw-r--r--src/yuzu/main.cpp62
-rw-r--r--src/yuzu/main.h2
-rw-r--r--src/yuzu/main.ui18
33 files changed, 370 insertions, 130 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 467d769a2..c906c5a50 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -164,7 +164,7 @@ if (ENABLE_SDL2)
164 set(SDL2_LIBRARIES "SDL2::SDL2") 164 set(SDL2_LIBRARIES "SDL2::SDL2")
165 endif() 165 endif()
166 166
167 include_directories(${SDL2_INCLUDE_DIRS}) 167 include_directories(SYSTEM ${SDL2_INCLUDE_DIRS})
168 add_library(SDL2 INTERFACE) 168 add_library(SDL2 INTERFACE)
169 target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARIES}") 169 target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARIES}")
170 endif() 170 endif()
diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt
index d4421f697..653c64f47 100644
--- a/externals/CMakeLists.txt
+++ b/externals/CMakeLists.txt
@@ -16,11 +16,11 @@ add_library(catch-single-include INTERFACE)
16target_include_directories(catch-single-include INTERFACE catch/single_include) 16target_include_directories(catch-single-include INTERFACE catch/single_include)
17 17
18# libfmt 18# libfmt
19pkg_check_modules(FMT IMPORTED_TARGET GLOBAL fmt>=6.1.0) 19pkg_check_modules(FMT IMPORTED_TARGET GLOBAL fmt>=6.2.0)
20if (FMT_FOUND) 20if (FMT_FOUND)
21 add_library(fmt::fmt ALIAS PkgConfig::FMT) 21 add_library(fmt::fmt ALIAS PkgConfig::FMT)
22else() 22else()
23 message(STATUS "fmt 6.1.0 or newer not found, falling back to externals") 23 message(STATUS "fmt 6.2.0 or newer not found, falling back to externals")
24 add_subdirectory(fmt) 24 add_subdirectory(fmt)
25 add_library(fmt::fmt ALIAS fmt) 25 add_library(fmt::fmt ALIAS fmt)
26endif() 26endif()
diff --git a/externals/fmt b/externals/fmt
Subproject 4b8f8fac96a7819f28f4be523ca10a2d5d8aaaf Subproject 9bdd1596cef1b57b9556f8bef32dc4a32322ef3
diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp
index 7f613891b..45b750e1e 100644
--- a/src/common/file_util.cpp
+++ b/src/common/file_util.cpp
@@ -888,7 +888,14 @@ std::string SanitizePath(std::string_view path_, DirectorySeparator directory_se
888 } 888 }
889 889
890 std::replace(path.begin(), path.end(), type1, type2); 890 std::replace(path.begin(), path.end(), type1, type2);
891 path.erase(std::unique(path.begin(), path.end(), 891
892 auto start = path.begin();
893#ifdef _WIN32
894 // allow network paths which start with a double backslash (e.g. \\server\share)
895 if (start != path.end())
896 ++start;
897#endif
898 path.erase(std::unique(start, path.end(),
892 [type2](char c1, char c2) { return c1 == type2 && c2 == type2; }), 899 [type2](char c1, char c2) { return c1 == type2 && c2 == type2; }),
893 path.end()); 900 path.end());
894 return std::string(RemoveTrailingSlash(path)); 901 return std::string(RemoveTrailingSlash(path));
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index d65dae3ae..91d94025c 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -282,19 +282,19 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(Thread& thread) {
282 return RESULT_SUCCESS; 282 return RESULT_SUCCESS;
283} 283}
284 284
285std::vector<u8> HLERequestContext::ReadBuffer(int buffer_index) const { 285std::vector<u8> HLERequestContext::ReadBuffer(std::size_t buffer_index) const {
286 std::vector<u8> buffer; 286 std::vector<u8> buffer;
287 const bool is_buffer_a{BufferDescriptorA().size() > std::size_t(buffer_index) && 287 const bool is_buffer_a{BufferDescriptorA().size() > buffer_index &&
288 BufferDescriptorA()[buffer_index].Size()}; 288 BufferDescriptorA()[buffer_index].Size()};
289 auto& memory = Core::System::GetInstance().Memory(); 289 auto& memory = Core::System::GetInstance().Memory();
290 290
291 if (is_buffer_a) { 291 if (is_buffer_a) {
292 ASSERT_MSG(BufferDescriptorA().size() > std::size_t(buffer_index), 292 ASSERT_MSG(BufferDescriptorA().size() > buffer_index,
293 "BufferDescriptorA invalid buffer_index {}", buffer_index); 293 "BufferDescriptorA invalid buffer_index {}", buffer_index);
294 buffer.resize(BufferDescriptorA()[buffer_index].Size()); 294 buffer.resize(BufferDescriptorA()[buffer_index].Size());
295 memory.ReadBlock(BufferDescriptorA()[buffer_index].Address(), buffer.data(), buffer.size()); 295 memory.ReadBlock(BufferDescriptorA()[buffer_index].Address(), buffer.data(), buffer.size());
296 } else { 296 } else {
297 ASSERT_MSG(BufferDescriptorX().size() > std::size_t(buffer_index), 297 ASSERT_MSG(BufferDescriptorX().size() > buffer_index,
298 "BufferDescriptorX invalid buffer_index {}", buffer_index); 298 "BufferDescriptorX invalid buffer_index {}", buffer_index);
299 buffer.resize(BufferDescriptorX()[buffer_index].Size()); 299 buffer.resize(BufferDescriptorX()[buffer_index].Size());
300 memory.ReadBlock(BufferDescriptorX()[buffer_index].Address(), buffer.data(), buffer.size()); 300 memory.ReadBlock(BufferDescriptorX()[buffer_index].Address(), buffer.data(), buffer.size());
@@ -304,13 +304,13 @@ std::vector<u8> HLERequestContext::ReadBuffer(int buffer_index) const {
304} 304}
305 305
306std::size_t HLERequestContext::WriteBuffer(const void* buffer, std::size_t size, 306std::size_t HLERequestContext::WriteBuffer(const void* buffer, std::size_t size,
307 int buffer_index) const { 307 std::size_t buffer_index) const {
308 if (size == 0) { 308 if (size == 0) {
309 LOG_WARNING(Core, "skip empty buffer write"); 309 LOG_WARNING(Core, "skip empty buffer write");
310 return 0; 310 return 0;
311 } 311 }
312 312
313 const bool is_buffer_b{BufferDescriptorB().size() > std::size_t(buffer_index) && 313 const bool is_buffer_b{BufferDescriptorB().size() > buffer_index &&
314 BufferDescriptorB()[buffer_index].Size()}; 314 BufferDescriptorB()[buffer_index].Size()};
315 const std::size_t buffer_size{GetWriteBufferSize(buffer_index)}; 315 const std::size_t buffer_size{GetWriteBufferSize(buffer_index)};
316 if (size > buffer_size) { 316 if (size > buffer_size) {
@@ -321,13 +321,13 @@ std::size_t HLERequestContext::WriteBuffer(const void* buffer, std::size_t size,
321 321
322 auto& memory = Core::System::GetInstance().Memory(); 322 auto& memory = Core::System::GetInstance().Memory();
323 if (is_buffer_b) { 323 if (is_buffer_b) {
324 ASSERT_MSG(BufferDescriptorB().size() > std::size_t(buffer_index), 324 ASSERT_MSG(BufferDescriptorB().size() > buffer_index,
325 "BufferDescriptorB invalid buffer_index {}", buffer_index); 325 "BufferDescriptorB invalid buffer_index {}", buffer_index);
326 ASSERT_MSG(BufferDescriptorB()[buffer_index].Size() >= size, 326 ASSERT_MSG(BufferDescriptorB()[buffer_index].Size() >= size,
327 "BufferDescriptorB buffer_index {} is not large enough", buffer_index); 327 "BufferDescriptorB buffer_index {} is not large enough", buffer_index);
328 memory.WriteBlock(BufferDescriptorB()[buffer_index].Address(), buffer, size); 328 memory.WriteBlock(BufferDescriptorB()[buffer_index].Address(), buffer, size);
329 } else { 329 } else {
330 ASSERT_MSG(BufferDescriptorC().size() > std::size_t(buffer_index), 330 ASSERT_MSG(BufferDescriptorC().size() > buffer_index,
331 "BufferDescriptorC invalid buffer_index {}", buffer_index); 331 "BufferDescriptorC invalid buffer_index {}", buffer_index);
332 ASSERT_MSG(BufferDescriptorC()[buffer_index].Size() >= size, 332 ASSERT_MSG(BufferDescriptorC()[buffer_index].Size() >= size,
333 "BufferDescriptorC buffer_index {} is not large enough", buffer_index); 333 "BufferDescriptorC buffer_index {} is not large enough", buffer_index);
@@ -337,17 +337,17 @@ std::size_t HLERequestContext::WriteBuffer(const void* buffer, std::size_t size,
337 return size; 337 return size;
338} 338}
339 339
340std::size_t HLERequestContext::GetReadBufferSize(int buffer_index) const { 340std::size_t HLERequestContext::GetReadBufferSize(std::size_t buffer_index) const {
341 const bool is_buffer_a{BufferDescriptorA().size() > std::size_t(buffer_index) && 341 const bool is_buffer_a{BufferDescriptorA().size() > buffer_index &&
342 BufferDescriptorA()[buffer_index].Size()}; 342 BufferDescriptorA()[buffer_index].Size()};
343 if (is_buffer_a) { 343 if (is_buffer_a) {
344 ASSERT_MSG(BufferDescriptorA().size() > std::size_t(buffer_index), 344 ASSERT_MSG(BufferDescriptorA().size() > buffer_index,
345 "BufferDescriptorA invalid buffer_index {}", buffer_index); 345 "BufferDescriptorA invalid buffer_index {}", buffer_index);
346 ASSERT_MSG(BufferDescriptorA()[buffer_index].Size() > 0, 346 ASSERT_MSG(BufferDescriptorA()[buffer_index].Size() > 0,
347 "BufferDescriptorA buffer_index {} is empty", buffer_index); 347 "BufferDescriptorA buffer_index {} is empty", buffer_index);
348 return BufferDescriptorA()[buffer_index].Size(); 348 return BufferDescriptorA()[buffer_index].Size();
349 } else { 349 } else {
350 ASSERT_MSG(BufferDescriptorX().size() > std::size_t(buffer_index), 350 ASSERT_MSG(BufferDescriptorX().size() > buffer_index,
351 "BufferDescriptorX invalid buffer_index {}", buffer_index); 351 "BufferDescriptorX invalid buffer_index {}", buffer_index);
352 ASSERT_MSG(BufferDescriptorX()[buffer_index].Size() > 0, 352 ASSERT_MSG(BufferDescriptorX()[buffer_index].Size() > 0,
353 "BufferDescriptorX buffer_index {} is empty", buffer_index); 353 "BufferDescriptorX buffer_index {} is empty", buffer_index);
@@ -355,15 +355,15 @@ std::size_t HLERequestContext::GetReadBufferSize(int buffer_index) const {
355 } 355 }
356} 356}
357 357
358std::size_t HLERequestContext::GetWriteBufferSize(int buffer_index) const { 358std::size_t HLERequestContext::GetWriteBufferSize(std::size_t buffer_index) const {
359 const bool is_buffer_b{BufferDescriptorB().size() > std::size_t(buffer_index) && 359 const bool is_buffer_b{BufferDescriptorB().size() > buffer_index &&
360 BufferDescriptorB()[buffer_index].Size()}; 360 BufferDescriptorB()[buffer_index].Size()};
361 if (is_buffer_b) { 361 if (is_buffer_b) {
362 ASSERT_MSG(BufferDescriptorB().size() > std::size_t(buffer_index), 362 ASSERT_MSG(BufferDescriptorB().size() > buffer_index,
363 "BufferDescriptorB invalid buffer_index {}", buffer_index); 363 "BufferDescriptorB invalid buffer_index {}", buffer_index);
364 return BufferDescriptorB()[buffer_index].Size(); 364 return BufferDescriptorB()[buffer_index].Size();
365 } else { 365 } else {
366 ASSERT_MSG(BufferDescriptorC().size() > std::size_t(buffer_index), 366 ASSERT_MSG(BufferDescriptorC().size() > buffer_index,
367 "BufferDescriptorC invalid buffer_index {}", buffer_index); 367 "BufferDescriptorC invalid buffer_index {}", buffer_index);
368 return BufferDescriptorC()[buffer_index].Size(); 368 return BufferDescriptorC()[buffer_index].Size();
369 } 369 }
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h
index 050ad8fd7..af3330297 100644
--- a/src/core/hle/kernel/hle_ipc.h
+++ b/src/core/hle/kernel/hle_ipc.h
@@ -179,10 +179,11 @@ public:
179 } 179 }
180 180
181 /// Helper function to read a buffer using the appropriate buffer descriptor 181 /// Helper function to read a buffer using the appropriate buffer descriptor
182 std::vector<u8> ReadBuffer(int buffer_index = 0) const; 182 std::vector<u8> ReadBuffer(std::size_t buffer_index = 0) const;
183 183
184 /// Helper function to write a buffer using the appropriate buffer descriptor 184 /// Helper function to write a buffer using the appropriate buffer descriptor
185 std::size_t WriteBuffer(const void* buffer, std::size_t size, int buffer_index = 0) const; 185 std::size_t WriteBuffer(const void* buffer, std::size_t size,
186 std::size_t buffer_index = 0) const;
186 187
187 /* Helper function to write a buffer using the appropriate buffer descriptor 188 /* Helper function to write a buffer using the appropriate buffer descriptor
188 * 189 *
@@ -194,7 +195,8 @@ public:
194 */ 195 */
195 template <typename ContiguousContainer, 196 template <typename ContiguousContainer,
196 typename = std::enable_if_t<!std::is_pointer_v<ContiguousContainer>>> 197 typename = std::enable_if_t<!std::is_pointer_v<ContiguousContainer>>>
197 std::size_t WriteBuffer(const ContiguousContainer& container, int buffer_index = 0) const { 198 std::size_t WriteBuffer(const ContiguousContainer& container,
199 std::size_t buffer_index = 0) const {
198 using ContiguousType = typename ContiguousContainer::value_type; 200 using ContiguousType = typename ContiguousContainer::value_type;
199 201
200 static_assert(std::is_trivially_copyable_v<ContiguousType>, 202 static_assert(std::is_trivially_copyable_v<ContiguousType>,
@@ -205,10 +207,10 @@ public:
205 } 207 }
206 208
207 /// Helper function to get the size of the input buffer 209 /// Helper function to get the size of the input buffer
208 std::size_t GetReadBufferSize(int buffer_index = 0) const; 210 std::size_t GetReadBufferSize(std::size_t buffer_index = 0) const;
209 211
210 /// Helper function to get the size of the output buffer 212 /// Helper function to get the size of the output buffer
211 std::size_t GetWriteBufferSize(int buffer_index = 0) const; 213 std::size_t GetWriteBufferSize(std::size_t buffer_index = 0) const;
212 214
213 template <typename T> 215 template <typename T>
214 std::shared_ptr<T> GetCopyObject(std::size_t index) { 216 std::shared_ptr<T> GetCopyObject(std::size_t index) {
diff --git a/src/core/hle/kernel/memory/slab_heap.h b/src/core/hle/kernel/memory/slab_heap.h
index 049403e15..be95fc3f7 100644
--- a/src/core/hle/kernel/memory/slab_heap.h
+++ b/src/core/hle/kernel/memory/slab_heap.h
@@ -51,7 +51,7 @@ public:
51 } 51 }
52 52
53 void Free(void* obj) { 53 void Free(void* obj) {
54 Node* node = reinterpret_cast<Node*>(obj); 54 Node* node = static_cast<Node*>(obj);
55 55
56 Node* cur_head = head.load(); 56 Node* cur_head = head.load();
57 do { 57 do {
@@ -145,7 +145,7 @@ public:
145 } 145 }
146 146
147 T* Allocate() { 147 T* Allocate() {
148 T* obj = reinterpret_cast<T*>(AllocateImpl()); 148 T* obj = static_cast<T*>(AllocateImpl());
149 if (obj != nullptr) { 149 if (obj != nullptr) {
150 new (obj) T(); 150 new (obj) T();
151 } 151 }
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 557608e76..3ece2cf3c 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -903,7 +903,7 @@ private:
903 void PopOutData(Kernel::HLERequestContext& ctx) { 903 void PopOutData(Kernel::HLERequestContext& ctx) {
904 LOG_DEBUG(Service_AM, "called"); 904 LOG_DEBUG(Service_AM, "called");
905 905
906 const auto storage = applet->GetBroker().PopNormalDataToGame(); 906 auto storage = applet->GetBroker().PopNormalDataToGame();
907 if (storage == nullptr) { 907 if (storage == nullptr) {
908 LOG_ERROR(Service_AM, 908 LOG_ERROR(Service_AM,
909 "storage is a nullptr. There is no data in the current normal channel"); 909 "storage is a nullptr. There is no data in the current normal channel");
@@ -934,7 +934,7 @@ private:
934 void PopInteractiveOutData(Kernel::HLERequestContext& ctx) { 934 void PopInteractiveOutData(Kernel::HLERequestContext& ctx) {
935 LOG_DEBUG(Service_AM, "called"); 935 LOG_DEBUG(Service_AM, "called");
936 936
937 const auto storage = applet->GetBroker().PopInteractiveDataToGame(); 937 auto storage = applet->GetBroker().PopInteractiveDataToGame();
938 if (storage == nullptr) { 938 if (storage == nullptr) {
939 LOG_ERROR(Service_AM, 939 LOG_ERROR(Service_AM,
940 "storage is a nullptr. There is no data in the current interactive channel"); 940 "storage is a nullptr. There is no data in the current interactive channel");
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index 175cabf45..851433595 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -252,8 +252,6 @@ private:
252 } 252 }
253 253
254 void GetAudioDeviceOutputVolume(Kernel::HLERequestContext& ctx) { 254 void GetAudioDeviceOutputVolume(Kernel::HLERequestContext& ctx) {
255 IPC::RequestParser rp{ctx};
256
257 const auto device_name_buffer = ctx.ReadBuffer(); 255 const auto device_name_buffer = ctx.ReadBuffer();
258 const std::string name = Common::StringFromBuffer(device_name_buffer); 256 const std::string name = Common::StringFromBuffer(device_name_buffer);
259 257
diff --git a/src/core/hle/service/es/es.cpp b/src/core/hle/service/es/es.cpp
index df00ae625..86f36915a 100644
--- a/src/core/hle/service/es/es.cpp
+++ b/src/core/hle/service/es/es.cpp
@@ -76,7 +76,6 @@ private:
76 } 76 }
77 77
78 void ImportTicket(Kernel::HLERequestContext& ctx) { 78 void ImportTicket(Kernel::HLERequestContext& ctx) {
79 IPC::RequestParser rp{ctx};
80 const auto ticket = ctx.ReadBuffer(); 79 const auto ticket = ctx.ReadBuffer();
81 const auto cert = ctx.ReadBuffer(1); 80 const auto cert = ctx.ReadBuffer(1);
82 81
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index c1e32b28c..2ccfffc19 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -107,6 +107,7 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) {
107 switch (controller_type) { 107 switch (controller_type) {
108 case NPadControllerType::None: 108 case NPadControllerType::None:
109 UNREACHABLE(); 109 UNREACHABLE();
110 break;
110 case NPadControllerType::Handheld: 111 case NPadControllerType::Handheld:
111 controller.joy_styles.handheld.Assign(1); 112 controller.joy_styles.handheld.Assign(1);
112 controller.device_type.handheld.Assign(1); 113 controller.device_type.handheld.Assign(1);
@@ -363,6 +364,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
363 switch (controller_type) { 364 switch (controller_type) {
364 case NPadControllerType::None: 365 case NPadControllerType::None:
365 UNREACHABLE(); 366 UNREACHABLE();
367 break;
366 case NPadControllerType::Handheld: 368 case NPadControllerType::Handheld:
367 handheld_entry.connection_status.raw = 0; 369 handheld_entry.connection_status.raw = 0;
368 handheld_entry.connection_status.IsWired.Assign(1); 370 handheld_entry.connection_status.IsWired.Assign(1);
diff --git a/src/core/hle/service/time/standard_network_system_clock_core.h b/src/core/hle/service/time/standard_network_system_clock_core.h
index 3f505c37c..c993bdf79 100644
--- a/src/core/hle/service/time/standard_network_system_clock_core.h
+++ b/src/core/hle/service/time/standard_network_system_clock_core.h
@@ -23,7 +23,7 @@ public:
23 standard_network_clock_sufficient_accuracy = value; 23 standard_network_clock_sufficient_accuracy = value;
24 } 24 }
25 25
26 bool IsStandardNetworkSystemClockAccuracySufficient(Core::System& system) { 26 bool IsStandardNetworkSystemClockAccuracySufficient(Core::System& system) const {
27 SystemClockContext context{}; 27 SystemClockContext context{};
28 if (GetClockContext(system, context) != RESULT_SUCCESS) { 28 if (GetClockContext(system, context) != RESULT_SUCCESS) {
29 return {}; 29 return {};
diff --git a/src/core/hle/service/time/steady_clock_core.h b/src/core/hle/service/time/steady_clock_core.h
index 84af3d105..d80a2385f 100644
--- a/src/core/hle/service/time/steady_clock_core.h
+++ b/src/core/hle/service/time/steady_clock_core.h
@@ -16,6 +16,7 @@ namespace Service::Time::Clock {
16class SteadyClockCore { 16class SteadyClockCore {
17public: 17public:
18 SteadyClockCore() = default; 18 SteadyClockCore() = default;
19 virtual ~SteadyClockCore() = default;
19 20
20 const Common::UUID& GetClockSourceId() const { 21 const Common::UUID& GetClockSourceId() const {
21 return clock_source_id; 22 return clock_source_id;
diff --git a/src/core/hle/service/time/system_clock_context_update_callback.h b/src/core/hle/service/time/system_clock_context_update_callback.h
index 6260de6c3..2b0fa7e75 100644
--- a/src/core/hle/service/time/system_clock_context_update_callback.h
+++ b/src/core/hle/service/time/system_clock_context_update_callback.h
@@ -20,7 +20,7 @@ namespace Service::Time::Clock {
20class SystemClockContextUpdateCallback { 20class SystemClockContextUpdateCallback {
21public: 21public:
22 SystemClockContextUpdateCallback(); 22 SystemClockContextUpdateCallback();
23 ~SystemClockContextUpdateCallback(); 23 virtual ~SystemClockContextUpdateCallback();
24 24
25 bool NeedUpdate(const SystemClockContext& value) const; 25 bool NeedUpdate(const SystemClockContext& value) const;
26 26
diff --git a/src/core/hle/service/time/system_clock_core.cpp b/src/core/hle/service/time/system_clock_core.cpp
index 1a3ab8cfa..d31d4e2ca 100644
--- a/src/core/hle/service/time/system_clock_core.cpp
+++ b/src/core/hle/service/time/system_clock_core.cpp
@@ -9,7 +9,7 @@
9namespace Service::Time::Clock { 9namespace Service::Time::Clock {
10 10
11SystemClockCore::SystemClockCore(SteadyClockCore& steady_clock_core) 11SystemClockCore::SystemClockCore(SteadyClockCore& steady_clock_core)
12 : steady_clock_core{steady_clock_core}, is_initialized{} { 12 : steady_clock_core{steady_clock_core} {
13 context.steady_time_point.clock_source_id = steady_clock_core.GetClockSourceId(); 13 context.steady_time_point.clock_source_id = steady_clock_core.GetClockSourceId();
14} 14}
15 15
diff --git a/src/core/hle/service/time/system_clock_core.h b/src/core/hle/service/time/system_clock_core.h
index 54407a6c5..608dd3b2e 100644
--- a/src/core/hle/service/time/system_clock_core.h
+++ b/src/core/hle/service/time/system_clock_core.h
@@ -22,7 +22,7 @@ class SystemClockContextUpdateCallback;
22class SystemClockCore { 22class SystemClockCore {
23public: 23public:
24 explicit SystemClockCore(SteadyClockCore& steady_clock_core); 24 explicit SystemClockCore(SteadyClockCore& steady_clock_core);
25 ~SystemClockCore(); 25 virtual ~SystemClockCore();
26 26
27 SteadyClockCore& GetSteadyClockCore() const { 27 SteadyClockCore& GetSteadyClockCore() const {
28 return steady_clock_core; 28 return steady_clock_core;
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp
index 612ff9bf6..575330a86 100644
--- a/src/core/loader/nso.cpp
+++ b/src/core/loader/nso.cpp
@@ -37,7 +37,7 @@ static_assert(sizeof(MODHeader) == 0x1c, "MODHeader has incorrect size.");
37 37
38std::vector<u8> DecompressSegment(const std::vector<u8>& compressed_data, 38std::vector<u8> DecompressSegment(const std::vector<u8>& compressed_data,
39 const NSOSegmentHeader& header) { 39 const NSOSegmentHeader& header) {
40 const std::vector<u8> uncompressed_data = 40 std::vector<u8> uncompressed_data =
41 Common::Compression::DecompressDataLZ4(compressed_data, header.size); 41 Common::Compression::DecompressDataLZ4(compressed_data, header.size);
42 42
43 ASSERT_MSG(uncompressed_data.size() == header.size, "{} != {}", header.size, 43 ASSERT_MSG(uncompressed_data.size() == header.size, "{} != {}", header.size,
diff --git a/src/video_core/dma_pusher.cpp b/src/video_core/dma_pusher.cpp
index 713c14182..0b77afc71 100644
--- a/src/video_core/dma_pusher.cpp
+++ b/src/video_core/dma_pusher.cpp
@@ -12,7 +12,7 @@
12 12
13namespace Tegra { 13namespace Tegra {
14 14
15DmaPusher::DmaPusher(GPU& gpu) : gpu(gpu) {} 15DmaPusher::DmaPusher(Core::System& system, GPU& gpu) : gpu{gpu}, system{system} {}
16 16
17DmaPusher::~DmaPusher() = default; 17DmaPusher::~DmaPusher() = default;
18 18
@@ -26,7 +26,7 @@ void DmaPusher::DispatchCalls() {
26 26
27 dma_pushbuffer_subindex = 0; 27 dma_pushbuffer_subindex = 0;
28 28
29 while (Core::System::GetInstance().IsPoweredOn()) { 29 while (system.IsPoweredOn()) {
30 if (!Step()) { 30 if (!Step()) {
31 break; 31 break;
32 } 32 }
diff --git a/src/video_core/dma_pusher.h b/src/video_core/dma_pusher.h
index 6ab06518f..d6188614a 100644
--- a/src/video_core/dma_pusher.h
+++ b/src/video_core/dma_pusher.h
@@ -10,6 +10,10 @@
10#include "common/bit_field.h" 10#include "common/bit_field.h"
11#include "common/common_types.h" 11#include "common/common_types.h"
12 12
13namespace Core {
14class System;
15}
16
13namespace Tegra { 17namespace Tegra {
14 18
15enum class SubmissionMode : u32 { 19enum class SubmissionMode : u32 {
@@ -56,7 +60,7 @@ using CommandList = std::vector<Tegra::CommandListHeader>;
56 */ 60 */
57class DmaPusher { 61class DmaPusher {
58public: 62public:
59 explicit DmaPusher(GPU& gpu); 63 explicit DmaPusher(Core::System& system, GPU& gpu);
60 ~DmaPusher(); 64 ~DmaPusher();
61 65
62 void Push(CommandList&& entries) { 66 void Push(CommandList&& entries) {
@@ -72,8 +76,6 @@ private:
72 76
73 void CallMethod(u32 argument) const; 77 void CallMethod(u32 argument) const;
74 78
75 GPU& gpu;
76
77 std::vector<CommandHeader> command_headers; ///< Buffer for list of commands fetched at once 79 std::vector<CommandHeader> command_headers; ///< Buffer for list of commands fetched at once
78 80
79 std::queue<CommandList> dma_pushbuffer; ///< Queue of command lists to be processed 81 std::queue<CommandList> dma_pushbuffer; ///< Queue of command lists to be processed
@@ -92,6 +94,9 @@ private:
92 94
93 GPUVAddr dma_mget{}; ///< main pushbuffer last read address 95 GPUVAddr dma_mget{}; ///< main pushbuffer last read address
94 bool ib_enable{true}; ///< IB mode enabled 96 bool ib_enable{true}; ///< IB mode enabled
97
98 GPU& gpu;
99 Core::System& system;
95}; 100};
96 101
97} // namespace Tegra 102} // namespace Tegra
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp
index 8acf2eda2..a606f4abd 100644
--- a/src/video_core/gpu.cpp
+++ b/src/video_core/gpu.cpp
@@ -27,7 +27,7 @@ GPU::GPU(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& render
27 : system{system}, renderer{std::move(renderer_)}, is_async{is_async} { 27 : system{system}, renderer{std::move(renderer_)}, is_async{is_async} {
28 auto& rasterizer{renderer->Rasterizer()}; 28 auto& rasterizer{renderer->Rasterizer()};
29 memory_manager = std::make_unique<Tegra::MemoryManager>(system, rasterizer); 29 memory_manager = std::make_unique<Tegra::MemoryManager>(system, rasterizer);
30 dma_pusher = std::make_unique<Tegra::DmaPusher>(*this); 30 dma_pusher = std::make_unique<Tegra::DmaPusher>(system, *this);
31 maxwell_3d = std::make_unique<Engines::Maxwell3D>(system, rasterizer, *memory_manager); 31 maxwell_3d = std::make_unique<Engines::Maxwell3D>(system, rasterizer, *memory_manager);
32 fermi_2d = std::make_unique<Engines::Fermi2D>(rasterizer); 32 fermi_2d = std::make_unique<Engines::Fermi2D>(rasterizer);
33 kepler_compute = std::make_unique<Engines::KeplerCompute>(system, rasterizer, *memory_manager); 33 kepler_compute = std::make_unique<Engines::KeplerCompute>(system, rasterizer, *memory_manager);
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 9495f48a2..22242cce9 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -1145,6 +1145,7 @@ private:
1145 return {"gl_FragCoord"s + GetSwizzle(element), Type::Float}; 1145 return {"gl_FragCoord"s + GetSwizzle(element), Type::Float};
1146 default: 1146 default:
1147 UNREACHABLE(); 1147 UNREACHABLE();
1148 return {"0", Type::Int};
1148 } 1149 }
1149 case Attribute::Index::FrontColor: 1150 case Attribute::Index::FrontColor:
1150 return {"gl_Color"s + GetSwizzle(element), Type::Float}; 1151 return {"gl_Color"s + GetSwizzle(element), Type::Float};
diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h
index 89f0e04ef..2c0c77c28 100644
--- a/src/video_core/renderer_opengl/maxwell_to_gl.h
+++ b/src/video_core/renderer_opengl/maxwell_to_gl.h
@@ -191,6 +191,7 @@ inline GLenum TextureFilterMode(Tegra::Texture::TextureFilter filter_mode,
191 case Tegra::Texture::TextureMipmapFilter::Linear: 191 case Tegra::Texture::TextureMipmapFilter::Linear:
192 return GL_LINEAR_MIPMAP_LINEAR; 192 return GL_LINEAR_MIPMAP_LINEAR;
193 } 193 }
194 break;
194 } 195 }
195 case Tegra::Texture::TextureFilter::Nearest: { 196 case Tegra::Texture::TextureFilter::Nearest: {
196 switch (mip_filter_mode) { 197 switch (mip_filter_mode) {
@@ -201,6 +202,7 @@ inline GLenum TextureFilterMode(Tegra::Texture::TextureFilter filter_mode,
201 case Tegra::Texture::TextureMipmapFilter::Linear: 202 case Tegra::Texture::TextureMipmapFilter::Linear:
202 return GL_NEAREST_MIPMAP_LINEAR; 203 return GL_NEAREST_MIPMAP_LINEAR;
203 } 204 }
205 break;
204 } 206 }
205 } 207 }
206 LOG_ERROR(Render_OpenGL, "Unimplemented texture filter mode={}", static_cast<u32>(filter_mode)); 208 LOG_ERROR(Render_OpenGL, "Unimplemented texture filter mode={}", static_cast<u32>(filter_mode));
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
index dd590c38b..04532f8f8 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
@@ -42,7 +42,7 @@
42#include <vulkan/vulkan_win32.h> 42#include <vulkan/vulkan_win32.h>
43#endif 43#endif
44 44
45#ifdef __linux__ 45#if !defined(_WIN32) && !defined(__APPLE__)
46#include <X11/Xlib.h> 46#include <X11/Xlib.h>
47#include <vulkan/vulkan_wayland.h> 47#include <vulkan/vulkan_wayland.h>
48#include <vulkan/vulkan_xlib.h> 48#include <vulkan/vulkan_xlib.h>
@@ -119,7 +119,7 @@ vk::Instance CreateInstance(Common::DynamicLibrary& library, vk::InstanceDispatc
119 extensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME); 119 extensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
120 break; 120 break;
121#endif 121#endif
122#ifdef __linux__ 122#if !defined(_WIN32) && !defined(__APPLE__)
123 case Core::Frontend::WindowSystemType::X11: 123 case Core::Frontend::WindowSystemType::X11:
124 extensions.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME); 124 extensions.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
125 break; 125 break;
@@ -345,7 +345,7 @@ bool RendererVulkan::CreateSurface() {
345 } 345 }
346 } 346 }
347#endif 347#endif
348#ifdef __linux__ 348#if !defined(_WIN32) && !defined(__APPLE__)
349 if (window_info.type == Core::Frontend::WindowSystemType::X11) { 349 if (window_info.type == Core::Frontend::WindowSystemType::X11) {
350 const VkXlibSurfaceCreateInfoKHR xlib_ci{ 350 const VkXlibSurfaceCreateInfoKHR xlib_ci{
351 VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, nullptr, 0, 351 VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, nullptr, 0,
diff --git a/src/video_core/renderer_vulkan/shaders/quad_indexed.comp b/src/video_core/renderer_vulkan/shaders/quad_indexed.comp
new file mode 100644
index 000000000..5a472ba9b
--- /dev/null
+++ b/src/video_core/renderer_vulkan/shaders/quad_indexed.comp
@@ -0,0 +1,50 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5/*
6 * Build instructions:
7 * $ glslangValidator -V quad_indexed.comp -o output.spv
8 * $ spirv-opt -O --strip-debug output.spv -o optimized.spv
9 * $ xxd -i optimized.spv
10 *
11 * Then copy that bytecode to the C++ file
12 */
13
14#version 460 core
15
16layout (local_size_x = 1024) in;
17
18layout (std430, set = 0, binding = 0) readonly buffer InputBuffer {
19 uint input_indexes[];
20};
21
22layout (std430, set = 0, binding = 1) writeonly buffer OutputBuffer {
23 uint output_indexes[];
24};
25
26layout (push_constant) uniform PushConstants {
27 uint base_vertex;
28 int index_shift; // 0: uint8, 1: uint16, 2: uint32
29};
30
31void main() {
32 int primitive = int(gl_GlobalInvocationID.x);
33 if (primitive * 6 >= output_indexes.length()) {
34 return;
35 }
36
37 int index_size = 8 << index_shift;
38 int flipped_shift = 2 - index_shift;
39 int mask = (1 << flipped_shift) - 1;
40
41 const int quad_swizzle[6] = int[](0, 1, 2, 0, 2, 3);
42 for (uint vertex = 0; vertex < 6; ++vertex) {
43 int offset = primitive * 4 + quad_swizzle[vertex];
44 int int_offset = offset >> flipped_shift;
45 int bit_offset = (offset & mask) * index_size;
46 uint packed_input = input_indexes[int_offset];
47 uint index = bitfieldExtract(packed_input, bit_offset, index_size);
48 output_indexes[primitive * 6 + vertex] = index + base_vertex;
49 }
50}
diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.cpp b/src/video_core/renderer_vulkan/vk_compute_pass.cpp
index 878a78755..7b0268033 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pass.cpp
+++ b/src/video_core/renderer_vulkan/vk_compute_pass.cpp
@@ -135,11 +135,11 @@ VkDescriptorUpdateTemplateEntryKHR BuildQuadArrayPassDescriptorUpdateTemplateEnt
135 return entry; 135 return entry;
136} 136}
137 137
138VkPushConstantRange BuildQuadArrayPassPushConstantRange() { 138VkPushConstantRange BuildComputePushConstantRange(std::size_t size) {
139 VkPushConstantRange range; 139 VkPushConstantRange range;
140 range.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; 140 range.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
141 range.offset = 0; 141 range.offset = 0;
142 range.size = sizeof(u32); 142 range.size = static_cast<u32>(size);
143 return range; 143 return range;
144} 144}
145 145
@@ -220,7 +220,130 @@ constexpr u8 uint8_pass[] = {
220 0xf9, 0x00, 0x02, 0x00, 0x1d, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x1d, 0x00, 0x00, 0x00, 220 0xf9, 0x00, 0x02, 0x00, 0x1d, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x1d, 0x00, 0x00, 0x00,
221 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00}; 221 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00};
222 222
223std::array<VkDescriptorSetLayoutBinding, 2> BuildUint8PassDescriptorSetBindings() { 223// Quad indexed SPIR-V module. Generated from the "shaders/" directory.
224constexpr u8 QUAD_INDEXED_SPV[] = {
225 0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x07, 0x00, 0x08, 0x00, 0x7c, 0x00, 0x00, 0x00,
226 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00,
227 0x01, 0x00, 0x00, 0x00, 0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30,
228 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
229 0x0f, 0x00, 0x06, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e,
230 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00,
231 0x11, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
232 0x47, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
233 0x47, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
234 0x48, 0x00, 0x04, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
235 0x48, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
236 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x16, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
237 0x47, 0x00, 0x04, 0x00, 0x18, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
238 0x47, 0x00, 0x04, 0x00, 0x18, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
239 0x48, 0x00, 0x05, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
240 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x22, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
241 0x23, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x22, 0x00, 0x00, 0x00,
242 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x56, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
243 0x04, 0x00, 0x00, 0x00, 0x48, 0x00, 0x04, 0x00, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
244 0x18, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
245 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x57, 0x00, 0x00, 0x00,
246 0x03, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x59, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
247 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x59, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
248 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x72, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
249 0x19, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00,
250 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
251 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
252 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00,
253 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00,
254 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
255 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
256 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00,
257 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
258 0x01, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
259 0x13, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x03, 0x00, 0x15, 0x00, 0x00, 0x00,
260 0x09, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x03, 0x00, 0x16, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
261 0x20, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
262 0x3b, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
263 0x14, 0x00, 0x02, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
264 0x21, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x04, 0x00, 0x22, 0x00, 0x00, 0x00,
265 0x09, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00,
266 0x09, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00,
267 0x24, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
268 0x25, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x26, 0x00, 0x00, 0x00,
269 0x09, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
270 0x2b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00,
271 0x3b, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
272 0x3f, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x41, 0x00, 0x00, 0x00,
273 0x06, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
274 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
275 0x43, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x09, 0x00, 0x41, 0x00, 0x00, 0x00,
276 0x44, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
277 0x42, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
278 0x46, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x03, 0x00,
279 0x56, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x03, 0x00, 0x57, 0x00, 0x00, 0x00,
280 0x56, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x58, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
281 0x57, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x58, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00,
282 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x5b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
283 0x09, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
284 0x09, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
285 0x00, 0x04, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00,
286 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x06, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00,
287 0x70, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00,
288 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
289 0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x46, 0x00, 0x00, 0x00,
290 0x47, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x74, 0x00, 0x00, 0x00,
291 0xf8, 0x00, 0x02, 0x00, 0x74, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x04, 0x00, 0x73, 0x00, 0x00, 0x00,
292 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00, 0x75, 0x00, 0x00, 0x00,
293 0xf8, 0x00, 0x02, 0x00, 0x75, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x0e, 0x00, 0x00, 0x00,
294 0x0f, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
295 0x09, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x04, 0x00,
296 0x06, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x84, 0x00, 0x05, 0x00,
297 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
298 0x44, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
299 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
300 0x19, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x05, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
301 0x14, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x03, 0x00, 0x1e, 0x00, 0x00, 0x00,
302 0x00, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
303 0x1e, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x1d, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x02, 0x00,
304 0x73, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
305 0x26, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
306 0x3d, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
307 0xc4, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
308 0x28, 0x00, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00,
309 0x2b, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
310 0x31, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x82, 0x00, 0x05, 0x00,
311 0x06, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
312 0xf9, 0x00, 0x02, 0x00, 0x35, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x35, 0x00, 0x00, 0x00,
313 0xf5, 0x00, 0x07, 0x00, 0x09, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
314 0x1e, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0xb0, 0x00, 0x05, 0x00,
315 0x1b, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00,
316 0xf6, 0x00, 0x04, 0x00, 0x37, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
317 0xfa, 0x00, 0x04, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00,
318 0xf8, 0x00, 0x02, 0x00, 0x36, 0x00, 0x00, 0x00, 0x84, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
319 0x40, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
320 0x47, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00,
321 0x48, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
322 0x06, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00,
323 0x06, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00,
324 0xc3, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00,
325 0x2e, 0x00, 0x00, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00,
326 0x4a, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x84, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
327 0x54, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00,
328 0x5b, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00,
329 0x4e, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x00,
330 0x5c, 0x00, 0x00, 0x00, 0xcb, 0x00, 0x06, 0x00, 0x09, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00,
331 0x5d, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x04, 0x00,
332 0x09, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00,
333 0x09, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00,
334 0x41, 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
335 0x42, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00,
336 0x6a, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00,
337 0x62, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x41, 0x00, 0x06, 0x00, 0x5b, 0x00, 0x00, 0x00,
338 0x6d, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00,
339 0x3e, 0x00, 0x03, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x80, 0x00, 0x05, 0x00,
340 0x09, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
341 0xf9, 0x00, 0x02, 0x00, 0x35, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x37, 0x00, 0x00, 0x00,
342 0xf9, 0x00, 0x02, 0x00, 0x73, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x76, 0x00, 0x00, 0x00,
343 0xf9, 0x00, 0x02, 0x00, 0x74, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x73, 0x00, 0x00, 0x00,
344 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00};
345
346std::array<VkDescriptorSetLayoutBinding, 2> BuildInputOutputDescriptorSetBindings() {
224 std::array<VkDescriptorSetLayoutBinding, 2> bindings; 347 std::array<VkDescriptorSetLayoutBinding, 2> bindings;
225 bindings[0].binding = 0; 348 bindings[0].binding = 0;
226 bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; 349 bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
@@ -235,7 +358,7 @@ std::array<VkDescriptorSetLayoutBinding, 2> BuildUint8PassDescriptorSetBindings(
235 return bindings; 358 return bindings;
236} 359}
237 360
238VkDescriptorUpdateTemplateEntryKHR BuildUint8PassDescriptorUpdateTemplateEntry() { 361VkDescriptorUpdateTemplateEntryKHR BuildInputOutputDescriptorUpdateTemplate() {
239 VkDescriptorUpdateTemplateEntryKHR entry; 362 VkDescriptorUpdateTemplateEntryKHR entry;
240 entry.dstBinding = 0; 363 entry.dstBinding = 0;
241 entry.dstArrayElement = 0; 364 entry.dstArrayElement = 0;
@@ -337,14 +460,14 @@ QuadArrayPass::QuadArrayPass(const VKDevice& device, VKScheduler& scheduler,
337 VKUpdateDescriptorQueue& update_descriptor_queue) 460 VKUpdateDescriptorQueue& update_descriptor_queue)
338 : VKComputePass(device, descriptor_pool, BuildQuadArrayPassDescriptorSetLayoutBinding(), 461 : VKComputePass(device, descriptor_pool, BuildQuadArrayPassDescriptorSetLayoutBinding(),
339 BuildQuadArrayPassDescriptorUpdateTemplateEntry(), 462 BuildQuadArrayPassDescriptorUpdateTemplateEntry(),
340 BuildQuadArrayPassPushConstantRange(), std::size(quad_array), quad_array), 463 BuildComputePushConstantRange(sizeof(u32)), std::size(quad_array), quad_array),
341 scheduler{scheduler}, staging_buffer_pool{staging_buffer_pool}, 464 scheduler{scheduler}, staging_buffer_pool{staging_buffer_pool},
342 update_descriptor_queue{update_descriptor_queue} {} 465 update_descriptor_queue{update_descriptor_queue} {}
343 466
344QuadArrayPass::~QuadArrayPass() = default; 467QuadArrayPass::~QuadArrayPass() = default;
345 468
346std::pair<VkBuffer, VkDeviceSize> QuadArrayPass::Assemble(u32 num_vertices, u32 first) { 469std::pair<VkBuffer, VkDeviceSize> QuadArrayPass::Assemble(u32 num_vertices, u32 first) {
347 const u32 num_triangle_vertices = num_vertices * 6 / 4; 470 const u32 num_triangle_vertices = (num_vertices / 4) * 6;
348 const std::size_t staging_size = num_triangle_vertices * sizeof(u32); 471 const std::size_t staging_size = num_triangle_vertices * sizeof(u32);
349 auto& buffer = staging_buffer_pool.GetUnusedBuffer(staging_size, false); 472 auto& buffer = staging_buffer_pool.GetUnusedBuffer(staging_size, false);
350 473
@@ -383,8 +506,8 @@ std::pair<VkBuffer, VkDeviceSize> QuadArrayPass::Assemble(u32 num_vertices, u32
383Uint8Pass::Uint8Pass(const VKDevice& device, VKScheduler& scheduler, 506Uint8Pass::Uint8Pass(const VKDevice& device, VKScheduler& scheduler,
384 VKDescriptorPool& descriptor_pool, VKStagingBufferPool& staging_buffer_pool, 507 VKDescriptorPool& descriptor_pool, VKStagingBufferPool& staging_buffer_pool,
385 VKUpdateDescriptorQueue& update_descriptor_queue) 508 VKUpdateDescriptorQueue& update_descriptor_queue)
386 : VKComputePass(device, descriptor_pool, BuildUint8PassDescriptorSetBindings(), 509 : VKComputePass(device, descriptor_pool, BuildInputOutputDescriptorSetBindings(),
387 BuildUint8PassDescriptorUpdateTemplateEntry(), {}, std::size(uint8_pass), 510 BuildInputOutputDescriptorUpdateTemplate(), {}, std::size(uint8_pass),
388 uint8_pass), 511 uint8_pass),
389 scheduler{scheduler}, staging_buffer_pool{staging_buffer_pool}, 512 scheduler{scheduler}, staging_buffer_pool{staging_buffer_pool},
390 update_descriptor_queue{update_descriptor_queue} {} 513 update_descriptor_queue{update_descriptor_queue} {}
@@ -425,4 +548,70 @@ std::pair<VkBuffer, u64> Uint8Pass::Assemble(u32 num_vertices, VkBuffer src_buff
425 return {*buffer.handle, 0}; 548 return {*buffer.handle, 0};
426} 549}
427 550
551QuadIndexedPass::QuadIndexedPass(const VKDevice& device, VKScheduler& scheduler,
552 VKDescriptorPool& descriptor_pool,
553 VKStagingBufferPool& staging_buffer_pool,
554 VKUpdateDescriptorQueue& update_descriptor_queue)
555 : VKComputePass(device, descriptor_pool, BuildInputOutputDescriptorSetBindings(),
556 BuildInputOutputDescriptorUpdateTemplate(),
557 BuildComputePushConstantRange(sizeof(u32) * 2), std::size(QUAD_INDEXED_SPV),
558 QUAD_INDEXED_SPV),
559 scheduler{scheduler}, staging_buffer_pool{staging_buffer_pool},
560 update_descriptor_queue{update_descriptor_queue} {}
561
562QuadIndexedPass::~QuadIndexedPass() = default;
563
564std::pair<VkBuffer, u64> QuadIndexedPass::Assemble(
565 Tegra::Engines::Maxwell3D::Regs::IndexFormat index_format, u32 num_vertices, u32 base_vertex,
566 VkBuffer src_buffer, u64 src_offset) {
567 const u32 index_shift = [index_format] {
568 switch (index_format) {
569 case Tegra::Engines::Maxwell3D::Regs::IndexFormat::UnsignedByte:
570 return 0;
571 case Tegra::Engines::Maxwell3D::Regs::IndexFormat::UnsignedShort:
572 return 1;
573 case Tegra::Engines::Maxwell3D::Regs::IndexFormat::UnsignedInt:
574 return 2;
575 }
576 UNREACHABLE();
577 return 2;
578 }();
579 const u32 input_size = num_vertices << index_shift;
580 const u32 num_tri_vertices = (num_vertices / 4) * 6;
581
582 const std::size_t staging_size = num_tri_vertices * sizeof(u32);
583 auto& buffer = staging_buffer_pool.GetUnusedBuffer(staging_size, false);
584
585 update_descriptor_queue.Acquire();
586 update_descriptor_queue.AddBuffer(src_buffer, src_offset, input_size);
587 update_descriptor_queue.AddBuffer(*buffer.handle, 0, staging_size);
588 const auto set = CommitDescriptorSet(update_descriptor_queue, scheduler.GetFence());
589
590 scheduler.RequestOutsideRenderPassOperationContext();
591 scheduler.Record([layout = *layout, pipeline = *pipeline, buffer = *buffer.handle, set,
592 num_tri_vertices, base_vertex, index_shift](vk::CommandBuffer cmdbuf) {
593 static constexpr u32 dispatch_size = 1024;
594 const std::array push_constants = {base_vertex, index_shift};
595 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
596 cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, layout, 0, set, {});
597 cmdbuf.PushConstants(layout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(push_constants),
598 &push_constants);
599 cmdbuf.Dispatch(Common::AlignUp(num_tri_vertices, dispatch_size) / dispatch_size, 1, 1);
600
601 VkBufferMemoryBarrier barrier;
602 barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
603 barrier.pNext = nullptr;
604 barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
605 barrier.dstAccessMask = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
606 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
607 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
608 barrier.buffer = buffer;
609 barrier.offset = 0;
610 barrier.size = static_cast<VkDeviceSize>(num_tri_vertices * sizeof(u32));
611 cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
612 VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0, {}, barrier, {});
613 });
614 return {*buffer.handle, 0};
615}
616
428} // namespace Vulkan 617} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.h b/src/video_core/renderer_vulkan/vk_compute_pass.h
index ec80c8683..26bf834de 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pass.h
+++ b/src/video_core/renderer_vulkan/vk_compute_pass.h
@@ -8,6 +8,7 @@
8#include <utility> 8#include <utility>
9#include <vector> 9#include <vector>
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "video_core/engines/maxwell_3d.h"
11#include "video_core/renderer_vulkan/vk_descriptor_pool.h" 12#include "video_core/renderer_vulkan/vk_descriptor_pool.h"
12#include "video_core/renderer_vulkan/wrapper.h" 13#include "video_core/renderer_vulkan/wrapper.h"
13 14
@@ -73,4 +74,22 @@ private:
73 VKUpdateDescriptorQueue& update_descriptor_queue; 74 VKUpdateDescriptorQueue& update_descriptor_queue;
74}; 75};
75 76
77class QuadIndexedPass final : public VKComputePass {
78public:
79 explicit QuadIndexedPass(const VKDevice& device, VKScheduler& scheduler,
80 VKDescriptorPool& descriptor_pool,
81 VKStagingBufferPool& staging_buffer_pool,
82 VKUpdateDescriptorQueue& update_descriptor_queue);
83 ~QuadIndexedPass();
84
85 std::pair<VkBuffer, u64> Assemble(Tegra::Engines::Maxwell3D::Regs::IndexFormat index_format,
86 u32 num_vertices, u32 base_vertex, VkBuffer src_buffer,
87 u64 src_offset);
88
89private:
90 VKScheduler& scheduler;
91 VKStagingBufferPool& staging_buffer_pool;
92 VKUpdateDescriptorQueue& update_descriptor_queue;
93};
94
76} // namespace Vulkan 95} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 4ca0febb8..857bea19f 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -293,6 +293,7 @@ RasterizerVulkan::RasterizerVulkan(Core::System& system, Core::Frontend::EmuWind
293 update_descriptor_queue(device, scheduler), renderpass_cache(device), 293 update_descriptor_queue(device, scheduler), renderpass_cache(device),
294 quad_array_pass(device, scheduler, descriptor_pool, staging_pool, update_descriptor_queue), 294 quad_array_pass(device, scheduler, descriptor_pool, staging_pool, update_descriptor_queue),
295 uint8_pass(device, scheduler, descriptor_pool, staging_pool, update_descriptor_queue), 295 uint8_pass(device, scheduler, descriptor_pool, staging_pool, update_descriptor_queue),
296 quad_indexed_pass(device, scheduler, descriptor_pool, staging_pool, update_descriptor_queue),
296 texture_cache(system, *this, device, resource_manager, memory_manager, scheduler, 297 texture_cache(system, *this, device, resource_manager, memory_manager, scheduler,
297 staging_pool), 298 staging_pool),
298 pipeline_cache(system, *this, device, scheduler, descriptor_pool, update_descriptor_queue, 299 pipeline_cache(system, *this, device, scheduler, descriptor_pool, update_descriptor_queue,
@@ -844,18 +845,26 @@ void RasterizerVulkan::SetupIndexBuffer(BufferBindings& buffer_bindings, DrawPar
844 bool is_indexed) { 845 bool is_indexed) {
845 const auto& regs = system.GPU().Maxwell3D().regs; 846 const auto& regs = system.GPU().Maxwell3D().regs;
846 switch (regs.draw.topology) { 847 switch (regs.draw.topology) {
847 case Maxwell::PrimitiveTopology::Quads: 848 case Maxwell::PrimitiveTopology::Quads: {
848 if (params.is_indexed) { 849 if (!params.is_indexed) {
849 UNIMPLEMENTED();
850 } else {
851 const auto [buffer, offset] = 850 const auto [buffer, offset] =
852 quad_array_pass.Assemble(params.num_vertices, params.base_vertex); 851 quad_array_pass.Assemble(params.num_vertices, params.base_vertex);
853 buffer_bindings.SetIndexBinding(buffer, offset, VK_INDEX_TYPE_UINT32); 852 buffer_bindings.SetIndexBinding(buffer, offset, VK_INDEX_TYPE_UINT32);
854 params.base_vertex = 0; 853 params.base_vertex = 0;
855 params.num_vertices = params.num_vertices * 6 / 4; 854 params.num_vertices = params.num_vertices * 6 / 4;
856 params.is_indexed = true; 855 params.is_indexed = true;
856 break;
857 } 857 }
858 const GPUVAddr gpu_addr = regs.index_array.IndexStart();
859 auto [buffer, offset] = buffer_cache.UploadMemory(gpu_addr, CalculateIndexBufferSize());
860 std::tie(buffer, offset) = quad_indexed_pass.Assemble(
861 regs.index_array.format, params.num_vertices, params.base_vertex, buffer, offset);
862
863 buffer_bindings.SetIndexBinding(buffer, offset, VK_INDEX_TYPE_UINT32);
864 params.num_vertices = (params.num_vertices / 4) * 6;
865 params.base_vertex = 0;
858 break; 866 break;
867 }
859 default: { 868 default: {
860 if (!is_indexed) { 869 if (!is_indexed) {
861 break; 870 break;
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h
index 46037860a..d9108f862 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.h
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.h
@@ -254,6 +254,7 @@ private:
254 VKUpdateDescriptorQueue update_descriptor_queue; 254 VKUpdateDescriptorQueue update_descriptor_queue;
255 VKRenderPassCache renderpass_cache; 255 VKRenderPassCache renderpass_cache;
256 QuadArrayPass quad_array_pass; 256 QuadArrayPass quad_array_pass;
257 QuadIndexedPass quad_indexed_pass;
257 Uint8Pass uint8_pass; 258 Uint8Pass uint8_pass;
258 259
259 VKTextureCache texture_cache; 260 VKTextureCache texture_cache;
diff --git a/src/video_core/shader/track.cpp b/src/video_core/shader/track.cpp
index 224943ad9..513e9bf49 100644
--- a/src/video_core/shader/track.cpp
+++ b/src/video_core/shader/track.cpp
@@ -76,12 +76,13 @@ std::tuple<Node, TrackSampler> ShaderIR::TrackBindlessSampler(Node tracked, cons
76 s64 cursor) { 76 s64 cursor) {
77 if (const auto cbuf = std::get_if<CbufNode>(&*tracked)) { 77 if (const auto cbuf = std::get_if<CbufNode>(&*tracked)) {
78 // Constant buffer found, test if it's an immediate 78 // Constant buffer found, test if it's an immediate
79 const auto offset = cbuf->GetOffset(); 79 const auto& offset = cbuf->GetOffset();
80 if (const auto immediate = std::get_if<ImmediateNode>(&*offset)) { 80 if (const auto immediate = std::get_if<ImmediateNode>(&*offset)) {
81 auto track = 81 auto track =
82 MakeTrackSampler<BindlessSamplerNode>(cbuf->GetIndex(), immediate->GetValue()); 82 MakeTrackSampler<BindlessSamplerNode>(cbuf->GetIndex(), immediate->GetValue());
83 return {tracked, track}; 83 return {tracked, track};
84 } else if (const auto operation = std::get_if<OperationNode>(&*offset)) { 84 }
85 if (const auto operation = std::get_if<OperationNode>(&*offset)) {
85 const u32 bound_buffer = registry.GetBoundBuffer(); 86 const u32 bound_buffer = registry.GetBoundBuffer();
86 if (bound_buffer != cbuf->GetIndex()) { 87 if (bound_buffer != cbuf->GetIndex()) {
87 return {}; 88 return {};
@@ -94,12 +95,12 @@ std::tuple<Node, TrackSampler> ShaderIR::TrackBindlessSampler(Node tracked, cons
94 const auto offset_inm = std::get_if<ImmediateNode>(&*base_offset); 95 const auto offset_inm = std::get_if<ImmediateNode>(&*base_offset);
95 const auto& gpu_driver = registry.AccessGuestDriverProfile(); 96 const auto& gpu_driver = registry.AccessGuestDriverProfile();
96 const u32 bindless_cv = NewCustomVariable(); 97 const u32 bindless_cv = NewCustomVariable();
97 const Node op = 98 Node op =
98 Operation(OperationCode::UDiv, gpr, Immediate(gpu_driver.GetTextureHandlerSize())); 99 Operation(OperationCode::UDiv, gpr, Immediate(gpu_driver.GetTextureHandlerSize()));
99 100
100 const Node cv_node = GetCustomVariable(bindless_cv); 101 const Node cv_node = GetCustomVariable(bindless_cv);
101 Node amend_op = Operation(OperationCode::Assign, cv_node, std::move(op)); 102 Node amend_op = Operation(OperationCode::Assign, cv_node, std::move(op));
102 const std::size_t amend_index = DeclareAmend(amend_op); 103 const std::size_t amend_index = DeclareAmend(std::move(amend_op));
103 AmendNodeCv(amend_index, code[cursor]); 104 AmendNodeCv(amend_index, code[cursor]);
104 // TODO Implement Bindless Index custom variable 105 // TODO Implement Bindless Index custom variable
105 auto track = MakeTrackSampler<ArraySamplerNode>(cbuf->GetIndex(), 106 auto track = MakeTrackSampler<ArraySamplerNode>(cbuf->GetIndex(),
@@ -142,7 +143,7 @@ std::tuple<Node, u32, u32> ShaderIR::TrackCbuf(Node tracked, const NodeBlock& co
142 s64 cursor) const { 143 s64 cursor) const {
143 if (const auto cbuf = std::get_if<CbufNode>(&*tracked)) { 144 if (const auto cbuf = std::get_if<CbufNode>(&*tracked)) {
144 // Constant buffer found, test if it's an immediate 145 // Constant buffer found, test if it's an immediate
145 const auto offset = cbuf->GetOffset(); 146 const auto& offset = cbuf->GetOffset();
146 if (const auto immediate = std::get_if<ImmediateNode>(&*offset)) { 147 if (const auto immediate = std::get_if<ImmediateNode>(&*offset)) {
147 return {tracked, cbuf->GetIndex(), immediate->GetValue()}; 148 return {tracked, cbuf->GetIndex(), immediate->GetValue()};
148 } 149 }
diff --git a/src/video_core/texture_cache/format_lookup_table.cpp b/src/video_core/texture_cache/format_lookup_table.cpp
index e151c26c4..25d2ee2e8 100644
--- a/src/video_core/texture_cache/format_lookup_table.cpp
+++ b/src/video_core/texture_cache/format_lookup_table.cpp
@@ -196,9 +196,9 @@ std::size_t FormatLookupTable::CalculateIndex(TextureFormat format, bool is_srgb
196 ComponentType alpha_component) noexcept { 196 ComponentType alpha_component) noexcept {
197 const auto format_index = static_cast<std::size_t>(format); 197 const auto format_index = static_cast<std::size_t>(format);
198 const auto red_index = static_cast<std::size_t>(red_component); 198 const auto red_index = static_cast<std::size_t>(red_component);
199 const auto green_index = static_cast<std::size_t>(red_component); 199 const auto green_index = static_cast<std::size_t>(green_component);
200 const auto blue_index = static_cast<std::size_t>(red_component); 200 const auto blue_index = static_cast<std::size_t>(blue_component);
201 const auto alpha_index = static_cast<std::size_t>(red_component); 201 const auto alpha_index = static_cast<std::size_t>(alpha_component);
202 const std::size_t srgb_index = is_srgb ? 1 : 0; 202 const std::size_t srgb_index = is_srgb ? 1 : 0;
203 203
204 return format_index * PerFormat + 204 return format_index * PerFormat +
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 2c8eb481d..05baec7e1 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -802,10 +802,6 @@ void GMainWindow::ConnectMenuEvents() {
802 connect(ui.action_Load_Folder, &QAction::triggered, this, &GMainWindow::OnMenuLoadFolder); 802 connect(ui.action_Load_Folder, &QAction::triggered, this, &GMainWindow::OnMenuLoadFolder);
803 connect(ui.action_Install_File_NAND, &QAction::triggered, this, 803 connect(ui.action_Install_File_NAND, &QAction::triggered, this,
804 &GMainWindow::OnMenuInstallToNAND); 804 &GMainWindow::OnMenuInstallToNAND);
805 connect(ui.action_Select_NAND_Directory, &QAction::triggered, this,
806 [this] { OnMenuSelectEmulatedDirectory(EmulatedDirectoryTarget::NAND); });
807 connect(ui.action_Select_SDMC_Directory, &QAction::triggered, this,
808 [this] { OnMenuSelectEmulatedDirectory(EmulatedDirectoryTarget::SDMC); });
809 connect(ui.action_Exit, &QAction::triggered, this, &QMainWindow::close); 805 connect(ui.action_Exit, &QAction::triggered, this, &QMainWindow::close);
810 connect(ui.action_Load_Amiibo, &QAction::triggered, this, &GMainWindow::OnLoadAmiibo); 806 connect(ui.action_Load_Amiibo, &QAction::triggered, this, &GMainWindow::OnLoadAmiibo);
811 807
@@ -940,16 +936,18 @@ bool GMainWindow::LoadROM(const QString& filename) {
940 default: 936 default:
941 if (static_cast<u32>(result) > 937 if (static_cast<u32>(result) >
942 static_cast<u32>(Core::System::ResultStatus::ErrorLoader)) { 938 static_cast<u32>(Core::System::ResultStatus::ErrorLoader)) {
943 LOG_CRITICAL(Frontend, "Failed to load ROM!");
944 const u16 loader_id = static_cast<u16>(Core::System::ResultStatus::ErrorLoader); 939 const u16 loader_id = static_cast<u16>(Core::System::ResultStatus::ErrorLoader);
945 const u16 error_id = static_cast<u16>(result) - loader_id; 940 const u16 error_id = static_cast<u16>(result) - loader_id;
941 const std::string error_code = fmt::format("({:04X}-{:04X})", loader_id, error_id);
942 LOG_CRITICAL(Frontend, "Failed to load ROM! {}", error_code);
946 QMessageBox::critical( 943 QMessageBox::critical(
947 this, tr("Error while loading ROM!"), 944 this,
945 tr("Error while loading ROM! ").append(QString::fromStdString(error_code)),
948 QString::fromStdString(fmt::format( 946 QString::fromStdString(fmt::format(
949 "While attempting to load the ROM requested, an error occured. Please " 947 "{}<br>Please follow <a href='https://yuzu-emu.org/help/quickstart/'>the "
950 "refer to the yuzu wiki for more information or the yuzu discord for " 948 "yuzu quickstart guide</a> to redump your files.<br>You can refer "
951 "additional help.\n\nError Code: {:04X}-{:04X}\nError Description: {}", 949 "to the yuzu wiki</a> or the yuzu Discord</a> for help.",
952 loader_id, error_id, static_cast<Loader::ResultStatus>(error_id)))); 950 static_cast<Loader::ResultStatus>(error_id))));
953 } else { 951 } else {
954 QMessageBox::critical( 952 QMessageBox::critical(
955 this, tr("Error while loading ROM!"), 953 this, tr("Error while loading ROM!"),
@@ -1663,28 +1661,6 @@ void GMainWindow::OnMenuInstallToNAND() {
1663 } 1661 }
1664} 1662}
1665 1663
1666void GMainWindow::OnMenuSelectEmulatedDirectory(EmulatedDirectoryTarget target) {
1667 const auto res = QMessageBox::information(
1668 this, tr("Changing Emulated Directory"),
1669 tr("You are about to change the emulated %1 directory of the system. Please note "
1670 "that this does not also move the contents of the previous directory to the "
1671 "new one and you will have to do that yourself.")
1672 .arg(target == EmulatedDirectoryTarget::SDMC ? tr("SD card") : tr("NAND")),
1673 QMessageBox::StandardButtons{QMessageBox::Ok, QMessageBox::Cancel});
1674
1675 if (res == QMessageBox::Cancel)
1676 return;
1677
1678 QString dir_path = QFileDialog::getExistingDirectory(this, tr("Select Directory"));
1679 if (!dir_path.isEmpty()) {
1680 FileUtil::GetUserPath(target == EmulatedDirectoryTarget::SDMC ? FileUtil::UserPath::SDMCDir
1681 : FileUtil::UserPath::NANDDir,
1682 dir_path.toStdString());
1683 Core::System::GetInstance().GetFileSystemController().CreateFactories(*vfs);
1684 game_list->PopulateAsync(UISettings::values.game_dirs);
1685 }
1686}
1687
1688void GMainWindow::OnMenuRecentFile() { 1664void GMainWindow::OnMenuRecentFile() {
1689 QAction* action = qobject_cast<QAction*>(sender()); 1665 QAction* action = qobject_cast<QAction*>(sender());
1690 assert(action); 1666 assert(action);
@@ -2095,27 +2071,25 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) {
2095 2071
2096 QString errors; 2072 QString errors;
2097 if (!pdm.HasFuses()) { 2073 if (!pdm.HasFuses()) {
2098 errors += tr("- Missing fuses - Cannot derive SBK\n"); 2074 errors += tr("Missing fuses");
2099 } 2075 }
2100 if (!pdm.HasBoot0()) { 2076 if (!pdm.HasBoot0()) {
2101 errors += tr("- Missing BOOT0 - Cannot derive master keys\n"); 2077 errors += tr(" - Missing BOOT0");
2102 } 2078 }
2103 if (!pdm.HasPackage2()) { 2079 if (!pdm.HasPackage2()) {
2104 errors += tr("- Missing BCPKG2-1-Normal-Main - Cannot derive general keys\n"); 2080 errors += tr(" - Missing BCPKG2-1-Normal-Main");
2105 } 2081 }
2106 if (!pdm.HasProdInfo()) { 2082 if (!pdm.HasProdInfo()) {
2107 errors += tr("- Missing PRODINFO - Cannot derive title keys\n"); 2083 errors += tr(" - Missing PRODINFO");
2108 } 2084 }
2109 if (!errors.isEmpty()) { 2085 if (!errors.isEmpty()) {
2110 QMessageBox::warning( 2086 QMessageBox::warning(
2111 this, tr("Warning Missing Derivation Components"), 2087 this, tr("Derivation Components Missing"),
2112 tr("The following are missing from your configuration that may hinder key " 2088 tr("Components are missing that may hinder key derivation from completing. "
2113 "derivation. It will be attempted but may not complete.<br><br>") + 2089 "<br>Please follow <a href='https://yuzu-emu.org/help/quickstart/'>the yuzu "
2114 errors + 2090 "quickstart guide</a> to get all your keys and "
2115 tr("<br><br>You can get all of these and dump all of your games easily by " 2091 "games.<br><br><small>(%1)</small>")
2116 "following <a href='https://yuzu-emu.org/help/quickstart/'>the " 2092 .arg(errors));
2117 "quickstart guide</a>. Alternatively, you can use another method of dumping "
2118 "to obtain all of your keys."));
2119 } 2093 }
2120 2094
2121 QProgressDialog prog; 2095 QProgressDialog prog;
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index a67125567..0b750689d 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -196,8 +196,6 @@ private slots:
196 void OnMenuLoadFile(); 196 void OnMenuLoadFile();
197 void OnMenuLoadFolder(); 197 void OnMenuLoadFolder();
198 void OnMenuInstallToNAND(); 198 void OnMenuInstallToNAND();
199 /// Called whenever a user select the "File->Select -- Directory" where -- is NAND or SD Card
200 void OnMenuSelectEmulatedDirectory(EmulatedDirectoryTarget target);
201 void OnMenuRecentFile(); 199 void OnMenuRecentFile();
202 void OnConfigure(); 200 void OnConfigure();
203 void OnLoadAmiibo(); 201 void OnLoadAmiibo();
diff --git a/src/yuzu/main.ui b/src/yuzu/main.ui
index a2c9e4547..ae414241e 100644
--- a/src/yuzu/main.ui
+++ b/src/yuzu/main.ui
@@ -64,8 +64,6 @@
64 <addaction name="separator"/> 64 <addaction name="separator"/>
65 <addaction name="menu_recent_files"/> 65 <addaction name="menu_recent_files"/>
66 <addaction name="separator"/> 66 <addaction name="separator"/>
67 <addaction name="action_Select_NAND_Directory"/>
68 <addaction name="action_Select_SDMC_Directory"/>
69 <addaction name="separator"/> 67 <addaction name="separator"/>
70 <addaction name="action_Load_Amiibo"/> 68 <addaction name="action_Load_Amiibo"/>
71 <addaction name="separator"/> 69 <addaction name="separator"/>
@@ -217,22 +215,6 @@
217 <string>Show Status Bar</string> 215 <string>Show Status Bar</string>
218 </property> 216 </property>
219 </action> 217 </action>
220 <action name="action_Select_NAND_Directory">
221 <property name="text">
222 <string>Select NAND Directory...</string>
223 </property>
224 <property name="toolTip">
225 <string>Selects a folder to use as the root of the emulated NAND</string>
226 </property>
227 </action>
228 <action name="action_Select_SDMC_Directory">
229 <property name="text">
230 <string>Select SD Card Directory...</string>
231 </property>
232 <property name="toolTip">
233 <string>Selects a folder to use as the root of the emulated SD card</string>
234 </property>
235 </action>
236 <action name="action_Fullscreen"> 218 <action name="action_Fullscreen">
237 <property name="checkable"> 219 <property name="checkable">
238 <bool>true</bool> 220 <bool>true</bool>