diff options
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 | ||
| 981 | void Controller_NPad::VibrateControllers( | 981 | void 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 | ||
| 74 | DriverResult NfcProtocol::ScanAmiibo(std::vector<u8>& data) { | 74 | DriverResult 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 | ||
| 132 | DriverResult NfcProtocol::StartPolling(TagFoundData& data) { | 137 | DriverResult 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 | ||
| 34 | private: | 34 | private: |
| 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 | ||
| 132 | template <class P> | 132 | template <class P> |
| 133 | void BufferCache<P>::DownloadMemory(VAddr cpu_addr, u64 size) { | 133 | void 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 | ||
| 140 | template <class P> | 139 | template <class P> |
| 141 | void 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 | |||
| 156 | template <class P> | ||
| 157 | void BufferCache<P>::ClearDownload(IntervalType subtract_interval) { | 140 | void 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 | ||
| 1238 | template <class P> | 1216 | template <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 | ||
| 153 | private: | 153 | private: |
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 | ||
| 77 | ConfigureGraphics::ConfigureGraphics(const Core::System& system_, QWidget* parent) | 79 | ConfigureGraphics::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 | ||
| 39 | public: | 40 | public: |
| 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 | ||
| 20 | ConfigureGraphicsAdvanced::~ConfigureGraphicsAdvanced() = default; | 22 | ConfigureGraphicsAdvanced::~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 | ||
| 79 | void ConfigureGraphicsAdvanced::changeEvent(QEvent* event) { | 87 | void 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 | |||
| 149 | void 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 | |||
| 31 | private: | 33 | private: |
| 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. | ||
| 143 | Compute 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 | ||
| 180 | void ConfigureHotkeys::SetPollingResult(Core::HID::NpadButton button, const bool cancel) { | 183 | void 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 | ||
| 192 | QString ConfigureHotkeys::GetButtonName(Core::HID::NpadButton button) const { | 193 | QString 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 | ||
| 245 | std::pair<bool, QString> ConfigureHotkeys::IsUsedKey(QKeySequence key_sequence) const { | 260 | std::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 | ||
| 1167 | void GMainWindow::LinkActionShortcut(QAction* action, const QString& action_name) { | 1167 | void 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 | ||
| 215 | private: | 215 | private: |
| 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 | ||