summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/common/settings.cpp1
-rw-r--r--src/common/settings.h1
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp4
-rw-r--r--src/core/hle/service/hid/controllers/npad.h4
-rw-r--r--src/core/hle/service/hid/hid.cpp20
-rw-r--r--src/input_common/helpers/joycon_protocol/joycon_types.h1
-rw-r--r--src/input_common/helpers/joycon_protocol/nfc.cpp10
-rw-r--r--src/input_common/helpers/joycon_protocol/nfc.h6
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp8
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate/impl/texture_mipmap_level.cpp7
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h29
-rw-r--r--src/video_core/buffer_cache/buffer_cache_base.h3
-rw-r--r--src/video_core/host1x/codecs/h264.cpp4
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.cpp3
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp25
-rw-r--r--src/video_core/vulkan_common/vulkan_device.cpp2
-rw-r--r--src/video_core/vulkan_common/vulkan_memory_allocator.cpp2
-rw-r--r--src/yuzu/configuration/config.cpp2
-rw-r--r--src/yuzu/configuration/configure_dialog.cpp3
-rw-r--r--src/yuzu/configuration/configure_dialog.h2
-rw-r--r--src/yuzu/configuration/configure_graphics.cpp23
-rw-r--r--src/yuzu/configuration/configure_graphics.h6
-rw-r--r--src/yuzu/configuration/configure_graphics_advanced.cpp17
-rw-r--r--src/yuzu/configuration/configure_graphics_advanced.h3
-rw-r--r--src/yuzu/configuration/configure_graphics_advanced.ui11
-rw-r--r--src/yuzu/configuration/configure_hotkeys.cpp65
-rw-r--r--src/yuzu/configuration/configure_hotkeys.h2
-rw-r--r--src/yuzu/configuration/configure_per_game.cpp3
-rw-r--r--src/yuzu/configuration/configure_per_game.h2
-rw-r--r--src/yuzu/main.cpp18
-rw-r--r--src/yuzu/main.h3
31 files changed, 168 insertions, 122 deletions
diff --git a/src/common/settings.cpp b/src/common/settings.cpp
index db1774c71..ba617aea1 100644
--- a/src/common/settings.cpp
+++ b/src/common/settings.cpp
@@ -232,6 +232,7 @@ void RestoreGlobalState(bool is_powered_on) {
232 values.bg_red.SetGlobal(true); 232 values.bg_red.SetGlobal(true);
233 values.bg_green.SetGlobal(true); 233 values.bg_green.SetGlobal(true);
234 values.bg_blue.SetGlobal(true); 234 values.bg_blue.SetGlobal(true);
235 values.enable_compute_pipelines.SetGlobal(true);
235 236
236 // System 237 // System
237 values.language_index.SetGlobal(true); 238 values.language_index.SetGlobal(true);
diff --git a/src/common/settings.h b/src/common/settings.h
index 5f4caaab9..36ffcd693 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -472,6 +472,7 @@ struct Values {
472 SwitchableSetting<bool> use_fast_gpu_time{true, "use_fast_gpu_time"}; 472 SwitchableSetting<bool> use_fast_gpu_time{true, "use_fast_gpu_time"};
473 SwitchableSetting<bool> use_vulkan_driver_pipeline_cache{true, 473 SwitchableSetting<bool> use_vulkan_driver_pipeline_cache{true,
474 "use_vulkan_driver_pipeline_cache"}; 474 "use_vulkan_driver_pipeline_cache"};
475 SwitchableSetting<bool> enable_compute_pipelines{false, "enable_compute_pipelines"};
475 476
476 SwitchableSetting<u8> bg_red{0, "bg_red"}; 477 SwitchableSetting<u8> bg_red{0, "bg_red"};
477 SwitchableSetting<u8> bg_green{0, "bg_green"}; 478 SwitchableSetting<u8> bg_green{0, "bg_green"};
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index ef4aec4ea..28818c813 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -979,8 +979,8 @@ void Controller_NPad::VibrateController(
979} 979}
980 980
981void Controller_NPad::VibrateControllers( 981void Controller_NPad::VibrateControllers(
982 const std::vector<Core::HID::VibrationDeviceHandle>& vibration_device_handles, 982 std::span<const Core::HID::VibrationDeviceHandle> vibration_device_handles,
983 const std::vector<Core::HID::VibrationValue>& vibration_values) { 983 std::span<const Core::HID::VibrationValue> vibration_values) {
984 if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { 984 if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) {
985 return; 985 return;
986 } 986 }
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 9cfe298f1..776411261 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -112,8 +112,8 @@ public:
112 const Core::HID::VibrationValue& vibration_value); 112 const Core::HID::VibrationValue& vibration_value);
113 113
114 void VibrateControllers( 114 void VibrateControllers(
115 const std::vector<Core::HID::VibrationDeviceHandle>& vibration_device_handles, 115 std::span<const Core::HID::VibrationDeviceHandle> vibration_device_handles,
116 const std::vector<Core::HID::VibrationValue>& vibration_values); 116 std::span<const Core::HID::VibrationValue> vibration_values);
117 117
118 Core::HID::VibrationValue GetLastVibration( 118 Core::HID::VibrationValue GetLastVibration(
119 const Core::HID::VibrationDeviceHandle& vibration_device_handle) const; 119 const Core::HID::VibrationDeviceHandle& vibration_device_handle) const;
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 87e7b864a..2bf1d8a27 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -1601,16 +1601,16 @@ void Hid::SendVibrationValues(HLERequestContext& ctx) {
1601 IPC::RequestParser rp{ctx}; 1601 IPC::RequestParser rp{ctx};
1602 const auto applet_resource_user_id{rp.Pop<u64>()}; 1602 const auto applet_resource_user_id{rp.Pop<u64>()};
1603 1603
1604 const auto handles = ctx.ReadBuffer(0); 1604 const auto handle_data = ctx.ReadBuffer(0);
1605 const auto vibrations = ctx.ReadBuffer(1); 1605 const auto handle_count = ctx.GetReadBufferNumElements<Core::HID::VibrationDeviceHandle>(0);
1606 1606 const auto vibration_data = ctx.ReadBuffer(1);
1607 std::vector<Core::HID::VibrationDeviceHandle> vibration_device_handles( 1607 const auto vibration_count = ctx.GetReadBufferNumElements<Core::HID::VibrationValue>(1);
1608 handles.size() / sizeof(Core::HID::VibrationDeviceHandle)); 1608
1609 std::vector<Core::HID::VibrationValue> vibration_values(vibrations.size() / 1609 auto vibration_device_handles =
1610 sizeof(Core::HID::VibrationValue)); 1610 std::span(reinterpret_cast<const Core::HID::VibrationDeviceHandle*>(handle_data.data()),
1611 1611 handle_count);
1612 std::memcpy(vibration_device_handles.data(), handles.data(), handles.size()); 1612 auto vibration_values = std::span(
1613 std::memcpy(vibration_values.data(), vibrations.data(), vibrations.size()); 1613 reinterpret_cast<const Core::HID::VibrationValue*>(vibration_data.data()), vibration_count);
1614 1614
1615 applet_resource->GetController<Controller_NPad>(HidController::NPad) 1615 applet_resource->GetController<Controller_NPad>(HidController::NPad)
1616 .VibrateControllers(vibration_device_handles, vibration_values); 1616 .VibrateControllers(vibration_device_handles, vibration_values);
diff --git a/src/input_common/helpers/joycon_protocol/joycon_types.h b/src/input_common/helpers/joycon_protocol/joycon_types.h
index b03143e04..1c8d294b0 100644
--- a/src/input_common/helpers/joycon_protocol/joycon_types.h
+++ b/src/input_common/helpers/joycon_protocol/joycon_types.h
@@ -394,6 +394,7 @@ enum class DriverResult {
394 InvalidHandle, 394 InvalidHandle,
395 NotSupported, 395 NotSupported,
396 Disabled, 396 Disabled,
397 Delayed,
397 Unknown, 398 Unknown,
398}; 399};
399 400
diff --git a/src/input_common/helpers/joycon_protocol/nfc.cpp b/src/input_common/helpers/joycon_protocol/nfc.cpp
index 77ea6d5cf..14818ae33 100644
--- a/src/input_common/helpers/joycon_protocol/nfc.cpp
+++ b/src/input_common/helpers/joycon_protocol/nfc.cpp
@@ -72,6 +72,11 @@ DriverResult NfcProtocol::StartNFCPollingMode() {
72} 72}
73 73
74DriverResult NfcProtocol::ScanAmiibo(std::vector<u8>& data) { 74DriverResult NfcProtocol::ScanAmiibo(std::vector<u8>& data) {
75 if (update_counter++ < AMIIBO_UPDATE_DELAY) {
76 return DriverResult::Delayed;
77 }
78 update_counter = 0;
79
75 LOG_DEBUG(Input, "Start NFC pooling Mode"); 80 LOG_DEBUG(Input, "Start NFC pooling Mode");
76 ScopedSetBlocking sb(this); 81 ScopedSetBlocking sb(this);
77 DriverResult result{DriverResult::Success}; 82 DriverResult result{DriverResult::Success};
@@ -87,7 +92,7 @@ DriverResult NfcProtocol::ScanAmiibo(std::vector<u8>& data) {
87 result = WaitUntilNfcIsReady(); 92 result = WaitUntilNfcIsReady();
88 } 93 }
89 if (result == DriverResult::Success) { 94 if (result == DriverResult::Success) {
90 result = StartPolling(tag_data); 95 result = StartPolling(tag_data, 7);
91 } 96 }
92 if (result == DriverResult::Success) { 97 if (result == DriverResult::Success) {
93 result = GetAmiiboData(data); 98 result = GetAmiiboData(data);
@@ -129,9 +134,8 @@ DriverResult NfcProtocol::WaitUntilNfcIsReady() {
129 return DriverResult::Success; 134 return DriverResult::Success;
130} 135}
131 136
132DriverResult NfcProtocol::StartPolling(TagFoundData& data) { 137DriverResult NfcProtocol::StartPolling(TagFoundData& data, std::size_t timeout_limit) {
133 LOG_DEBUG(Input, "Start Polling for tag"); 138 LOG_DEBUG(Input, "Start Polling for tag");
134 constexpr std::size_t timeout_limit = 7;
135 MCUCommandResponse output{}; 139 MCUCommandResponse output{};
136 std::size_t tries = 0; 140 std::size_t tries = 0;
137 141
diff --git a/src/input_common/helpers/joycon_protocol/nfc.h b/src/input_common/helpers/joycon_protocol/nfc.h
index 11e263e07..4cb992d1d 100644
--- a/src/input_common/helpers/joycon_protocol/nfc.h
+++ b/src/input_common/helpers/joycon_protocol/nfc.h
@@ -32,6 +32,9 @@ public:
32 bool IsEnabled() const; 32 bool IsEnabled() const;
33 33
34private: 34private:
35 // Number of times the function will be delayed until it outputs valid data
36 static constexpr std::size_t AMIIBO_UPDATE_DELAY = 15;
37
35 struct TagFoundData { 38 struct TagFoundData {
36 u8 type; 39 u8 type;
37 std::vector<u8> uuid; 40 std::vector<u8> uuid;
@@ -39,7 +42,7 @@ private:
39 42
40 DriverResult WaitUntilNfcIsReady(); 43 DriverResult WaitUntilNfcIsReady();
41 44
42 DriverResult StartPolling(TagFoundData& data); 45 DriverResult StartPolling(TagFoundData& data, std::size_t timeout_limit = 1);
43 46
44 DriverResult ReadTag(const TagFoundData& data); 47 DriverResult ReadTag(const TagFoundData& data);
45 48
@@ -56,6 +59,7 @@ private:
56 NFCReadBlockCommand GetReadBlockCommand(NFCPages pages) const; 59 NFCReadBlockCommand GetReadBlockCommand(NFCPages pages) const;
57 60
58 bool is_enabled{}; 61 bool is_enabled{};
62 std::size_t update_counter{};
59}; 63};
60 64
61} // namespace InputCommon::Joycon 65} // namespace InputCommon::Joycon
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
index fee510f7b..07c2b7b8a 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
@@ -339,9 +339,7 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex) {
339 if (ctx.profile.support_vertex_instance_id) { 339 if (ctx.profile.support_vertex_instance_id) {
340 return ctx.OpBitcast(ctx.F32[1], ctx.OpLoad(ctx.U32[1], ctx.vertex_id)); 340 return ctx.OpBitcast(ctx.F32[1], ctx.OpLoad(ctx.U32[1], ctx.vertex_id));
341 } else { 341 } else {
342 const Id index{ctx.OpLoad(ctx.U32[1], ctx.vertex_index)}; 342 return ctx.OpBitcast(ctx.F32[1], ctx.OpLoad(ctx.U32[1], ctx.vertex_index));
343 const Id base{ctx.OpLoad(ctx.U32[1], ctx.base_vertex)};
344 return ctx.OpBitcast(ctx.F32[1], ctx.OpISub(ctx.U32[1], index, base));
345 } 343 }
346 case IR::Attribute::BaseInstance: 344 case IR::Attribute::BaseInstance:
347 return ctx.OpBitcast(ctx.F32[1], ctx.OpLoad(ctx.U32[1], ctx.base_instance)); 345 return ctx.OpBitcast(ctx.F32[1], ctx.OpLoad(ctx.U32[1], ctx.base_instance));
@@ -386,9 +384,7 @@ Id EmitGetAttributeU32(EmitContext& ctx, IR::Attribute attr, Id) {
386 if (ctx.profile.support_vertex_instance_id) { 384 if (ctx.profile.support_vertex_instance_id) {
387 return ctx.OpLoad(ctx.U32[1], ctx.vertex_id); 385 return ctx.OpLoad(ctx.U32[1], ctx.vertex_id);
388 } else { 386 } else {
389 const Id index{ctx.OpLoad(ctx.U32[1], ctx.vertex_index)}; 387 return ctx.OpLoad(ctx.U32[1], ctx.vertex_index);
390 const Id base{ctx.OpLoad(ctx.U32[1], ctx.base_vertex)};
391 return ctx.OpISub(ctx.U32[1], index, base);
392 } 388 }
393 case IR::Attribute::BaseInstance: 389 case IR::Attribute::BaseInstance:
394 return ctx.OpLoad(ctx.U32[1], ctx.base_instance); 390 return ctx.OpLoad(ctx.U32[1], ctx.base_instance);
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_mipmap_level.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_mipmap_level.cpp
index 639da1e9c..eeb49444f 100644
--- a/src/shader_recompiler/frontend/maxwell/translate/impl/texture_mipmap_level.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate/impl/texture_mipmap_level.cpp
@@ -102,12 +102,7 @@ void Impl(TranslatorVisitor& v, u64 insn, bool is_bindless) {
102 } 102 }
103 IR::F32 value{v.ir.CompositeExtract(sample, element)}; 103 IR::F32 value{v.ir.CompositeExtract(sample, element)};
104 if (element < 2) { 104 if (element < 2) {
105 IR::U32 casted_value; 105 IR::U32 casted_value = v.ir.ConvertFToU(32, value);
106 if (element == 0) {
107 casted_value = v.ir.ConvertFToU(32, value);
108 } else {
109 casted_value = v.ir.ConvertFToS(16, value);
110 }
111 v.X(dest_reg, v.ir.ShiftLeftLogical(casted_value, v.ir.Imm32(8))); 106 v.X(dest_reg, v.ir.ShiftLeftLogical(casted_value, v.ir.Imm32(8)));
112 } else { 107 } else {
113 v.F(dest_reg, value); 108 v.F(dest_reg, value);
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index fff57ffa9..98756e4da 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -131,33 +131,15 @@ std::optional<VideoCore::RasterizerDownloadArea> BufferCache<P>::GetFlushArea(VA
131 131
132template <class P> 132template <class P>
133void BufferCache<P>::DownloadMemory(VAddr cpu_addr, u64 size) { 133void BufferCache<P>::DownloadMemory(VAddr cpu_addr, u64 size) {
134 WaitOnAsyncFlushes(cpu_addr, size);
135 ForEachBufferInRange(cpu_addr, size, [&](BufferId, Buffer& buffer) { 134 ForEachBufferInRange(cpu_addr, size, [&](BufferId, Buffer& buffer) {
136 DownloadBufferMemory(buffer, cpu_addr, size); 135 DownloadBufferMemory(buffer, cpu_addr, size);
137 }); 136 });
138} 137}
139 138
140template <class P> 139template <class P>
141void BufferCache<P>::WaitOnAsyncFlushes(VAddr cpu_addr, u64 size) {
142 bool must_wait = false;
143 ForEachInOverlapCounter(async_downloads, cpu_addr, size,
144 [&](VAddr, VAddr, int) { must_wait = true; });
145 bool must_release = false;
146 ForEachInRangeSet(pending_ranges, cpu_addr, size, [&](VAddr, VAddr) { must_release = true; });
147 if (must_release) {
148 std::function<void()> tmp([]() {});
149 rasterizer.SignalFence(std::move(tmp));
150 }
151 if (must_wait || must_release) {
152 rasterizer.ReleaseFences();
153 }
154}
155
156template <class P>
157void BufferCache<P>::ClearDownload(IntervalType subtract_interval) { 140void BufferCache<P>::ClearDownload(IntervalType subtract_interval) {
158 RemoveEachInOverlapCounter(async_downloads, subtract_interval, -1024); 141 RemoveEachInOverlapCounter(async_downloads, subtract_interval, -1024);
159 uncommitted_ranges.subtract(subtract_interval); 142 uncommitted_ranges.subtract(subtract_interval);
160 pending_ranges.subtract(subtract_interval);
161 for (auto& interval_set : committed_ranges) { 143 for (auto& interval_set : committed_ranges) {
162 interval_set.subtract(subtract_interval); 144 interval_set.subtract(subtract_interval);
163 } 145 }
@@ -177,7 +159,6 @@ bool BufferCache<P>::DMACopy(GPUVAddr src_address, GPUVAddr dest_address, u64 am
177 } 159 }
178 160
179 const IntervalType subtract_interval{*cpu_dest_address, *cpu_dest_address + amount}; 161 const IntervalType subtract_interval{*cpu_dest_address, *cpu_dest_address + amount};
180 WaitOnAsyncFlushes(*cpu_src_address, static_cast<u32>(amount));
181 ClearDownload(subtract_interval); 162 ClearDownload(subtract_interval);
182 163
183 BufferId buffer_a; 164 BufferId buffer_a;
@@ -205,7 +186,6 @@ bool BufferCache<P>::DMACopy(GPUVAddr src_address, GPUVAddr dest_address, u64 am
205 const IntervalType add_interval{new_base_address, new_base_address + size}; 186 const IntervalType add_interval{new_base_address, new_base_address + size};
206 tmp_intervals.push_back(add_interval); 187 tmp_intervals.push_back(add_interval);
207 uncommitted_ranges.add(add_interval); 188 uncommitted_ranges.add(add_interval);
208 pending_ranges.add(add_interval);
209 }; 189 };
210 ForEachInRangeSet(common_ranges, *cpu_src_address, amount, mirror); 190 ForEachInRangeSet(common_ranges, *cpu_src_address, amount, mirror);
211 // This subtraction in this order is important for overlapping copies. 191 // This subtraction in this order is important for overlapping copies.
@@ -492,7 +472,6 @@ void BufferCache<P>::CommitAsyncFlushesHigh() {
492 } 472 }
493 MICROPROFILE_SCOPE(GPU_DownloadMemory); 473 MICROPROFILE_SCOPE(GPU_DownloadMemory);
494 474
495 pending_ranges.clear();
496 auto it = committed_ranges.begin(); 475 auto it = committed_ranges.begin();
497 while (it != committed_ranges.end()) { 476 while (it != committed_ranges.end()) {
498 auto& current_intervals = *it; 477 auto& current_intervals = *it;
@@ -1232,7 +1211,6 @@ void BufferCache<P>::MarkWrittenBuffer(BufferId buffer_id, VAddr cpu_addr, u32 s
1232 const IntervalType base_interval{cpu_addr, cpu_addr + size}; 1211 const IntervalType base_interval{cpu_addr, cpu_addr + size};
1233 common_ranges.add(base_interval); 1212 common_ranges.add(base_interval);
1234 uncommitted_ranges.add(base_interval); 1213 uncommitted_ranges.add(base_interval);
1235 pending_ranges.add(base_interval);
1236} 1214}
1237 1215
1238template <class P> 1216template <class P>
@@ -1677,14 +1655,15 @@ typename BufferCache<P>::Binding BufferCache<P>::StorageBufferBinding(GPUVAddr s
1677 const bool is_nvn_cbuf = cbuf_index == 0; 1655 const bool is_nvn_cbuf = cbuf_index == 0;
1678 // The NVN driver buffer (index 0) is known to pack the SSBO address followed by its size. 1656 // The NVN driver buffer (index 0) is known to pack the SSBO address followed by its size.
1679 if (is_nvn_cbuf) { 1657 if (is_nvn_cbuf) {
1680 return gpu_memory->Read<u32>(ssbo_addr + 8); 1658 const u32 ssbo_size = gpu_memory->Read<u32>(ssbo_addr + 8);
1659 if (ssbo_size != 0) {
1660 return ssbo_size;
1661 }
1681 } 1662 }
1682 // Other titles (notably Doom Eternal) may use STG/LDG on buffer addresses in custom defined 1663 // Other titles (notably Doom Eternal) may use STG/LDG on buffer addresses in custom defined
1683 // cbufs, which do not store the sizes adjacent to the addresses, so use the fully 1664 // cbufs, which do not store the sizes adjacent to the addresses, so use the fully
1684 // mapped buffer size for now. 1665 // mapped buffer size for now.
1685 const u32 memory_layout_size = static_cast<u32>(gpu_memory->GetMemoryLayoutSize(gpu_addr)); 1666 const u32 memory_layout_size = static_cast<u32>(gpu_memory->GetMemoryLayoutSize(gpu_addr));
1686 LOG_INFO(HW_GPU, "Binding storage buffer for cbuf index {}, MemoryLayoutSize 0x{:X}",
1687 cbuf_index, memory_layout_size);
1688 return memory_layout_size; 1667 return memory_layout_size;
1689 }(); 1668 }();
1690 const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr); 1669 const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr);
diff --git a/src/video_core/buffer_cache/buffer_cache_base.h b/src/video_core/buffer_cache/buffer_cache_base.h
index 0445ec47f..ac00d4d9d 100644
--- a/src/video_core/buffer_cache/buffer_cache_base.h
+++ b/src/video_core/buffer_cache/buffer_cache_base.h
@@ -381,8 +381,6 @@ private:
381 381
382 void RunGarbageCollector(); 382 void RunGarbageCollector();
383 383
384 void WaitOnAsyncFlushes(VAddr cpu_addr, u64 size);
385
386 void BindHostIndexBuffer(); 384 void BindHostIndexBuffer();
387 385
388 void BindHostVertexBuffers(); 386 void BindHostVertexBuffers();
@@ -547,7 +545,6 @@ private:
547 IntervalSet uncommitted_ranges; 545 IntervalSet uncommitted_ranges;
548 IntervalSet common_ranges; 546 IntervalSet common_ranges;
549 IntervalSet cached_ranges; 547 IntervalSet cached_ranges;
550 IntervalSet pending_ranges;
551 std::deque<IntervalSet> committed_ranges; 548 std::deque<IntervalSet> committed_ranges;
552 549
553 // Async Buffers 550 // Async Buffers
diff --git a/src/video_core/host1x/codecs/h264.cpp b/src/video_core/host1x/codecs/h264.cpp
index e87bd65fa..6ce179167 100644
--- a/src/video_core/host1x/codecs/h264.cpp
+++ b/src/video_core/host1x/codecs/h264.cpp
@@ -111,7 +111,7 @@ const std::vector<u8>& H264::ComposeFrame(const Host1x::NvdecCommon::NvdecRegist
111 writer.WriteUe(0); 111 writer.WriteUe(0);
112 112
113 writer.WriteBit(context.h264_parameter_set.entropy_coding_mode_flag != 0); 113 writer.WriteBit(context.h264_parameter_set.entropy_coding_mode_flag != 0);
114 writer.WriteBit(false); 114 writer.WriteBit(context.h264_parameter_set.pic_order_present_flag != 0);
115 writer.WriteUe(0); 115 writer.WriteUe(0);
116 writer.WriteUe(context.h264_parameter_set.num_refidx_l0_default_active); 116 writer.WriteUe(context.h264_parameter_set.num_refidx_l0_default_active);
117 writer.WriteUe(context.h264_parameter_set.num_refidx_l1_default_active); 117 writer.WriteUe(context.h264_parameter_set.num_refidx_l1_default_active);
@@ -129,7 +129,7 @@ const std::vector<u8>& H264::ComposeFrame(const Host1x::NvdecCommon::NvdecRegist
129 writer.WriteBit(context.h264_parameter_set.redundant_pic_cnt_present_flag != 0); 129 writer.WriteBit(context.h264_parameter_set.redundant_pic_cnt_present_flag != 0);
130 writer.WriteBit(context.h264_parameter_set.transform_8x8_mode_flag != 0); 130 writer.WriteBit(context.h264_parameter_set.transform_8x8_mode_flag != 0);
131 131
132 writer.WriteBit(true); 132 writer.WriteBit(true); // pic_scaling_matrix_present_flag
133 133
134 for (s32 index = 0; index < 6; index++) { 134 for (s32 index = 0; index < 6; index++) {
135 writer.WriteBit(true); 135 writer.WriteBit(true);
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index 596996bec..66dfe5733 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -698,7 +698,8 @@ std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline(
698 PipelineStatistics* statistics, bool build_in_parallel) try { 698 PipelineStatistics* statistics, bool build_in_parallel) try {
699 // TODO: Remove this when Intel fixes their shader compiler. 699 // TODO: Remove this when Intel fixes their shader compiler.
700 // https://github.com/IGCIT/Intel-GPU-Community-Issue-Tracker-IGCIT/issues/159 700 // https://github.com/IGCIT/Intel-GPU-Community-Issue-Tracker-IGCIT/issues/159
701 if (device.GetDriverID() == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS) { 701 if (device.GetDriverID() == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS &&
702 !Settings::values.enable_compute_pipelines.GetValue()) {
702 LOG_ERROR(Render_Vulkan, "Skipping 0x{:016x}", key.Hash()); 703 LOG_ERROR(Render_Vulkan, "Skipping 0x{:016x}", key.Hash());
703 return nullptr; 704 return nullptr;
704 } 705 }
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 64bd2f6a5..8d3a9736b 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -348,25 +348,12 @@ void RasterizerVulkan::Clear(u32 layer_count) {
348 348
349 const u32 color_attachment = regs.clear_surface.RT; 349 const u32 color_attachment = regs.clear_surface.RT;
350 if (use_color && framebuffer->HasAspectColorBit(color_attachment)) { 350 if (use_color && framebuffer->HasAspectColorBit(color_attachment)) {
351 VkClearValue clear_value; 351 const auto format =
352 bool is_integer = false; 352 VideoCore::Surface::PixelFormatFromRenderTargetFormat(regs.rt[color_attachment].format);
353 bool is_signed = false; 353 bool is_integer = IsPixelFormatInteger(format);
354 size_t int_size = 8; 354 bool is_signed = IsPixelFormatSignedInteger(format);
355 for (std::size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; ++i) { 355 size_t int_size = PixelComponentSizeBitsInteger(format);
356 const auto& this_rt = regs.rt[i]; 356 VkClearValue clear_value{};
357 if (this_rt.Address() == 0) {
358 continue;
359 }
360 if (this_rt.format == Tegra::RenderTargetFormat::NONE) {
361 continue;
362 }
363 const auto format =
364 VideoCore::Surface::PixelFormatFromRenderTargetFormat(this_rt.format);
365 is_integer = IsPixelFormatInteger(format);
366 is_signed = IsPixelFormatSignedInteger(format);
367 int_size = PixelComponentSizeBitsInteger(format);
368 break;
369 }
370 if (!is_integer) { 357 if (!is_integer) {
371 std::memcpy(clear_value.color.float32, regs.clear_color.data(), 358 std::memcpy(clear_value.color.float32, regs.clear_color.data(),
372 regs.clear_color.size() * sizeof(f32)); 359 regs.clear_color.size() * sizeof(f32));
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp
index 7132bae99..9a8763e6a 100644
--- a/src/video_core/vulkan_common/vulkan_device.cpp
+++ b/src/video_core/vulkan_common/vulkan_device.cpp
@@ -1017,6 +1017,8 @@ void Device::CollectPhysicalMemoryInfo() {
1017 device_access_memory += mem_properties.memoryHeaps[element].size; 1017 device_access_memory += mem_properties.memoryHeaps[element].size;
1018 } 1018 }
1019 if (!is_integrated) { 1019 if (!is_integrated) {
1020 const u64 reserve_memory = std::min<u64>(device_access_memory / 8, 1_GiB);
1021 device_access_memory -= reserve_memory;
1020 return; 1022 return;
1021 } 1023 }
1022 const s64 available_memory = static_cast<s64>(device_access_memory - device_initial_usage); 1024 const s64 available_memory = static_cast<s64>(device_access_memory - device_initial_usage);
diff --git a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp
index 1732866e0..e28a556f8 100644
--- a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp
+++ b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp
@@ -147,7 +147,7 @@ public:
147 147
148 /// Returns whether this allocation is compatible with the arguments. 148 /// Returns whether this allocation is compatible with the arguments.
149 [[nodiscard]] bool IsCompatible(VkMemoryPropertyFlags flags, u32 type_mask) const { 149 [[nodiscard]] bool IsCompatible(VkMemoryPropertyFlags flags, u32 type_mask) const {
150 return (flags & property_flags) == property_flags && (type_mask & shifted_memory_type) != 0; 150 return (flags & property_flags) == flags && (type_mask & shifted_memory_type) != 0;
151 } 151 }
152 152
153private: 153private:
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index b94d36838..70737c54e 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -716,6 +716,7 @@ void Config::ReadRendererValues() {
716 ReadGlobalSetting(Settings::values.use_asynchronous_shaders); 716 ReadGlobalSetting(Settings::values.use_asynchronous_shaders);
717 ReadGlobalSetting(Settings::values.use_fast_gpu_time); 717 ReadGlobalSetting(Settings::values.use_fast_gpu_time);
718 ReadGlobalSetting(Settings::values.use_vulkan_driver_pipeline_cache); 718 ReadGlobalSetting(Settings::values.use_vulkan_driver_pipeline_cache);
719 ReadGlobalSetting(Settings::values.enable_compute_pipelines);
719 ReadGlobalSetting(Settings::values.bg_red); 720 ReadGlobalSetting(Settings::values.bg_red);
720 ReadGlobalSetting(Settings::values.bg_green); 721 ReadGlobalSetting(Settings::values.bg_green);
721 ReadGlobalSetting(Settings::values.bg_blue); 722 ReadGlobalSetting(Settings::values.bg_blue);
@@ -1366,6 +1367,7 @@ void Config::SaveRendererValues() {
1366 WriteGlobalSetting(Settings::values.use_asynchronous_shaders); 1367 WriteGlobalSetting(Settings::values.use_asynchronous_shaders);
1367 WriteGlobalSetting(Settings::values.use_fast_gpu_time); 1368 WriteGlobalSetting(Settings::values.use_fast_gpu_time);
1368 WriteGlobalSetting(Settings::values.use_vulkan_driver_pipeline_cache); 1369 WriteGlobalSetting(Settings::values.use_vulkan_driver_pipeline_cache);
1370 WriteGlobalSetting(Settings::values.enable_compute_pipelines);
1369 WriteGlobalSetting(Settings::values.bg_red); 1371 WriteGlobalSetting(Settings::values.bg_red);
1370 WriteGlobalSetting(Settings::values.bg_green); 1372 WriteGlobalSetting(Settings::values.bg_green);
1371 WriteGlobalSetting(Settings::values.bg_blue); 1373 WriteGlobalSetting(Settings::values.bg_blue);
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp
index 2aaefcc05..8e76a819a 100644
--- a/src/yuzu/configuration/configure_dialog.cpp
+++ b/src/yuzu/configuration/configure_dialog.cpp
@@ -36,8 +36,9 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_,
36 debug_tab_tab{std::make_unique<ConfigureDebugTab>(system_, this)}, 36 debug_tab_tab{std::make_unique<ConfigureDebugTab>(system_, this)},
37 filesystem_tab{std::make_unique<ConfigureFilesystem>(this)}, 37 filesystem_tab{std::make_unique<ConfigureFilesystem>(this)},
38 general_tab{std::make_unique<ConfigureGeneral>(system_, this)}, 38 general_tab{std::make_unique<ConfigureGeneral>(system_, this)},
39 graphics_tab{std::make_unique<ConfigureGraphics>(system_, this)},
40 graphics_advanced_tab{std::make_unique<ConfigureGraphicsAdvanced>(system_, this)}, 39 graphics_advanced_tab{std::make_unique<ConfigureGraphicsAdvanced>(system_, this)},
40 graphics_tab{std::make_unique<ConfigureGraphics>(
41 system_, [&]() { graphics_advanced_tab->ExposeComputeOption(); }, this)},
41 hotkeys_tab{std::make_unique<ConfigureHotkeys>(system_.HIDCore(), this)}, 42 hotkeys_tab{std::make_unique<ConfigureHotkeys>(system_.HIDCore(), this)},
42 input_tab{std::make_unique<ConfigureInput>(system_, this)}, 43 input_tab{std::make_unique<ConfigureInput>(system_, this)},
43 network_tab{std::make_unique<ConfigureNetwork>(system_, this)}, 44 network_tab{std::make_unique<ConfigureNetwork>(system_, this)},
diff --git a/src/yuzu/configuration/configure_dialog.h b/src/yuzu/configuration/configure_dialog.h
index 1f724834a..a086a07c4 100644
--- a/src/yuzu/configuration/configure_dialog.h
+++ b/src/yuzu/configuration/configure_dialog.h
@@ -72,8 +72,8 @@ private:
72 std::unique_ptr<ConfigureDebugTab> debug_tab_tab; 72 std::unique_ptr<ConfigureDebugTab> debug_tab_tab;
73 std::unique_ptr<ConfigureFilesystem> filesystem_tab; 73 std::unique_ptr<ConfigureFilesystem> filesystem_tab;
74 std::unique_ptr<ConfigureGeneral> general_tab; 74 std::unique_ptr<ConfigureGeneral> general_tab;
75 std::unique_ptr<ConfigureGraphics> graphics_tab;
76 std::unique_ptr<ConfigureGraphicsAdvanced> graphics_advanced_tab; 75 std::unique_ptr<ConfigureGraphicsAdvanced> graphics_advanced_tab;
76 std::unique_ptr<ConfigureGraphics> graphics_tab;
77 std::unique_ptr<ConfigureHotkeys> hotkeys_tab; 77 std::unique_ptr<ConfigureHotkeys> hotkeys_tab;
78 std::unique_ptr<ConfigureInput> input_tab; 78 std::unique_ptr<ConfigureInput> input_tab;
79 std::unique_ptr<ConfigureNetwork> network_tab; 79 std::unique_ptr<ConfigureNetwork> network_tab;
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp
index 76e5b7499..f316b598c 100644
--- a/src/yuzu/configuration/configure_graphics.cpp
+++ b/src/yuzu/configuration/configure_graphics.cpp
@@ -2,9 +2,11 @@
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4// Include this early to include Vulkan headers how we want to 4// Include this early to include Vulkan headers how we want to
5#include "video_core/vulkan_common/vulkan_device.h"
5#include "video_core/vulkan_common/vulkan_wrapper.h" 6#include "video_core/vulkan_common/vulkan_wrapper.h"
6 7
7#include <algorithm> 8#include <algorithm>
9#include <functional>
8#include <iosfwd> 10#include <iosfwd>
9#include <iterator> 11#include <iterator>
10#include <string> 12#include <string>
@@ -74,8 +76,11 @@ static constexpr Settings::VSyncMode PresentModeToSetting(VkPresentModeKHR mode)
74 } 76 }
75} 77}
76 78
77ConfigureGraphics::ConfigureGraphics(const Core::System& system_, QWidget* parent) 79ConfigureGraphics::ConfigureGraphics(const Core::System& system_,
78 : QWidget(parent), ui{std::make_unique<Ui::ConfigureGraphics>()}, system{system_} { 80 const std::function<void()>& expose_compute_option_,
81 QWidget* parent)
82 : QWidget(parent), ui{std::make_unique<Ui::ConfigureGraphics>()},
83 expose_compute_option{expose_compute_option_}, system{system_} {
79 vulkan_device = Settings::values.vulkan_device.GetValue(); 84 vulkan_device = Settings::values.vulkan_device.GetValue();
80 RetrieveVulkanDevices(); 85 RetrieveVulkanDevices();
81 86
@@ -513,8 +518,7 @@ void ConfigureGraphics::RetrieveVulkanDevices() try {
513 const Common::DynamicLibrary library = OpenLibrary(); 518 const Common::DynamicLibrary library = OpenLibrary();
514 const vk::Instance instance = CreateInstance(library, dld, VK_API_VERSION_1_1, wsi.type); 519 const vk::Instance instance = CreateInstance(library, dld, VK_API_VERSION_1_1, wsi.type);
515 const std::vector<VkPhysicalDevice> physical_devices = instance.EnumeratePhysicalDevices(); 520 const std::vector<VkPhysicalDevice> physical_devices = instance.EnumeratePhysicalDevices();
516 vk::SurfaceKHR surface = //< needed to view present modes for a device 521 vk::SurfaceKHR surface = CreateSurface(instance, wsi);
517 CreateSurface(instance, wsi);
518 522
519 vulkan_devices.clear(); 523 vulkan_devices.clear();
520 vulkan_devices.reserve(physical_devices.size()); 524 vulkan_devices.reserve(physical_devices.size());
@@ -527,6 +531,17 @@ void ConfigureGraphics::RetrieveVulkanDevices() try {
527 physical_device.GetSurfacePresentModesKHR(*surface); 531 physical_device.GetSurfacePresentModesKHR(*surface);
528 vulkan_devices.push_back(QString::fromStdString(name)); 532 vulkan_devices.push_back(QString::fromStdString(name));
529 device_present_modes.push_back(present_modes); 533 device_present_modes.push_back(present_modes);
534
535 VkPhysicalDeviceDriverProperties driver_properties{};
536 driver_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES;
537 driver_properties.pNext = nullptr;
538 VkPhysicalDeviceProperties2 properties{};
539 properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR;
540 properties.pNext = &driver_properties;
541 dld.vkGetPhysicalDeviceProperties2(physical_device, &properties);
542 if (driver_properties.driverID == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS) {
543 expose_compute_option();
544 }
530 } 545 }
531} catch (const Vulkan::vk::Exception& exception) { 546} catch (const Vulkan::vk::Exception& exception) {
532 LOG_ERROR(Frontend, "Failed to enumerate devices with error: {}", exception.what()); 547 LOG_ERROR(Frontend, "Failed to enumerate devices with error: {}", exception.what());
diff --git a/src/yuzu/configuration/configure_graphics.h b/src/yuzu/configuration/configure_graphics.h
index 901f604a5..364b1cac2 100644
--- a/src/yuzu/configuration/configure_graphics.h
+++ b/src/yuzu/configuration/configure_graphics.h
@@ -3,6 +3,7 @@
3 3
4#pragma once 4#pragma once
5 5
6#include <functional>
6#include <memory> 7#include <memory>
7#include <vector> 8#include <vector>
8#include <QColor> 9#include <QColor>
@@ -37,7 +38,9 @@ class ConfigureGraphics : public QWidget {
37 Q_OBJECT 38 Q_OBJECT
38 39
39public: 40public:
40 explicit ConfigureGraphics(const Core::System& system_, QWidget* parent = nullptr); 41 explicit ConfigureGraphics(const Core::System& system_,
42 const std::function<void()>& expose_compute_option_,
43 QWidget* parent = nullptr);
41 ~ConfigureGraphics() override; 44 ~ConfigureGraphics() override;
42 45
43 void ApplyConfiguration(); 46 void ApplyConfiguration();
@@ -81,6 +84,7 @@ private:
81 // selection in the combobox 84 // selection in the combobox
82 u32 vulkan_device{}; 85 u32 vulkan_device{};
83 Settings::ShaderBackend shader_backend{}; 86 Settings::ShaderBackend shader_backend{};
87 const std::function<void()>& expose_compute_option;
84 88
85 const Core::System& system; 89 const Core::System& system;
86}; 90};
diff --git a/src/yuzu/configuration/configure_graphics_advanced.cpp b/src/yuzu/configuration/configure_graphics_advanced.cpp
index 627ed8b17..1f3e489d0 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.cpp
+++ b/src/yuzu/configuration/configure_graphics_advanced.cpp
@@ -15,6 +15,8 @@ ConfigureGraphicsAdvanced::ConfigureGraphicsAdvanced(const Core::System& system_
15 SetupPerGameUI(); 15 SetupPerGameUI();
16 16
17 SetConfiguration(); 17 SetConfiguration();
18
19 ui->enable_compute_pipelines_checkbox->setVisible(false);
18} 20}
19 21
20ConfigureGraphicsAdvanced::~ConfigureGraphicsAdvanced() = default; 22ConfigureGraphicsAdvanced::~ConfigureGraphicsAdvanced() = default;
@@ -27,6 +29,7 @@ void ConfigureGraphicsAdvanced::SetConfiguration() {
27 ui->async_astc->setEnabled(runtime_lock); 29 ui->async_astc->setEnabled(runtime_lock);
28 ui->use_asynchronous_shaders->setEnabled(runtime_lock); 30 ui->use_asynchronous_shaders->setEnabled(runtime_lock);
29 ui->anisotropic_filtering_combobox->setEnabled(runtime_lock); 31 ui->anisotropic_filtering_combobox->setEnabled(runtime_lock);
32 ui->enable_compute_pipelines_checkbox->setEnabled(runtime_lock);
30 33
31 ui->async_present->setChecked(Settings::values.async_presentation.GetValue()); 34 ui->async_present->setChecked(Settings::values.async_presentation.GetValue());
32 ui->renderer_force_max_clock->setChecked(Settings::values.renderer_force_max_clock.GetValue()); 35 ui->renderer_force_max_clock->setChecked(Settings::values.renderer_force_max_clock.GetValue());
@@ -36,6 +39,8 @@ void ConfigureGraphicsAdvanced::SetConfiguration() {
36 ui->use_fast_gpu_time->setChecked(Settings::values.use_fast_gpu_time.GetValue()); 39 ui->use_fast_gpu_time->setChecked(Settings::values.use_fast_gpu_time.GetValue());
37 ui->use_vulkan_driver_pipeline_cache->setChecked( 40 ui->use_vulkan_driver_pipeline_cache->setChecked(
38 Settings::values.use_vulkan_driver_pipeline_cache.GetValue()); 41 Settings::values.use_vulkan_driver_pipeline_cache.GetValue());
42 ui->enable_compute_pipelines_checkbox->setChecked(
43 Settings::values.enable_compute_pipelines.GetValue());
39 44
40 if (Settings::IsConfiguringGlobal()) { 45 if (Settings::IsConfiguringGlobal()) {
41 ui->gpu_accuracy->setCurrentIndex( 46 ui->gpu_accuracy->setCurrentIndex(
@@ -74,6 +79,9 @@ void ConfigureGraphicsAdvanced::ApplyConfiguration() {
74 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vulkan_driver_pipeline_cache, 79 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vulkan_driver_pipeline_cache,
75 ui->use_vulkan_driver_pipeline_cache, 80 ui->use_vulkan_driver_pipeline_cache,
76 use_vulkan_driver_pipeline_cache); 81 use_vulkan_driver_pipeline_cache);
82 ConfigurationShared::ApplyPerGameSetting(&Settings::values.enable_compute_pipelines,
83 ui->enable_compute_pipelines_checkbox,
84 enable_compute_pipelines);
77} 85}
78 86
79void ConfigureGraphicsAdvanced::changeEvent(QEvent* event) { 87void ConfigureGraphicsAdvanced::changeEvent(QEvent* event) {
@@ -104,6 +112,8 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() {
104 Settings::values.use_vulkan_driver_pipeline_cache.UsingGlobal()); 112 Settings::values.use_vulkan_driver_pipeline_cache.UsingGlobal());
105 ui->anisotropic_filtering_combobox->setEnabled( 113 ui->anisotropic_filtering_combobox->setEnabled(
106 Settings::values.max_anisotropy.UsingGlobal()); 114 Settings::values.max_anisotropy.UsingGlobal());
115 ui->enable_compute_pipelines_checkbox->setEnabled(
116 Settings::values.enable_compute_pipelines.UsingGlobal());
107 117
108 return; 118 return;
109 } 119 }
@@ -125,6 +135,9 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() {
125 ConfigurationShared::SetColoredTristate(ui->use_vulkan_driver_pipeline_cache, 135 ConfigurationShared::SetColoredTristate(ui->use_vulkan_driver_pipeline_cache,
126 Settings::values.use_vulkan_driver_pipeline_cache, 136 Settings::values.use_vulkan_driver_pipeline_cache,
127 use_vulkan_driver_pipeline_cache); 137 use_vulkan_driver_pipeline_cache);
138 ConfigurationShared::SetColoredTristate(ui->enable_compute_pipelines_checkbox,
139 Settings::values.enable_compute_pipelines,
140 enable_compute_pipelines);
128 ConfigurationShared::SetColoredComboBox( 141 ConfigurationShared::SetColoredComboBox(
129 ui->gpu_accuracy, ui->label_gpu_accuracy, 142 ui->gpu_accuracy, ui->label_gpu_accuracy,
130 static_cast<int>(Settings::values.gpu_accuracy.GetValue(true))); 143 static_cast<int>(Settings::values.gpu_accuracy.GetValue(true)));
@@ -132,3 +145,7 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() {
132 ui->anisotropic_filtering_combobox, ui->af_label, 145 ui->anisotropic_filtering_combobox, ui->af_label,
133 static_cast<int>(Settings::values.max_anisotropy.GetValue(true))); 146 static_cast<int>(Settings::values.max_anisotropy.GetValue(true)));
134} 147}
148
149void ConfigureGraphicsAdvanced::ExposeComputeOption() {
150 ui->enable_compute_pipelines_checkbox->setVisible(true);
151}
diff --git a/src/yuzu/configuration/configure_graphics_advanced.h b/src/yuzu/configuration/configure_graphics_advanced.h
index ae3c10946..1c7b636b9 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.h
+++ b/src/yuzu/configuration/configure_graphics_advanced.h
@@ -28,6 +28,8 @@ public:
28 void ApplyConfiguration(); 28 void ApplyConfiguration();
29 void SetConfiguration(); 29 void SetConfiguration();
30 30
31 void ExposeComputeOption();
32
31private: 33private:
32 void changeEvent(QEvent* event) override; 34 void changeEvent(QEvent* event) override;
33 void RetranslateUI(); 35 void RetranslateUI();
@@ -44,6 +46,7 @@ private:
44 ConfigurationShared::CheckState use_asynchronous_shaders; 46 ConfigurationShared::CheckState use_asynchronous_shaders;
45 ConfigurationShared::CheckState use_fast_gpu_time; 47 ConfigurationShared::CheckState use_fast_gpu_time;
46 ConfigurationShared::CheckState use_vulkan_driver_pipeline_cache; 48 ConfigurationShared::CheckState use_vulkan_driver_pipeline_cache;
49 ConfigurationShared::CheckState enable_compute_pipelines;
47 50
48 const Core::System& system; 51 const Core::System& system;
49}; 52};
diff --git a/src/yuzu/configuration/configure_graphics_advanced.ui b/src/yuzu/configuration/configure_graphics_advanced.ui
index 9d8cbea09..9ef7c8e8f 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.ui
+++ b/src/yuzu/configuration/configure_graphics_advanced.ui
@@ -137,6 +137,17 @@
137 </widget> 137 </widget>
138 </item> 138 </item>
139 <item> 139 <item>
140 <widget class="QCheckBox" name="enable_compute_pipelines_checkbox">
141 <property name="toolTip">
142 <string>Enable compute pipelines, required by some games. This setting only exists for Intel proprietary drivers, and may crash if enabled.
143Compute pipelines are always enabled on all other drivers.</string>
144 </property>
145 <property name="text">
146 <string>Enable Compute Pipelines (Intel Vulkan only)</string>
147 </property>
148 </widget>
149 </item>
150 <item>
140 <widget class="QWidget" name="af_layout" native="true"> 151 <widget class="QWidget" name="af_layout" native="true">
141 <layout class="QHBoxLayout" name="horizontalLayout_1"> 152 <layout class="QHBoxLayout" name="horizontalLayout_1">
142 <property name="leftMargin"> 153 <property name="leftMargin">
diff --git a/src/yuzu/configuration/configure_hotkeys.cpp b/src/yuzu/configuration/configure_hotkeys.cpp
index daa77a8f8..0b2a965f8 100644
--- a/src/yuzu/configuration/configure_hotkeys.cpp
+++ b/src/yuzu/configuration/configure_hotkeys.cpp
@@ -48,7 +48,9 @@ ConfigureHotkeys::ConfigureHotkeys(Core::HID::HIDCore& hid_core, QWidget* parent
48 48
49 connect(poll_timer.get(), &QTimer::timeout, [this] { 49 connect(poll_timer.get(), &QTimer::timeout, [this] {
50 const auto buttons = controller->GetNpadButtons(); 50 const auto buttons = controller->GetNpadButtons();
51 if (buttons.raw != Core::HID::NpadButton::None) { 51 const auto home_pressed = controller->GetHomeButtons().home != 0;
52 const auto capture_pressed = controller->GetCaptureButtons().capture != 0;
53 if (home_pressed || capture_pressed) {
52 SetPollingResult(buttons.raw, false); 54 SetPollingResult(buttons.raw, false);
53 return; 55 return;
54 } 56 }
@@ -154,8 +156,10 @@ void ConfigureHotkeys::ConfigureController(QModelIndex index) {
154 model->setData(index, previous_key); 156 model->setData(index, previous_key);
155 return; 157 return;
156 } 158 }
157 159 const auto home_pressed = this->controller->GetHomeButtons().home != 0;
158 const QString button_string = tr("Home+%1").arg(GetButtonName(button)); 160 const auto capture_pressed = this->controller->GetCaptureButtons().capture != 0;
161 const QString button_string =
162 GetButtonCombinationName(button, home_pressed, capture_pressed);
159 163
160 const auto [key_sequence_used, used_action] = IsUsedControllerKey(button_string); 164 const auto [key_sequence_used, used_action] = IsUsedControllerKey(button_string);
161 165
@@ -174,72 +178,83 @@ void ConfigureHotkeys::ConfigureController(QModelIndex index) {
174 poll_timer->start(200); // Check for new inputs every 200ms 178 poll_timer->start(200); // Check for new inputs every 200ms
175 // We need to disable configuration to be able to read npad buttons 179 // We need to disable configuration to be able to read npad buttons
176 controller->DisableConfiguration(); 180 controller->DisableConfiguration();
177 controller->DisableSystemButtons();
178} 181}
179 182
180void ConfigureHotkeys::SetPollingResult(Core::HID::NpadButton button, const bool cancel) { 183void ConfigureHotkeys::SetPollingResult(Core::HID::NpadButton button, const bool cancel) {
181 timeout_timer->stop(); 184 timeout_timer->stop();
182 poll_timer->stop(); 185 poll_timer->stop();
186 (*input_setter)(button, cancel);
183 // Re-Enable configuration 187 // Re-Enable configuration
184 controller->EnableConfiguration(); 188 controller->EnableConfiguration();
185 controller->EnableSystemButtons();
186
187 (*input_setter)(button, cancel);
188 189
189 input_setter = std::nullopt; 190 input_setter = std::nullopt;
190} 191}
191 192
192QString ConfigureHotkeys::GetButtonName(Core::HID::NpadButton button) const { 193QString ConfigureHotkeys::GetButtonCombinationName(Core::HID::NpadButton button,
194 const bool home = false,
195 const bool capture = false) const {
193 Core::HID::NpadButtonState state{button}; 196 Core::HID::NpadButtonState state{button};
197 QString button_combination;
198 if (home) {
199 button_combination.append(QStringLiteral("Home+"));
200 }
201 if (capture) {
202 button_combination.append(QStringLiteral("Screenshot+"));
203 }
194 if (state.a) { 204 if (state.a) {
195 return QStringLiteral("A"); 205 button_combination.append(QStringLiteral("A+"));
196 } 206 }
197 if (state.b) { 207 if (state.b) {
198 return QStringLiteral("B"); 208 button_combination.append(QStringLiteral("B+"));
199 } 209 }
200 if (state.x) { 210 if (state.x) {
201 return QStringLiteral("X"); 211 button_combination.append(QStringLiteral("X+"));
202 } 212 }
203 if (state.y) { 213 if (state.y) {
204 return QStringLiteral("Y"); 214 button_combination.append(QStringLiteral("Y+"));
205 } 215 }
206 if (state.l || state.right_sl || state.left_sl) { 216 if (state.l || state.right_sl || state.left_sl) {
207 return QStringLiteral("L"); 217 button_combination.append(QStringLiteral("L+"));
208 } 218 }
209 if (state.r || state.right_sr || state.left_sr) { 219 if (state.r || state.right_sr || state.left_sr) {
210 return QStringLiteral("R"); 220 button_combination.append(QStringLiteral("R+"));
211 } 221 }
212 if (state.zl) { 222 if (state.zl) {
213 return QStringLiteral("ZL"); 223 button_combination.append(QStringLiteral("ZL+"));
214 } 224 }
215 if (state.zr) { 225 if (state.zr) {
216 return QStringLiteral("ZR"); 226 button_combination.append(QStringLiteral("ZR+"));
217 } 227 }
218 if (state.left) { 228 if (state.left) {
219 return QStringLiteral("Dpad_Left"); 229 button_combination.append(QStringLiteral("Dpad_Left+"));
220 } 230 }
221 if (state.right) { 231 if (state.right) {
222 return QStringLiteral("Dpad_Right"); 232 button_combination.append(QStringLiteral("Dpad_Right+"));
223 } 233 }
224 if (state.up) { 234 if (state.up) {
225 return QStringLiteral("Dpad_Up"); 235 button_combination.append(QStringLiteral("Dpad_Up+"));
226 } 236 }
227 if (state.down) { 237 if (state.down) {
228 return QStringLiteral("Dpad_Down"); 238 button_combination.append(QStringLiteral("Dpad_Down+"));
229 } 239 }
230 if (state.stick_l) { 240 if (state.stick_l) {
231 return QStringLiteral("Left_Stick"); 241 button_combination.append(QStringLiteral("Left_Stick+"));
232 } 242 }
233 if (state.stick_r) { 243 if (state.stick_r) {
234 return QStringLiteral("Right_Stick"); 244 button_combination.append(QStringLiteral("Right_Stick+"));
235 } 245 }
236 if (state.minus) { 246 if (state.minus) {
237 return QStringLiteral("Minus"); 247 button_combination.append(QStringLiteral("Minus+"));
238 } 248 }
239 if (state.plus) { 249 if (state.plus) {
240 return QStringLiteral("Plus"); 250 button_combination.append(QStringLiteral("Plus+"));
251 }
252 if (button_combination.isEmpty()) {
253 return tr("Invalid");
254 } else {
255 button_combination.chop(1);
256 return button_combination;
241 } 257 }
242 return tr("Invalid");
243} 258}
244 259
245std::pair<bool, QString> ConfigureHotkeys::IsUsedKey(QKeySequence key_sequence) const { 260std::pair<bool, QString> ConfigureHotkeys::IsUsedKey(QKeySequence key_sequence) const {
diff --git a/src/yuzu/configuration/configure_hotkeys.h b/src/yuzu/configuration/configure_hotkeys.h
index e8e414320..5fd1bcbfe 100644
--- a/src/yuzu/configuration/configure_hotkeys.h
+++ b/src/yuzu/configuration/configure_hotkeys.h
@@ -59,7 +59,7 @@ private:
59 QStandardItemModel* model; 59 QStandardItemModel* model;
60 60
61 void SetPollingResult(Core::HID::NpadButton button, bool cancel); 61 void SetPollingResult(Core::HID::NpadButton button, bool cancel);
62 QString GetButtonName(Core::HID::NpadButton button) const; 62 QString GetButtonCombinationName(Core::HID::NpadButton button, bool home, bool capture) const;
63 Core::HID::EmulatedController* controller; 63 Core::HID::EmulatedController* controller;
64 std::unique_ptr<QTimer> timeout_timer; 64 std::unique_ptr<QTimer> timeout_timer;
65 std::unique_ptr<QTimer> poll_timer; 65 std::unique_ptr<QTimer> poll_timer;
diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp
index 7e757eafd..7ac162586 100644
--- a/src/yuzu/configuration/configure_per_game.cpp
+++ b/src/yuzu/configuration/configure_per_game.cpp
@@ -48,8 +48,9 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::st
48 audio_tab = std::make_unique<ConfigureAudio>(system_, this); 48 audio_tab = std::make_unique<ConfigureAudio>(system_, this);
49 cpu_tab = std::make_unique<ConfigureCpu>(system_, this); 49 cpu_tab = std::make_unique<ConfigureCpu>(system_, this);
50 general_tab = std::make_unique<ConfigureGeneral>(system_, this); 50 general_tab = std::make_unique<ConfigureGeneral>(system_, this);
51 graphics_tab = std::make_unique<ConfigureGraphics>(system_, this);
52 graphics_advanced_tab = std::make_unique<ConfigureGraphicsAdvanced>(system_, this); 51 graphics_advanced_tab = std::make_unique<ConfigureGraphicsAdvanced>(system_, this);
52 graphics_tab = std::make_unique<ConfigureGraphics>(
53 system_, [&]() { graphics_advanced_tab->ExposeComputeOption(); }, this);
53 input_tab = std::make_unique<ConfigureInputPerGame>(system_, game_config.get(), this); 54 input_tab = std::make_unique<ConfigureInputPerGame>(system_, game_config.get(), this);
54 system_tab = std::make_unique<ConfigureSystem>(system_, this); 55 system_tab = std::make_unique<ConfigureSystem>(system_, this);
55 56
diff --git a/src/yuzu/configuration/configure_per_game.h b/src/yuzu/configuration/configure_per_game.h
index 4ecc43541..85752f1fa 100644
--- a/src/yuzu/configuration/configure_per_game.h
+++ b/src/yuzu/configuration/configure_per_game.h
@@ -75,8 +75,8 @@ private:
75 std::unique_ptr<ConfigureAudio> audio_tab; 75 std::unique_ptr<ConfigureAudio> audio_tab;
76 std::unique_ptr<ConfigureCpu> cpu_tab; 76 std::unique_ptr<ConfigureCpu> cpu_tab;
77 std::unique_ptr<ConfigureGeneral> general_tab; 77 std::unique_ptr<ConfigureGeneral> general_tab;
78 std::unique_ptr<ConfigureGraphics> graphics_tab;
79 std::unique_ptr<ConfigureGraphicsAdvanced> graphics_advanced_tab; 78 std::unique_ptr<ConfigureGraphicsAdvanced> graphics_advanced_tab;
79 std::unique_ptr<ConfigureGraphics> graphics_tab;
80 std::unique_ptr<ConfigureInputPerGame> input_tab; 80 std::unique_ptr<ConfigureInputPerGame> input_tab;
81 std::unique_ptr<ConfigureSystem> system_tab; 81 std::unique_ptr<ConfigureSystem> system_tab;
82}; 82};
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index d932e33a7..4489f43af 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -1164,7 +1164,8 @@ void GMainWindow::InitializeRecentFileMenuActions() {
1164 UpdateRecentFiles(); 1164 UpdateRecentFiles();
1165} 1165}
1166 1166
1167void GMainWindow::LinkActionShortcut(QAction* action, const QString& action_name) { 1167void GMainWindow::LinkActionShortcut(QAction* action, const QString& action_name,
1168 const bool tas_allowed) {
1168 static const QString main_window = QStringLiteral("Main Window"); 1169 static const QString main_window = QStringLiteral("Main Window");
1169 action->setShortcut(hotkey_registry.GetKeySequence(main_window, action_name)); 1170 action->setShortcut(hotkey_registry.GetKeySequence(main_window, action_name));
1170 action->setShortcutContext(hotkey_registry.GetShortcutContext(main_window, action_name)); 1171 action->setShortcutContext(hotkey_registry.GetShortcutContext(main_window, action_name));
@@ -1176,7 +1177,14 @@ void GMainWindow::LinkActionShortcut(QAction* action, const QString& action_name
1176 const auto* controller_hotkey = 1177 const auto* controller_hotkey =
1177 hotkey_registry.GetControllerHotkey(main_window, action_name, controller); 1178 hotkey_registry.GetControllerHotkey(main_window, action_name, controller);
1178 connect( 1179 connect(
1179 controller_hotkey, &ControllerShortcut::Activated, this, [action] { action->trigger(); }, 1180 controller_hotkey, &ControllerShortcut::Activated, this,
1181 [action, tas_allowed, this] {
1182 auto [tas_status, current_tas_frame, total_tas_frames] =
1183 input_subsystem->GetTas()->GetStatus();
1184 if (tas_allowed || tas_status == InputCommon::TasInput::TasState::Stopped) {
1185 action->trigger();
1186 }
1187 },
1180 Qt::QueuedConnection); 1188 Qt::QueuedConnection);
1181} 1189}
1182 1190
@@ -1193,9 +1201,9 @@ void GMainWindow::InitializeHotkeys() {
1193 LinkActionShortcut(ui->action_Show_Status_Bar, QStringLiteral("Toggle Status Bar")); 1201 LinkActionShortcut(ui->action_Show_Status_Bar, QStringLiteral("Toggle Status Bar"));
1194 LinkActionShortcut(ui->action_Fullscreen, QStringLiteral("Fullscreen")); 1202 LinkActionShortcut(ui->action_Fullscreen, QStringLiteral("Fullscreen"));
1195 LinkActionShortcut(ui->action_Capture_Screenshot, QStringLiteral("Capture Screenshot")); 1203 LinkActionShortcut(ui->action_Capture_Screenshot, QStringLiteral("Capture Screenshot"));
1196 LinkActionShortcut(ui->action_TAS_Start, QStringLiteral("TAS Start/Stop")); 1204 LinkActionShortcut(ui->action_TAS_Start, QStringLiteral("TAS Start/Stop"), true);
1197 LinkActionShortcut(ui->action_TAS_Record, QStringLiteral("TAS Record")); 1205 LinkActionShortcut(ui->action_TAS_Record, QStringLiteral("TAS Record"), true);
1198 LinkActionShortcut(ui->action_TAS_Reset, QStringLiteral("TAS Reset")); 1206 LinkActionShortcut(ui->action_TAS_Reset, QStringLiteral("TAS Reset"), true);
1199 1207
1200 static const QString main_window = QStringLiteral("Main Window"); 1208 static const QString main_window = QStringLiteral("Main Window");
1201 const auto connect_shortcut = [&]<typename Fn>(const QString& action_name, const Fn& function) { 1209 const auto connect_shortcut = [&]<typename Fn>(const QString& action_name, const Fn& function) {
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 7b23f2a59..17631a2d9 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -214,7 +214,8 @@ public slots:
214 214
215private: 215private:
216 /// Updates an action's shortcut and text to reflect an updated hotkey from the hotkey registry. 216 /// Updates an action's shortcut and text to reflect an updated hotkey from the hotkey registry.
217 void LinkActionShortcut(QAction* action, const QString& action_name); 217 void LinkActionShortcut(QAction* action, const QString& action_name,
218 const bool tas_allowed = false);
218 219
219 void RegisterMetaTypes(); 220 void RegisterMetaTypes();
220 221