summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/core/CMakeLists.txt7
-rw-r--r--src/core/file_sys/patch_manager.cpp6
-rw-r--r--src/core/hle/kernel/kernel.cpp2
-rw-r--r--src/core/hle/service/friend/friend.cpp11
-rw-r--r--src/core/hle/service/time/interface.cpp2
-rw-r--r--src/core/hle/service/time/time.cpp23
-rw-r--r--src/core/hle/service/time/time.h1
-rw-r--r--src/input_common/CMakeLists.txt2
-rw-r--r--src/video_core/engines/maxwell_3d.h4
-rw-r--r--src/video_core/engines/shader_bytecode.h14
-rw-r--r--src/video_core/gpu_asynch.cpp5
-rw-r--r--src/video_core/renderer_opengl/gl_device.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp4
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp4
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp30
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.cpp2
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp4
-rw-r--r--src/video_core/renderer_vulkan/maxwell_to_vk.cpp10
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.cpp2
-rw-r--r--src/video_core/renderer_vulkan/vk_memory_manager.h2
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp9
-rw-r--r--src/video_core/renderer_vulkan/vk_shader_decompiler.cpp65
-rw-r--r--src/video_core/shader/control_flow.cpp6
-rw-r--r--src/video_core/shader/decode/arithmetic.cpp3
-rw-r--r--src/video_core/shader/decode/memory.cpp100
-rw-r--r--src/video_core/shader/decode/shift.cpp1
-rw-r--r--src/video_core/shader/node.h14
-rw-r--r--src/video_core/texture_cache/surface_base.cpp6
-rw-r--r--src/video_core/texture_cache/surface_base.h4
-rw-r--r--src/video_core/texture_cache/surface_view.cpp4
-rw-r--r--src/video_core/texture_cache/surface_view.h1
-rw-r--r--src/video_core/texture_cache/texture_cache.h12
-rw-r--r--src/web_service/CMakeLists.txt7
34 files changed, 256 insertions, 114 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 9d0af02fd..e40e9b0a5 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -53,6 +53,7 @@ if (MSVC)
53else() 53else()
54 add_compile_options( 54 add_compile_options(
55 -Wall 55 -Wall
56 -Werror=reorder
56 -Wno-attributes 57 -Wno-attributes
57 ) 58 )
58 59
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 66497a386..c15d9f52f 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -591,11 +591,8 @@ target_link_libraries(core PUBLIC common PRIVATE audio_core video_core)
591target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt json-headers mbedtls opus unicorn) 591target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt json-headers mbedtls opus unicorn)
592 592
593if (YUZU_ENABLE_BOXCAT) 593if (YUZU_ENABLE_BOXCAT)
594 get_directory_property(OPENSSL_LIBS 594 target_compile_definitions(core PRIVATE -DYUZU_ENABLE_BOXCAT)
595 DIRECTORY ${PROJECT_SOURCE_DIR}/externals/libressl 595 target_link_libraries(core PRIVATE httplib json-headers zip)
596 DEFINITION OPENSSL_LIBS)
597 target_compile_definitions(core PRIVATE -DCPPHTTPLIB_OPENSSL_SUPPORT -DYUZU_ENABLE_BOXCAT)
598 target_link_libraries(core PRIVATE httplib json-headers ${OPENSSL_LIBS} zip)
599endif() 596endif()
600 597
601if (ENABLE_WEB_SERVICE) 598if (ENABLE_WEB_SERVICE)
diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp
index e226e9711..e77e82b8d 100644
--- a/src/core/file_sys/patch_manager.cpp
+++ b/src/core/file_sys/patch_manager.cpp
@@ -348,6 +348,12 @@ static void ApplyLayeredFS(VirtualFile& romfs, u64 title_id, ContentRecordType t
348 if (ext_dir != nullptr) 348 if (ext_dir != nullptr)
349 layers_ext.push_back(std::move(ext_dir)); 349 layers_ext.push_back(std::move(ext_dir));
350 } 350 }
351
352 // When there are no layers to apply, return early as there is no need to rebuild the RomFS
353 if (layers.empty() && layers_ext.empty()) {
354 return;
355 }
356
351 layers.push_back(std::move(extracted)); 357 layers.push_back(std::move(extracted));
352 358
353 auto layered = LayeredVfsDirectory::MakeLayeredDirectory(std::move(layers)); 359 auto layered = LayeredVfsDirectory::MakeLayeredDirectory(std::move(layers));
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index e47f1deed..014d647cf 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -103,7 +103,7 @@ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_
103 103
104struct KernelCore::Impl { 104struct KernelCore::Impl {
105 explicit Impl(Core::System& system, KernelCore& kernel) 105 explicit Impl(Core::System& system, KernelCore& kernel)
106 : system{system}, global_scheduler{kernel}, synchronization{system}, time_manager{system} {} 106 : global_scheduler{kernel}, synchronization{system}, time_manager{system}, system{system} {}
107 107
108 void Initialize(KernelCore& kernel) { 108 void Initialize(KernelCore& kernel) {
109 Shutdown(); 109 Shutdown();
diff --git a/src/core/hle/service/friend/friend.cpp b/src/core/hle/service/friend/friend.cpp
index 6aadb3ea8..7938b4b80 100644
--- a/src/core/hle/service/friend/friend.cpp
+++ b/src/core/hle/service/friend/friend.cpp
@@ -27,7 +27,7 @@ public:
27 {10110, nullptr, "GetFriendProfileImage"}, 27 {10110, nullptr, "GetFriendProfileImage"},
28 {10200, nullptr, "SendFriendRequestForApplication"}, 28 {10200, nullptr, "SendFriendRequestForApplication"},
29 {10211, nullptr, "AddFacedFriendRequestForApplication"}, 29 {10211, nullptr, "AddFacedFriendRequestForApplication"},
30 {10400, nullptr, "GetBlockedUserListIds"}, 30 {10400, &IFriendService::GetBlockedUserListIds, "GetBlockedUserListIds"},
31 {10500, nullptr, "GetProfileList"}, 31 {10500, nullptr, "GetProfileList"},
32 {10600, nullptr, "DeclareOpenOnlinePlaySession"}, 32 {10600, nullptr, "DeclareOpenOnlinePlaySession"},
33 {10601, &IFriendService::DeclareCloseOnlinePlaySession, "DeclareCloseOnlinePlaySession"}, 33 {10601, &IFriendService::DeclareCloseOnlinePlaySession, "DeclareCloseOnlinePlaySession"},
@@ -121,6 +121,15 @@ private:
121 }; 121 };
122 static_assert(sizeof(SizedFriendFilter) == 0x10, "SizedFriendFilter is an invalid size"); 122 static_assert(sizeof(SizedFriendFilter) == 0x10, "SizedFriendFilter is an invalid size");
123 123
124 void GetBlockedUserListIds(Kernel::HLERequestContext& ctx) {
125 // This is safe to stub, as there should be no adverse consequences from reporting no
126 // blocked users.
127 LOG_WARNING(Service_ACC, "(STUBBED) called");
128 IPC::ResponseBuilder rb{ctx, 3};
129 rb.Push(RESULT_SUCCESS);
130 rb.Push<u32>(0); // Indicates there are no blocked users
131 }
132
124 void DeclareCloseOnlinePlaySession(Kernel::HLERequestContext& ctx) { 133 void DeclareCloseOnlinePlaySession(Kernel::HLERequestContext& ctx) {
125 // Stub used by Splatoon 2 134 // Stub used by Splatoon 2
126 LOG_WARNING(Service_ACC, "(STUBBED) called"); 135 LOG_WARNING(Service_ACC, "(STUBBED) called");
diff --git a/src/core/hle/service/time/interface.cpp b/src/core/hle/service/time/interface.cpp
index f509653a3..ba8fd6152 100644
--- a/src/core/hle/service/time/interface.cpp
+++ b/src/core/hle/service/time/interface.cpp
@@ -29,7 +29,7 @@ Time::Time(std::shared_ptr<Module> module, Core::System& system, const char* nam
29 {300, &Time::CalculateMonotonicSystemClockBaseTimePoint, "CalculateMonotonicSystemClockBaseTimePoint"}, 29 {300, &Time::CalculateMonotonicSystemClockBaseTimePoint, "CalculateMonotonicSystemClockBaseTimePoint"},
30 {400, &Time::GetClockSnapshot, "GetClockSnapshot"}, 30 {400, &Time::GetClockSnapshot, "GetClockSnapshot"},
31 {401, &Time::GetClockSnapshotFromSystemClockContext, "GetClockSnapshotFromSystemClockContext"}, 31 {401, &Time::GetClockSnapshotFromSystemClockContext, "GetClockSnapshotFromSystemClockContext"},
32 {500, nullptr, "CalculateStandardUserSystemClockDifferenceByUser"}, 32 {500, &Time::CalculateStandardUserSystemClockDifferenceByUser, "CalculateStandardUserSystemClockDifferenceByUser"},
33 {501, &Time::CalculateSpanBetween, "CalculateSpanBetween"}, 33 {501, &Time::CalculateSpanBetween, "CalculateSpanBetween"},
34 }; 34 };
35 // clang-format on 35 // clang-format on
diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp
index ce859f18d..e722886de 100644
--- a/src/core/hle/service/time/time.cpp
+++ b/src/core/hle/service/time/time.cpp
@@ -308,6 +308,29 @@ void Module::Interface::GetClockSnapshotFromSystemClockContext(Kernel::HLEReques
308 ctx.WriteBuffer(&clock_snapshot, sizeof(Clock::ClockSnapshot)); 308 ctx.WriteBuffer(&clock_snapshot, sizeof(Clock::ClockSnapshot));
309} 309}
310 310
311void Module::Interface::CalculateStandardUserSystemClockDifferenceByUser(
312 Kernel::HLERequestContext& ctx) {
313 LOG_DEBUG(Service_Time, "called");
314
315 IPC::RequestParser rp{ctx};
316 const auto snapshot_a = rp.PopRaw<Clock::ClockSnapshot>();
317 const auto snapshot_b = rp.PopRaw<Clock::ClockSnapshot>();
318
319 auto time_span_type{Clock::TimeSpanType::FromSeconds(snapshot_b.user_context.offset -
320 snapshot_a.user_context.offset)};
321
322 if ((snapshot_b.user_context.steady_time_point.clock_source_id !=
323 snapshot_a.user_context.steady_time_point.clock_source_id) ||
324 (snapshot_b.is_automatic_correction_enabled &&
325 snapshot_a.is_automatic_correction_enabled)) {
326 time_span_type.nanoseconds = 0;
327 }
328
329 IPC::ResponseBuilder rb{ctx, (sizeof(s64) / 4) + 2};
330 rb.Push(RESULT_SUCCESS);
331 rb.PushRaw(time_span_type.nanoseconds);
332}
333
311void Module::Interface::CalculateSpanBetween(Kernel::HLERequestContext& ctx) { 334void Module::Interface::CalculateSpanBetween(Kernel::HLERequestContext& ctx) {
312 LOG_DEBUG(Service_Time, "called"); 335 LOG_DEBUG(Service_Time, "called");
313 336
diff --git a/src/core/hle/service/time/time.h b/src/core/hle/service/time/time.h
index 351988468..41f3002e9 100644
--- a/src/core/hle/service/time/time.h
+++ b/src/core/hle/service/time/time.h
@@ -32,6 +32,7 @@ public:
32 void CalculateMonotonicSystemClockBaseTimePoint(Kernel::HLERequestContext& ctx); 32 void CalculateMonotonicSystemClockBaseTimePoint(Kernel::HLERequestContext& ctx);
33 void GetClockSnapshot(Kernel::HLERequestContext& ctx); 33 void GetClockSnapshot(Kernel::HLERequestContext& ctx);
34 void GetClockSnapshotFromSystemClockContext(Kernel::HLERequestContext& ctx); 34 void GetClockSnapshotFromSystemClockContext(Kernel::HLERequestContext& ctx);
35 void CalculateStandardUserSystemClockDifferenceByUser(Kernel::HLERequestContext& ctx);
35 void CalculateSpanBetween(Kernel::HLERequestContext& ctx); 36 void CalculateSpanBetween(Kernel::HLERequestContext& ctx);
36 void GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx); 37 void GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx);
37 38
diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt
index 2520ba321..a9c2392b1 100644
--- a/src/input_common/CMakeLists.txt
+++ b/src/input_common/CMakeLists.txt
@@ -27,4 +27,4 @@ if(SDL2_FOUND)
27endif() 27endif()
28 28
29create_target_directory_groups(input_common) 29create_target_directory_groups(input_common)
30target_link_libraries(input_common PUBLIC core PRIVATE common ${Boost_LIBRARIES}) 30target_link_libraries(input_common PUBLIC core PRIVATE common Boost::boost)
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index 2977a7d81..5cf6a4cc3 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -303,6 +303,10 @@ public:
303 return (type == Type::SignedNorm) || (type == Type::UnsignedNorm); 303 return (type == Type::SignedNorm) || (type == Type::UnsignedNorm);
304 } 304 }
305 305
306 bool IsConstant() const {
307 return constant;
308 }
309
306 bool IsValid() const { 310 bool IsValid() const {
307 return size != Size::Invalid; 311 return size != Size::Invalid;
308 } 312 }
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index c66c66f6c..5e9cfba22 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -1006,6 +1006,12 @@ union Instruction {
1006 } stg; 1006 } stg;
1007 1007
1008 union { 1008 union {
1009 BitField<23, 3, AtomicOp> operation;
1010 BitField<48, 1, u64> extended;
1011 BitField<20, 3, GlobalAtomicType> type;
1012 } red;
1013
1014 union {
1009 BitField<52, 4, AtomicOp> operation; 1015 BitField<52, 4, AtomicOp> operation;
1010 BitField<49, 3, GlobalAtomicType> type; 1016 BitField<49, 3, GlobalAtomicType> type;
1011 BitField<28, 20, s64> offset; 1017 BitField<28, 20, s64> offset;
@@ -1787,6 +1793,7 @@ public:
1787 ST_S, 1793 ST_S,
1788 ST, // Store in generic memory 1794 ST, // Store in generic memory
1789 STG, // Store in global memory 1795 STG, // Store in global memory
1796 RED, // Reduction operation
1790 ATOM, // Atomic operation on global memory 1797 ATOM, // Atomic operation on global memory
1791 ATOMS, // Atomic operation on shared memory 1798 ATOMS, // Atomic operation on shared memory
1792 AL2P, // Transforms attribute memory into physical memory 1799 AL2P, // Transforms attribute memory into physical memory
@@ -1871,7 +1878,8 @@ public:
1871 ICMP_R, 1878 ICMP_R,
1872 ICMP_CR, 1879 ICMP_CR,
1873 ICMP_IMM, 1880 ICMP_IMM,
1874 FCMP_R, 1881 FCMP_RR,
1882 FCMP_RC,
1875 MUFU, // Multi-Function Operator 1883 MUFU, // Multi-Function Operator
1876 RRO_C, // Range Reduction Operator 1884 RRO_C, // Range Reduction Operator
1877 RRO_R, 1885 RRO_R,
@@ -2096,6 +2104,7 @@ private:
2096 INST("1110111101010---", Id::ST_L, Type::Memory, "ST_L"), 2104 INST("1110111101010---", Id::ST_L, Type::Memory, "ST_L"),
2097 INST("101-------------", Id::ST, Type::Memory, "ST"), 2105 INST("101-------------", Id::ST, Type::Memory, "ST"),
2098 INST("1110111011011---", Id::STG, Type::Memory, "STG"), 2106 INST("1110111011011---", Id::STG, Type::Memory, "STG"),
2107 INST("1110101111111---", Id::RED, Type::Memory, "RED"),
2099 INST("11101101--------", Id::ATOM, Type::Memory, "ATOM"), 2108 INST("11101101--------", Id::ATOM, Type::Memory, "ATOM"),
2100 INST("11101100--------", Id::ATOMS, Type::Memory, "ATOMS"), 2109 INST("11101100--------", Id::ATOMS, Type::Memory, "ATOMS"),
2101 INST("1110111110100---", Id::AL2P, Type::Memory, "AL2P"), 2110 INST("1110111110100---", Id::AL2P, Type::Memory, "AL2P"),
@@ -2179,7 +2188,8 @@ private:
2179 INST("0101110100100---", Id::HSETP2_R, Type::HalfSetPredicate, "HSETP2_R"), 2188 INST("0101110100100---", Id::HSETP2_R, Type::HalfSetPredicate, "HSETP2_R"),
2180 INST("0111111-0-------", Id::HSETP2_IMM, Type::HalfSetPredicate, "HSETP2_IMM"), 2189 INST("0111111-0-------", Id::HSETP2_IMM, Type::HalfSetPredicate, "HSETP2_IMM"),
2181 INST("0101110100011---", Id::HSET2_R, Type::HalfSet, "HSET2_R"), 2190 INST("0101110100011---", Id::HSET2_R, Type::HalfSet, "HSET2_R"),
2182 INST("010110111010----", Id::FCMP_R, Type::Arithmetic, "FCMP_R"), 2191 INST("010110111010----", Id::FCMP_RR, Type::Arithmetic, "FCMP_RR"),
2192 INST("010010111010----", Id::FCMP_RC, Type::Arithmetic, "FCMP_RC"),
2183 INST("0101000010000---", Id::MUFU, Type::Arithmetic, "MUFU"), 2193 INST("0101000010000---", Id::MUFU, Type::Arithmetic, "MUFU"),
2184 INST("0100110010010---", Id::RRO_C, Type::Arithmetic, "RRO_C"), 2194 INST("0100110010010---", Id::RRO_C, Type::Arithmetic, "RRO_C"),
2185 INST("0101110010010---", Id::RRO_R, Type::Arithmetic, "RRO_R"), 2195 INST("0101110010010---", Id::RRO_R, Type::Arithmetic, "RRO_R"),
diff --git a/src/video_core/gpu_asynch.cpp b/src/video_core/gpu_asynch.cpp
index cc434faf7..20e73a37e 100644
--- a/src/video_core/gpu_asynch.cpp
+++ b/src/video_core/gpu_asynch.cpp
@@ -12,8 +12,9 @@ namespace VideoCommon {
12 12
13GPUAsynch::GPUAsynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer_, 13GPUAsynch::GPUAsynch(Core::System& system, std::unique_ptr<VideoCore::RendererBase>&& renderer_,
14 std::unique_ptr<Core::Frontend::GraphicsContext>&& context) 14 std::unique_ptr<Core::Frontend::GraphicsContext>&& context)
15 : GPU(system, std::move(renderer_), true), gpu_thread{system}, gpu_context(std::move(context)), 15 : GPU(system, std::move(renderer_), true), gpu_thread{system},
16 cpu_context(renderer->GetRenderWindow().CreateSharedContext()) {} 16 cpu_context(renderer->GetRenderWindow().CreateSharedContext()),
17 gpu_context(std::move(context)) {}
17 18
18GPUAsynch::~GPUAsynch() = default; 19GPUAsynch::~GPUAsynch() = default;
19 20
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp
index c286502ba..d83dca25a 100644
--- a/src/video_core/renderer_opengl/gl_device.cpp
+++ b/src/video_core/renderer_opengl/gl_device.cpp
@@ -87,7 +87,7 @@ u32 Extract(u32& base, u32& num, u32 amount, std::optional<GLenum> limit = {}) {
87std::array<Device::BaseBindings, Tegra::Engines::MaxShaderTypes> BuildBaseBindings() noexcept { 87std::array<Device::BaseBindings, Tegra::Engines::MaxShaderTypes> BuildBaseBindings() noexcept {
88 std::array<Device::BaseBindings, Tegra::Engines::MaxShaderTypes> bindings; 88 std::array<Device::BaseBindings, Tegra::Engines::MaxShaderTypes> bindings;
89 89
90 static std::array<std::size_t, 5> stage_swizzle = {0, 1, 2, 3, 4}; 90 static constexpr std::array<std::size_t, 5> stage_swizzle{0, 1, 2, 3, 4};
91 const u32 total_ubos = GetInteger<u32>(GL_MAX_UNIFORM_BUFFER_BINDINGS); 91 const u32 total_ubos = GetInteger<u32>(GL_MAX_UNIFORM_BUFFER_BINDINGS);
92 const u32 total_ssbos = GetInteger<u32>(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS); 92 const u32 total_ssbos = GetInteger<u32>(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS);
93 const u32 total_samplers = GetInteger<u32>(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS); 93 const u32 total_samplers = GetInteger<u32>(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS);
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 91abeb9d7..175374f0d 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -140,8 +140,8 @@ void RasterizerOpenGL::SetupVertexFormat() {
140 const auto attrib = gpu.regs.vertex_attrib_format[index]; 140 const auto attrib = gpu.regs.vertex_attrib_format[index];
141 const auto gl_index = static_cast<GLuint>(index); 141 const auto gl_index = static_cast<GLuint>(index);
142 142
143 // Ignore invalid attributes. 143 // Disable constant attributes.
144 if (!attrib.IsValid()) { 144 if (attrib.IsConstant()) {
145 glDisableVertexAttribArray(gl_index); 145 glDisableVertexAttribArray(gl_index);
146 continue; 146 continue;
147 } 147 }
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index 6d2ff20f9..12c6dcfde 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -34,6 +34,8 @@
34namespace OpenGL { 34namespace OpenGL {
35 35
36using Tegra::Engines::ShaderType; 36using Tegra::Engines::ShaderType;
37using VideoCommon::Shader::CompileDepth;
38using VideoCommon::Shader::CompilerSettings;
37using VideoCommon::Shader::ProgramCode; 39using VideoCommon::Shader::ProgramCode;
38using VideoCommon::Shader::Registry; 40using VideoCommon::Shader::Registry;
39using VideoCommon::Shader::ShaderIR; 41using VideoCommon::Shader::ShaderIR;
@@ -43,7 +45,7 @@ namespace {
43constexpr u32 STAGE_MAIN_OFFSET = 10; 45constexpr u32 STAGE_MAIN_OFFSET = 10;
44constexpr u32 KERNEL_MAIN_OFFSET = 0; 46constexpr u32 KERNEL_MAIN_OFFSET = 0;
45 47
46constexpr VideoCommon::Shader::CompilerSettings COMPILER_SETTINGS{}; 48constexpr CompilerSettings COMPILER_SETTINGS{CompileDepth::FullDecompile};
47 49
48/// Gets the address for the specified shader stage program 50/// Gets the address for the specified shader stage program
49GPUVAddr GetShaderAddress(Core::System& system, Maxwell::ShaderProgram program) { 51GPUVAddr GetShaderAddress(Core::System& system, Maxwell::ShaderProgram program) {
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 1f1f01313..b1804e9ea 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -1821,13 +1821,15 @@ private:
1821 Expression HMergeH0(Operation operation) { 1821 Expression HMergeH0(Operation operation) {
1822 const std::string dest = VisitOperand(operation, 0).AsUint(); 1822 const std::string dest = VisitOperand(operation, 0).AsUint();
1823 const std::string src = VisitOperand(operation, 1).AsUint(); 1823 const std::string src = VisitOperand(operation, 1).AsUint();
1824 return {fmt::format("bitfieldInsert({}, {}, 0, 16)", dest, src), Type::Uint}; 1824 return {fmt::format("vec2(unpackHalf2x16({}).x, unpackHalf2x16({}).y)", src, dest),
1825 Type::HalfFloat};
1825 } 1826 }
1826 1827
1827 Expression HMergeH1(Operation operation) { 1828 Expression HMergeH1(Operation operation) {
1828 const std::string dest = VisitOperand(operation, 0).AsUint(); 1829 const std::string dest = VisitOperand(operation, 0).AsUint();
1829 const std::string src = VisitOperand(operation, 1).AsUint(); 1830 const std::string src = VisitOperand(operation, 1).AsUint();
1830 return {fmt::format("bitfieldInsert({}, {}, 16, 16)", dest, src), Type::Uint}; 1831 return {fmt::format("vec2(unpackHalf2x16({}).x, unpackHalf2x16({}).y)", dest, src),
1832 Type::HalfFloat};
1831 } 1833 }
1832 1834
1833 Expression HPack2(Operation operation) { 1835 Expression HPack2(Operation operation) {
@@ -2117,8 +2119,14 @@ private:
2117 return {}; 2119 return {};
2118 } 2120 }
2119 return {fmt::format("atomic{}({}, {})", opname, Visit(operation[0]).GetCode(), 2121 return {fmt::format("atomic{}({}, {})", opname, Visit(operation[0]).GetCode(),
2120 Visit(operation[1]).As(type)), 2122 Visit(operation[1]).AsUint()),
2121 type}; 2123 Type::Uint};
2124 }
2125
2126 template <const std::string_view& opname, Type type>
2127 Expression Reduce(Operation operation) {
2128 code.AddLine("{};", Atomic<opname, type>(operation).GetCode());
2129 return {};
2122 } 2130 }
2123 2131
2124 Expression Branch(Operation operation) { 2132 Expression Branch(Operation operation) {
@@ -2477,6 +2485,20 @@ private:
2477 &GLSLDecompiler::Atomic<Func::Or, Type::Int>, 2485 &GLSLDecompiler::Atomic<Func::Or, Type::Int>,
2478 &GLSLDecompiler::Atomic<Func::Xor, Type::Int>, 2486 &GLSLDecompiler::Atomic<Func::Xor, Type::Int>,
2479 2487
2488 &GLSLDecompiler::Reduce<Func::Add, Type::Uint>,
2489 &GLSLDecompiler::Reduce<Func::Min, Type::Uint>,
2490 &GLSLDecompiler::Reduce<Func::Max, Type::Uint>,
2491 &GLSLDecompiler::Reduce<Func::And, Type::Uint>,
2492 &GLSLDecompiler::Reduce<Func::Or, Type::Uint>,
2493 &GLSLDecompiler::Reduce<Func::Xor, Type::Uint>,
2494
2495 &GLSLDecompiler::Reduce<Func::Add, Type::Int>,
2496 &GLSLDecompiler::Reduce<Func::Min, Type::Int>,
2497 &GLSLDecompiler::Reduce<Func::Max, Type::Int>,
2498 &GLSLDecompiler::Reduce<Func::And, Type::Int>,
2499 &GLSLDecompiler::Reduce<Func::Or, Type::Int>,
2500 &GLSLDecompiler::Reduce<Func::Xor, Type::Int>,
2501
2480 &GLSLDecompiler::Branch, 2502 &GLSLDecompiler::Branch,
2481 &GLSLDecompiler::BranchIndirect, 2503 &GLSLDecompiler::BranchIndirect,
2482 &GLSLDecompiler::PushFlowStack, 2504 &GLSLDecompiler::PushFlowStack,
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp
index 0b4d999d7..2729d1265 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp
@@ -417,7 +417,7 @@ void CachedSurfaceView::Attach(GLenum attachment, GLenum target) const {
417 417
418 switch (params.target) { 418 switch (params.target) {
419 case SurfaceTarget::Texture2DArray: 419 case SurfaceTarget::Texture2DArray:
420 glFramebufferTexture(target, attachment, GetTexture(), params.base_level); 420 glFramebufferTexture(target, attachment, GetTexture(), 0);
421 break; 421 break;
422 default: 422 default:
423 UNIMPLEMENTED(); 423 UNIMPLEMENTED();
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index f1a28cc21..b2a179746 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -315,8 +315,8 @@ public:
315 315
316RendererOpenGL::RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system, 316RendererOpenGL::RendererOpenGL(Core::Frontend::EmuWindow& emu_window, Core::System& system,
317 Core::Frontend::GraphicsContext& context) 317 Core::Frontend::GraphicsContext& context)
318 : VideoCore::RendererBase{emu_window}, emu_window{emu_window}, system{system}, 318 : RendererBase{emu_window}, emu_window{emu_window}, system{system}, context{context},
319 frame_mailbox{}, context{context}, has_debug_tool{HasDebugTool()} {} 319 has_debug_tool{HasDebugTool()} {}
320 320
321RendererOpenGL::~RendererOpenGL() = default; 321RendererOpenGL::~RendererOpenGL() = default;
322 322
diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
index 143478863..8681b821f 100644
--- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
+++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
@@ -360,6 +360,7 @@ VkFormat VertexFormat(Maxwell::VertexAttribute::Type type, Maxwell::VertexAttrib
360 default: 360 default:
361 break; 361 break;
362 } 362 }
363 break;
363 case Maxwell::VertexAttribute::Type::UnsignedInt: 364 case Maxwell::VertexAttribute::Type::UnsignedInt:
364 switch (size) { 365 switch (size) {
365 case Maxwell::VertexAttribute::Size::Size_8: 366 case Maxwell::VertexAttribute::Size::Size_8:
@@ -370,6 +371,14 @@ VkFormat VertexFormat(Maxwell::VertexAttribute::Type type, Maxwell::VertexAttrib
370 return VK_FORMAT_R8G8B8_UINT; 371 return VK_FORMAT_R8G8B8_UINT;
371 case Maxwell::VertexAttribute::Size::Size_8_8_8_8: 372 case Maxwell::VertexAttribute::Size::Size_8_8_8_8:
372 return VK_FORMAT_R8G8B8A8_UINT; 373 return VK_FORMAT_R8G8B8A8_UINT;
374 case Maxwell::VertexAttribute::Size::Size_16:
375 return VK_FORMAT_R16_UINT;
376 case Maxwell::VertexAttribute::Size::Size_16_16:
377 return VK_FORMAT_R16G16_UINT;
378 case Maxwell::VertexAttribute::Size::Size_16_16_16:
379 return VK_FORMAT_R16G16B16_UINT;
380 case Maxwell::VertexAttribute::Size::Size_16_16_16_16:
381 return VK_FORMAT_R16G16B16A16_UINT;
373 case Maxwell::VertexAttribute::Size::Size_32: 382 case Maxwell::VertexAttribute::Size::Size_32:
374 return VK_FORMAT_R32_UINT; 383 return VK_FORMAT_R32_UINT;
375 case Maxwell::VertexAttribute::Size::Size_32_32: 384 case Maxwell::VertexAttribute::Size::Size_32_32:
@@ -381,6 +390,7 @@ VkFormat VertexFormat(Maxwell::VertexAttribute::Type type, Maxwell::VertexAttrib
381 default: 390 default:
382 break; 391 break;
383 } 392 }
393 break;
384 case Maxwell::VertexAttribute::Type::UnsignedScaled: 394 case Maxwell::VertexAttribute::Type::UnsignedScaled:
385 switch (size) { 395 switch (size) {
386 case Maxwell::VertexAttribute::Size::Size_8: 396 case Maxwell::VertexAttribute::Size::Size_8:
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
index 21644a7e7..fbd406f2b 100644
--- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp
+++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
@@ -535,7 +535,9 @@ void VKBlitScreen::CreateGraphicsPipeline() {
535 viewport_state_ci.pNext = nullptr; 535 viewport_state_ci.pNext = nullptr;
536 viewport_state_ci.flags = 0; 536 viewport_state_ci.flags = 0;
537 viewport_state_ci.viewportCount = 1; 537 viewport_state_ci.viewportCount = 1;
538 viewport_state_ci.pViewports = nullptr;
538 viewport_state_ci.scissorCount = 1; 539 viewport_state_ci.scissorCount = 1;
540 viewport_state_ci.pScissors = nullptr;
539 541
540 VkPipelineRasterizationStateCreateInfo rasterization_ci; 542 VkPipelineRasterizationStateCreateInfo rasterization_ci;
541 rasterization_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; 543 rasterization_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
diff --git a/src/video_core/renderer_vulkan/vk_memory_manager.h b/src/video_core/renderer_vulkan/vk_memory_manager.h
index 35ee54d30..5b6858e9b 100644
--- a/src/video_core/renderer_vulkan/vk_memory_manager.h
+++ b/src/video_core/renderer_vulkan/vk_memory_manager.h
@@ -32,7 +32,7 @@ public:
32 * memory. When passing false, it will try to allocate device local memory. 32 * memory. When passing false, it will try to allocate device local memory.
33 * @returns A memory commit. 33 * @returns A memory commit.
34 */ 34 */
35 VKMemoryCommit Commit(const VkMemoryRequirements& reqs, bool host_visible); 35 VKMemoryCommit Commit(const VkMemoryRequirements& requirements, bool host_visible);
36 36
37 /// Commits memory required by the buffer and binds it. 37 /// Commits memory required by the buffer and binds it.
38 VKMemoryCommit Commit(const vk::Buffer& buffer, bool host_visible); 38 VKMemoryCommit Commit(const vk::Buffer& buffer, bool host_visible);
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index ab281c9e2..4ca0febb8 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -62,13 +62,16 @@ constexpr auto ComputeShaderIndex = static_cast<std::size_t>(Tegra::Engines::Sha
62 62
63VkViewport GetViewportState(const VKDevice& device, const Maxwell& regs, std::size_t index) { 63VkViewport GetViewportState(const VKDevice& device, const Maxwell& regs, std::size_t index) {
64 const auto& src = regs.viewport_transform[index]; 64 const auto& src = regs.viewport_transform[index];
65 const float width = src.scale_x * 2.0f;
66 const float height = src.scale_y * 2.0f;
67
65 VkViewport viewport; 68 VkViewport viewport;
66 viewport.x = src.translate_x - src.scale_x; 69 viewport.x = src.translate_x - src.scale_x;
67 viewport.y = src.translate_y - src.scale_y; 70 viewport.y = src.translate_y - src.scale_y;
68 viewport.width = src.scale_x * 2.0f; 71 viewport.width = width != 0.0f ? width : 1.0f;
69 viewport.height = src.scale_y * 2.0f; 72 viewport.height = height != 0.0f ? height : 1.0f;
70 73
71 const float reduce_z = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne; 74 const float reduce_z = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne ? 1.0f : 0.0f;
72 viewport.minDepth = src.translate_z - src.scale_z * reduce_z; 75 viewport.minDepth = src.translate_z - src.scale_z * reduce_z;
73 viewport.maxDepth = src.translate_z + src.scale_z; 76 viewport.maxDepth = src.translate_z + src.scale_z;
74 if (!device.IsExtDepthRangeUnrestrictedSupported()) { 77 if (!device.IsExtDepthRangeUnrestrictedSupported()) {
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
index 62e4ca488..aaa138f52 100644
--- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
+++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
@@ -1938,11 +1938,8 @@ private:
1938 return {}; 1938 return {};
1939 } 1939 }
1940 1940
1941 template <Id (Module::*func)(Id, Id, Id, Id, Id), Type result_type, 1941 template <Id (Module::*func)(Id, Id, Id, Id, Id)>
1942 Type value_type = result_type>
1943 Expression Atomic(Operation operation) { 1942 Expression Atomic(Operation operation) {
1944 const Id type_def = GetTypeDefinition(result_type);
1945
1946 Id pointer; 1943 Id pointer;
1947 if (const auto smem = std::get_if<SmemNode>(&*operation[0])) { 1944 if (const auto smem = std::get_if<SmemNode>(&*operation[0])) {
1948 pointer = GetSharedMemoryPointer(*smem); 1945 pointer = GetSharedMemoryPointer(*smem);
@@ -1950,15 +1947,19 @@ private:
1950 pointer = GetGlobalMemoryPointer(*gmem); 1947 pointer = GetGlobalMemoryPointer(*gmem);
1951 } else { 1948 } else {
1952 UNREACHABLE(); 1949 UNREACHABLE();
1953 return {Constant(type_def, 0), result_type}; 1950 return {v_float_zero, Type::Float};
1954 } 1951 }
1955
1956 const Id value = As(Visit(operation[1]), value_type);
1957
1958 const Id scope = Constant(t_uint, static_cast<u32>(spv::Scope::Device)); 1952 const Id scope = Constant(t_uint, static_cast<u32>(spv::Scope::Device));
1959 const Id semantics = Constant(type_def, 0); 1953 const Id semantics = Constant(t_uint, 0);
1954 const Id value = AsUint(Visit(operation[1]));
1955
1956 return {(this->*func)(t_uint, pointer, scope, semantics, value), Type::Uint};
1957 }
1960 1958
1961 return {(this->*func)(type_def, pointer, scope, semantics, value), result_type}; 1959 template <Id (Module::*func)(Id, Id, Id, Id, Id)>
1960 Expression Reduce(Operation operation) {
1961 Atomic<func>(operation);
1962 return {};
1962 } 1963 }
1963 1964
1964 Expression Branch(Operation operation) { 1965 Expression Branch(Operation operation) {
@@ -2547,21 +2548,35 @@ private:
2547 &SPIRVDecompiler::AtomicImageXor, 2548 &SPIRVDecompiler::AtomicImageXor,
2548 &SPIRVDecompiler::AtomicImageExchange, 2549 &SPIRVDecompiler::AtomicImageExchange,
2549 2550
2550 &SPIRVDecompiler::Atomic<&Module::OpAtomicExchange, Type::Uint>, 2551 &SPIRVDecompiler::Atomic<&Module::OpAtomicExchange>,
2551 &SPIRVDecompiler::Atomic<&Module::OpAtomicIAdd, Type::Uint>, 2552 &SPIRVDecompiler::Atomic<&Module::OpAtomicIAdd>,
2552 &SPIRVDecompiler::Atomic<&Module::OpAtomicUMin, Type::Uint>, 2553 &SPIRVDecompiler::Atomic<&Module::OpAtomicUMin>,
2553 &SPIRVDecompiler::Atomic<&Module::OpAtomicUMax, Type::Uint>, 2554 &SPIRVDecompiler::Atomic<&Module::OpAtomicUMax>,
2554 &SPIRVDecompiler::Atomic<&Module::OpAtomicAnd, Type::Uint>, 2555 &SPIRVDecompiler::Atomic<&Module::OpAtomicAnd>,
2555 &SPIRVDecompiler::Atomic<&Module::OpAtomicOr, Type::Uint>, 2556 &SPIRVDecompiler::Atomic<&Module::OpAtomicOr>,
2556 &SPIRVDecompiler::Atomic<&Module::OpAtomicXor, Type::Uint>, 2557 &SPIRVDecompiler::Atomic<&Module::OpAtomicXor>,
2557 2558
2558 &SPIRVDecompiler::Atomic<&Module::OpAtomicExchange, Type::Int>, 2559 &SPIRVDecompiler::Atomic<&Module::OpAtomicExchange>,
2559 &SPIRVDecompiler::Atomic<&Module::OpAtomicIAdd, Type::Int>, 2560 &SPIRVDecompiler::Atomic<&Module::OpAtomicIAdd>,
2560 &SPIRVDecompiler::Atomic<&Module::OpAtomicSMin, Type::Int>, 2561 &SPIRVDecompiler::Atomic<&Module::OpAtomicSMin>,
2561 &SPIRVDecompiler::Atomic<&Module::OpAtomicSMax, Type::Int>, 2562 &SPIRVDecompiler::Atomic<&Module::OpAtomicSMax>,
2562 &SPIRVDecompiler::Atomic<&Module::OpAtomicAnd, Type::Int>, 2563 &SPIRVDecompiler::Atomic<&Module::OpAtomicAnd>,
2563 &SPIRVDecompiler::Atomic<&Module::OpAtomicOr, Type::Int>, 2564 &SPIRVDecompiler::Atomic<&Module::OpAtomicOr>,
2564 &SPIRVDecompiler::Atomic<&Module::OpAtomicXor, Type::Int>, 2565 &SPIRVDecompiler::Atomic<&Module::OpAtomicXor>,
2566
2567 &SPIRVDecompiler::Reduce<&Module::OpAtomicIAdd>,
2568 &SPIRVDecompiler::Reduce<&Module::OpAtomicUMin>,
2569 &SPIRVDecompiler::Reduce<&Module::OpAtomicUMax>,
2570 &SPIRVDecompiler::Reduce<&Module::OpAtomicAnd>,
2571 &SPIRVDecompiler::Reduce<&Module::OpAtomicOr>,
2572 &SPIRVDecompiler::Reduce<&Module::OpAtomicXor>,
2573
2574 &SPIRVDecompiler::Reduce<&Module::OpAtomicIAdd>,
2575 &SPIRVDecompiler::Reduce<&Module::OpAtomicSMin>,
2576 &SPIRVDecompiler::Reduce<&Module::OpAtomicSMax>,
2577 &SPIRVDecompiler::Reduce<&Module::OpAtomicAnd>,
2578 &SPIRVDecompiler::Reduce<&Module::OpAtomicOr>,
2579 &SPIRVDecompiler::Reduce<&Module::OpAtomicXor>,
2565 2580
2566 &SPIRVDecompiler::Branch, 2581 &SPIRVDecompiler::Branch,
2567 &SPIRVDecompiler::BranchIndirect, 2582 &SPIRVDecompiler::BranchIndirect,
diff --git a/src/video_core/shader/control_flow.cpp b/src/video_core/shader/control_flow.cpp
index 2e2711350..6d313963a 100644
--- a/src/video_core/shader/control_flow.cpp
+++ b/src/video_core/shader/control_flow.cpp
@@ -484,17 +484,17 @@ bool TryInspectAddress(CFGRebuildState& state) {
484 } 484 }
485 case BlockCollision::Inside: { 485 case BlockCollision::Inside: {
486 // This case is the tricky one: 486 // This case is the tricky one:
487 // We need to Split the block in 2 sepparate blocks 487 // We need to split the block into 2 separate blocks
488 const u32 end = state.block_info[block_index].end; 488 const u32 end = state.block_info[block_index].end;
489 BlockInfo& new_block = CreateBlockInfo(state, address, end); 489 BlockInfo& new_block = CreateBlockInfo(state, address, end);
490 BlockInfo& current_block = state.block_info[block_index]; 490 BlockInfo& current_block = state.block_info[block_index];
491 current_block.end = address - 1; 491 current_block.end = address - 1;
492 new_block.branch = current_block.branch; 492 new_block.branch = std::move(current_block.branch);
493 BlockBranchInfo forward_branch = MakeBranchInfo<SingleBranch>(); 493 BlockBranchInfo forward_branch = MakeBranchInfo<SingleBranch>();
494 const auto branch = std::get_if<SingleBranch>(forward_branch.get()); 494 const auto branch = std::get_if<SingleBranch>(forward_branch.get());
495 branch->address = address; 495 branch->address = address;
496 branch->ignore = true; 496 branch->ignore = true;
497 current_block.branch = forward_branch; 497 current_block.branch = std::move(forward_branch);
498 return true; 498 return true;
499 } 499 }
500 default: 500 default:
diff --git a/src/video_core/shader/decode/arithmetic.cpp b/src/video_core/shader/decode/arithmetic.cpp
index 478394682..4db329fa5 100644
--- a/src/video_core/shader/decode/arithmetic.cpp
+++ b/src/video_core/shader/decode/arithmetic.cpp
@@ -136,7 +136,8 @@ u32 ShaderIR::DecodeArithmetic(NodeBlock& bb, u32 pc) {
136 SetRegister(bb, instr.gpr0, value); 136 SetRegister(bb, instr.gpr0, value);
137 break; 137 break;
138 } 138 }
139 case OpCode::Id::FCMP_R: { 139 case OpCode::Id::FCMP_RR:
140 case OpCode::Id::FCMP_RC: {
140 UNIMPLEMENTED_IF(instr.fcmp.ftz == 0); 141 UNIMPLEMENTED_IF(instr.fcmp.ftz == 0);
141 Node op_c = GetRegister(instr.gpr39); 142 Node op_c = GetRegister(instr.gpr39);
142 Node comp = GetPredicateComparisonFloat(instr.fcmp.cond, std::move(op_c), Immediate(0.0f)); 143 Node comp = GetPredicateComparisonFloat(instr.fcmp.cond, std::move(op_c), Immediate(0.0f));
diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp
index b8f63922f..8112ead3e 100644
--- a/src/video_core/shader/decode/memory.cpp
+++ b/src/video_core/shader/decode/memory.cpp
@@ -3,7 +3,9 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm> 5#include <algorithm>
6#include <utility>
6#include <vector> 7#include <vector>
8
7#include <fmt/format.h> 9#include <fmt/format.h>
8 10
9#include "common/alignment.h" 11#include "common/alignment.h"
@@ -16,6 +18,7 @@
16 18
17namespace VideoCommon::Shader { 19namespace VideoCommon::Shader {
18 20
21using std::move;
19using Tegra::Shader::AtomicOp; 22using Tegra::Shader::AtomicOp;
20using Tegra::Shader::AtomicType; 23using Tegra::Shader::AtomicType;
21using Tegra::Shader::Attribute; 24using Tegra::Shader::Attribute;
@@ -27,29 +30,26 @@ using Tegra::Shader::StoreType;
27 30
28namespace { 31namespace {
29 32
30Node GetAtomOperation(AtomicOp op, bool is_signed, Node memory, Node data) { 33OperationCode GetAtomOperation(AtomicOp op) {
31 const OperationCode operation_code = [op] { 34 switch (op) {
32 switch (op) { 35 case AtomicOp::Add:
33 case AtomicOp::Add: 36 return OperationCode::AtomicIAdd;
34 return OperationCode::AtomicIAdd; 37 case AtomicOp::Min:
35 case AtomicOp::Min: 38 return OperationCode::AtomicIMin;
36 return OperationCode::AtomicIMin; 39 case AtomicOp::Max:
37 case AtomicOp::Max: 40 return OperationCode::AtomicIMax;
38 return OperationCode::AtomicIMax; 41 case AtomicOp::And:
39 case AtomicOp::And: 42 return OperationCode::AtomicIAnd;
40 return OperationCode::AtomicIAnd; 43 case AtomicOp::Or:
41 case AtomicOp::Or: 44 return OperationCode::AtomicIOr;
42 return OperationCode::AtomicIOr; 45 case AtomicOp::Xor:
43 case AtomicOp::Xor: 46 return OperationCode::AtomicIXor;
44 return OperationCode::AtomicIXor; 47 case AtomicOp::Exch:
45 case AtomicOp::Exch: 48 return OperationCode::AtomicIExchange;
46 return OperationCode::AtomicIExchange; 49 default:
47 default: 50 UNIMPLEMENTED_MSG("op={}", static_cast<int>(op));
48 UNIMPLEMENTED_MSG("op={}", static_cast<int>(op)); 51 return OperationCode::AtomicIAdd;
49 return OperationCode::AtomicIAdd; 52 }
50 }
51 }();
52 return SignedOperation(operation_code, is_signed, std::move(memory), std::move(data));
53} 53}
54 54
55bool IsUnaligned(Tegra::Shader::UniformType uniform_type) { 55bool IsUnaligned(Tegra::Shader::UniformType uniform_type) {
@@ -90,23 +90,22 @@ u32 GetMemorySize(Tegra::Shader::UniformType uniform_type) {
90 90
91Node ExtractUnaligned(Node value, Node address, u32 mask, u32 size) { 91Node ExtractUnaligned(Node value, Node address, u32 mask, u32 size) {
92 Node offset = Operation(OperationCode::UBitwiseAnd, address, Immediate(mask)); 92 Node offset = Operation(OperationCode::UBitwiseAnd, address, Immediate(mask));
93 offset = Operation(OperationCode::ULogicalShiftLeft, std::move(offset), Immediate(3)); 93 offset = Operation(OperationCode::ULogicalShiftLeft, move(offset), Immediate(3));
94 return Operation(OperationCode::UBitfieldExtract, std::move(value), std::move(offset), 94 return Operation(OperationCode::UBitfieldExtract, move(value), move(offset), Immediate(size));
95 Immediate(size));
96} 95}
97 96
98Node InsertUnaligned(Node dest, Node value, Node address, u32 mask, u32 size) { 97Node InsertUnaligned(Node dest, Node value, Node address, u32 mask, u32 size) {
99 Node offset = Operation(OperationCode::UBitwiseAnd, std::move(address), Immediate(mask)); 98 Node offset = Operation(OperationCode::UBitwiseAnd, move(address), Immediate(mask));
100 offset = Operation(OperationCode::ULogicalShiftLeft, std::move(offset), Immediate(3)); 99 offset = Operation(OperationCode::ULogicalShiftLeft, move(offset), Immediate(3));
101 return Operation(OperationCode::UBitfieldInsert, std::move(dest), std::move(value), 100 return Operation(OperationCode::UBitfieldInsert, move(dest), move(value), move(offset),
102 std::move(offset), Immediate(size)); 101 Immediate(size));
103} 102}
104 103
105Node Sign16Extend(Node value) { 104Node Sign16Extend(Node value) {
106 Node sign = Operation(OperationCode::UBitwiseAnd, value, Immediate(1U << 15)); 105 Node sign = Operation(OperationCode::UBitwiseAnd, value, Immediate(1U << 15));
107 Node is_sign = Operation(OperationCode::LogicalUEqual, std::move(sign), Immediate(1U << 15)); 106 Node is_sign = Operation(OperationCode::LogicalUEqual, move(sign), Immediate(1U << 15));
108 Node extend = Operation(OperationCode::Select, is_sign, Immediate(0xFFFF0000), Immediate(0)); 107 Node extend = Operation(OperationCode::Select, is_sign, Immediate(0xFFFF0000), Immediate(0));
109 return Operation(OperationCode::UBitwiseOr, std::move(value), std::move(extend)); 108 return Operation(OperationCode::UBitwiseOr, move(value), move(extend));
110} 109}
111 110
112} // Anonymous namespace 111} // Anonymous namespace
@@ -379,20 +378,36 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
379 378
380 if (IsUnaligned(type)) { 379 if (IsUnaligned(type)) {
381 const u32 mask = GetUnalignedMask(type); 380 const u32 mask = GetUnalignedMask(type);
382 value = InsertUnaligned(gmem, std::move(value), real_address, mask, size); 381 value = InsertUnaligned(gmem, move(value), real_address, mask, size);
383 } 382 }
384 383
385 bb.push_back(Operation(OperationCode::Assign, gmem, value)); 384 bb.push_back(Operation(OperationCode::Assign, gmem, value));
386 } 385 }
387 break; 386 break;
388 } 387 }
388 case OpCode::Id::RED: {
389 UNIMPLEMENTED_IF_MSG(instr.red.type != GlobalAtomicType::U32);
390 UNIMPLEMENTED_IF_MSG(instr.red.operation != AtomicOp::Add);
391 const auto [real_address, base_address, descriptor] =
392 TrackGlobalMemory(bb, instr, true, true);
393 if (!real_address || !base_address) {
394 // Tracking failed, skip atomic.
395 break;
396 }
397 Node gmem = MakeNode<GmemNode>(real_address, base_address, descriptor);
398 Node value = GetRegister(instr.gpr0);
399 bb.push_back(Operation(OperationCode::ReduceIAdd, move(gmem), move(value)));
400 break;
401 }
389 case OpCode::Id::ATOM: { 402 case OpCode::Id::ATOM: {
390 UNIMPLEMENTED_IF_MSG(instr.atom.operation == AtomicOp::Inc || 403 UNIMPLEMENTED_IF_MSG(instr.atom.operation == AtomicOp::Inc ||
391 instr.atom.operation == AtomicOp::Dec || 404 instr.atom.operation == AtomicOp::Dec ||
392 instr.atom.operation == AtomicOp::SafeAdd, 405 instr.atom.operation == AtomicOp::SafeAdd,
393 "operation={}", static_cast<int>(instr.atom.operation.Value())); 406 "operation={}", static_cast<int>(instr.atom.operation.Value()));
394 UNIMPLEMENTED_IF_MSG(instr.atom.type == GlobalAtomicType::S64 || 407 UNIMPLEMENTED_IF_MSG(instr.atom.type == GlobalAtomicType::S64 ||
395 instr.atom.type == GlobalAtomicType::U64, 408 instr.atom.type == GlobalAtomicType::U64 ||
409 instr.atom.type == GlobalAtomicType::F16x2_FTZ_RN ||
410 instr.atom.type == GlobalAtomicType::F32_FTZ_RN,
396 "type={}", static_cast<int>(instr.atom.type.Value())); 411 "type={}", static_cast<int>(instr.atom.type.Value()));
397 412
398 const auto [real_address, base_address, descriptor] = 413 const auto [real_address, base_address, descriptor] =
@@ -403,11 +418,11 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
403 } 418 }
404 419
405 const bool is_signed = 420 const bool is_signed =
406 instr.atoms.type == AtomicType::S32 || instr.atoms.type == AtomicType::S64; 421 instr.atom.type == GlobalAtomicType::S32 || instr.atom.type == GlobalAtomicType::S64;
407 Node gmem = MakeNode<GmemNode>(real_address, base_address, descriptor); 422 Node gmem = MakeNode<GmemNode>(real_address, base_address, descriptor);
408 Node value = GetAtomOperation(static_cast<AtomicOp>(instr.atom.operation), is_signed, gmem, 423 SetRegister(bb, instr.gpr0,
409 GetRegister(instr.gpr20)); 424 SignedOperation(GetAtomOperation(instr.atom.operation), is_signed, gmem,
410 SetRegister(bb, instr.gpr0, std::move(value)); 425 GetRegister(instr.gpr20)));
411 break; 426 break;
412 } 427 }
413 case OpCode::Id::ATOMS: { 428 case OpCode::Id::ATOMS: {
@@ -421,11 +436,10 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
421 instr.atoms.type == AtomicType::S32 || instr.atoms.type == AtomicType::S64; 436 instr.atoms.type == AtomicType::S32 || instr.atoms.type == AtomicType::S64;
422 const s32 offset = instr.atoms.GetImmediateOffset(); 437 const s32 offset = instr.atoms.GetImmediateOffset();
423 Node address = GetRegister(instr.gpr8); 438 Node address = GetRegister(instr.gpr8);
424 address = Operation(OperationCode::IAdd, std::move(address), Immediate(offset)); 439 address = Operation(OperationCode::IAdd, move(address), Immediate(offset));
425 Node value = 440 SetRegister(bb, instr.gpr0,
426 GetAtomOperation(static_cast<AtomicOp>(instr.atoms.operation), is_signed, 441 SignedOperation(GetAtomOperation(instr.atoms.operation), is_signed,
427 GetSharedMemory(std::move(address)), GetRegister(instr.gpr20)); 442 GetSharedMemory(move(address)), GetRegister(instr.gpr20)));
428 SetRegister(bb, instr.gpr0, std::move(value));
429 break; 443 break;
430 } 444 }
431 case OpCode::Id::AL2P: { 445 case OpCode::Id::AL2P: {
diff --git a/src/video_core/shader/decode/shift.cpp b/src/video_core/shader/decode/shift.cpp
index 3b391d3e6..d4ffa8014 100644
--- a/src/video_core/shader/decode/shift.cpp
+++ b/src/video_core/shader/decode/shift.cpp
@@ -23,7 +23,6 @@ Node IsFull(Node shift) {
23} 23}
24 24
25Node Shift(OperationCode opcode, Node value, Node shift) { 25Node Shift(OperationCode opcode, Node value, Node shift) {
26 Node is_full = Operation(OperationCode::LogicalIEqual, shift, Immediate(32));
27 Node shifted = Operation(opcode, move(value), shift); 26 Node shifted = Operation(opcode, move(value), shift);
28 return Operation(OperationCode::Select, IsFull(move(shift)), Immediate(0), move(shifted)); 27 return Operation(OperationCode::Select, IsFull(move(shift)), Immediate(0), move(shifted));
29} 28}
diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h
index 5fcc9da60..3eee961f5 100644
--- a/src/video_core/shader/node.h
+++ b/src/video_core/shader/node.h
@@ -178,6 +178,20 @@ enum class OperationCode {
178 AtomicIOr, /// (memory, int) -> int 178 AtomicIOr, /// (memory, int) -> int
179 AtomicIXor, /// (memory, int) -> int 179 AtomicIXor, /// (memory, int) -> int
180 180
181 ReduceUAdd, /// (memory, uint) -> void
182 ReduceUMin, /// (memory, uint) -> void
183 ReduceUMax, /// (memory, uint) -> void
184 ReduceUAnd, /// (memory, uint) -> void
185 ReduceUOr, /// (memory, uint) -> void
186 ReduceUXor, /// (memory, uint) -> void
187
188 ReduceIAdd, /// (memory, int) -> void
189 ReduceIMin, /// (memory, int) -> void
190 ReduceIMax, /// (memory, int) -> void
191 ReduceIAnd, /// (memory, int) -> void
192 ReduceIOr, /// (memory, int) -> void
193 ReduceIXor, /// (memory, int) -> void
194
181 Branch, /// (uint branch_target) -> void 195 Branch, /// (uint branch_target) -> void
182 BranchIndirect, /// (uint branch_target) -> void 196 BranchIndirect, /// (uint branch_target) -> void
183 PushFlowStack, /// (uint branch_target) -> void 197 PushFlowStack, /// (uint branch_target) -> void
diff --git a/src/video_core/texture_cache/surface_base.cpp b/src/video_core/texture_cache/surface_base.cpp
index 7af0e792c..715f39d0d 100644
--- a/src/video_core/texture_cache/surface_base.cpp
+++ b/src/video_core/texture_cache/surface_base.cpp
@@ -248,8 +248,14 @@ void SurfaceBaseImpl::FlushBuffer(Tegra::MemoryManager& memory_manager,
248 248
249 // Use an extra temporal buffer 249 // Use an extra temporal buffer
250 auto& tmp_buffer = staging_cache.GetBuffer(1); 250 auto& tmp_buffer = staging_cache.GetBuffer(1);
251 // Special case for 3D Texture Segments
252 const bool must_read_current_data =
253 params.block_depth > 0 && params.target == VideoCore::Surface::SurfaceTarget::Texture2D;
251 tmp_buffer.resize(guest_memory_size); 254 tmp_buffer.resize(guest_memory_size);
252 host_ptr = tmp_buffer.data(); 255 host_ptr = tmp_buffer.data();
256 if (must_read_current_data) {
257 memory_manager.ReadBlockUnsafe(gpu_addr, host_ptr, guest_memory_size);
258 }
253 259
254 if (params.is_tiled) { 260 if (params.is_tiled) {
255 ASSERT_MSG(params.block_width == 0, "Block width is defined as {}", params.block_width); 261 ASSERT_MSG(params.block_width == 0, "Block width is defined as {}", params.block_width);
diff --git a/src/video_core/texture_cache/surface_base.h b/src/video_core/texture_cache/surface_base.h
index a39a8661b..c5ab21f56 100644
--- a/src/video_core/texture_cache/surface_base.h
+++ b/src/video_core/texture_cache/surface_base.h
@@ -72,9 +72,9 @@ public:
72 return (cpu_addr < end) && (cpu_addr_end > start); 72 return (cpu_addr < end) && (cpu_addr_end > start);
73 } 73 }
74 74
75 bool IsInside(const GPUVAddr other_start, const GPUVAddr other_end) { 75 bool IsInside(const GPUVAddr other_start, const GPUVAddr other_end) const {
76 const GPUVAddr gpu_addr_end = gpu_addr + guest_memory_size; 76 const GPUVAddr gpu_addr_end = gpu_addr + guest_memory_size;
77 return (gpu_addr <= other_start && other_end <= gpu_addr_end); 77 return gpu_addr <= other_start && other_end <= gpu_addr_end;
78 } 78 }
79 79
80 // Use only when recycling a surface 80 // Use only when recycling a surface
diff --git a/src/video_core/texture_cache/surface_view.cpp b/src/video_core/texture_cache/surface_view.cpp
index 57a1f5803..6b5f5984b 100644
--- a/src/video_core/texture_cache/surface_view.cpp
+++ b/src/video_core/texture_cache/surface_view.cpp
@@ -20,4 +20,8 @@ bool ViewParams::operator==(const ViewParams& rhs) const {
20 std::tie(rhs.base_layer, rhs.num_layers, rhs.base_level, rhs.num_levels, rhs.target); 20 std::tie(rhs.base_layer, rhs.num_layers, rhs.base_level, rhs.num_levels, rhs.target);
21} 21}
22 22
23bool ViewParams::operator!=(const ViewParams& rhs) const {
24 return !operator==(rhs);
25}
26
23} // namespace VideoCommon 27} // namespace VideoCommon
diff --git a/src/video_core/texture_cache/surface_view.h b/src/video_core/texture_cache/surface_view.h
index b17fd11a9..90a8bb0ae 100644
--- a/src/video_core/texture_cache/surface_view.h
+++ b/src/video_core/texture_cache/surface_view.h
@@ -21,6 +21,7 @@ struct ViewParams {
21 std::size_t Hash() const; 21 std::size_t Hash() const;
22 22
23 bool operator==(const ViewParams& rhs) const; 23 bool operator==(const ViewParams& rhs) const;
24 bool operator!=(const ViewParams& rhs) const;
24 25
25 bool IsLayered() const { 26 bool IsLayered() const {
26 switch (target) { 27 switch (target) {
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index cfc7fe6e9..3e8663adf 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -509,7 +509,9 @@ private:
509 } 509 }
510 const auto& final_params = new_surface->GetSurfaceParams(); 510 const auto& final_params = new_surface->GetSurfaceParams();
511 if (cr_params.type != final_params.type) { 511 if (cr_params.type != final_params.type) {
512 BufferCopy(current_surface, new_surface); 512 if (Settings::values.use_accurate_gpu_emulation) {
513 BufferCopy(current_surface, new_surface);
514 }
513 } else { 515 } else {
514 std::vector<CopyParams> bricks = current_surface->BreakDown(final_params); 516 std::vector<CopyParams> bricks = current_surface->BreakDown(final_params);
515 for (auto& brick : bricks) { 517 for (auto& brick : bricks) {
@@ -612,10 +614,10 @@ private:
612 * textures within the GPU if possible. Falls back to LLE when it isn't possible to use any of 614 * textures within the GPU if possible. Falls back to LLE when it isn't possible to use any of
613 * the HLE methods. 615 * the HLE methods.
614 * 616 *
615 * @param overlaps The overlapping surfaces registered in the cache. 617 * @param overlaps The overlapping surfaces registered in the cache.
616 * @param params The parameters on the new surface. 618 * @param params The parameters on the new surface.
617 * @param gpu_addr The starting address of the new surface. 619 * @param gpu_addr The starting address of the new surface.
618 * @param cache_addr The starting address of the new surface on physical memory. 620 * @param cpu_addr The starting address of the new surface on physical memory.
619 */ 621 */
620 std::optional<std::pair<TSurface, TView>> Manage3DSurfaces(std::vector<TSurface>& overlaps, 622 std::optional<std::pair<TSurface, TView>> Manage3DSurfaces(std::vector<TSurface>& overlaps,
621 const SurfaceParams& params, 623 const SurfaceParams& params,
diff --git a/src/web_service/CMakeLists.txt b/src/web_service/CMakeLists.txt
index 01f2d129d..0c9bb0d55 100644
--- a/src/web_service/CMakeLists.txt
+++ b/src/web_service/CMakeLists.txt
@@ -8,9 +8,4 @@ add_library(web_service STATIC
8) 8)
9 9
10create_target_directory_groups(web_service) 10create_target_directory_groups(web_service)
11 11target_link_libraries(web_service PRIVATE common json-headers httplib lurlparser)
12get_directory_property(OPENSSL_LIBS
13 DIRECTORY ${PROJECT_SOURCE_DIR}/externals/libressl
14 DEFINITION OPENSSL_LIBS)
15target_compile_definitions(web_service PRIVATE -DCPPHTTPLIB_OPENSSL_SUPPORT)
16target_link_libraries(web_service PRIVATE common json-headers ${OPENSSL_LIBS} httplib lurlparser)