diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 26087e40ae..bec5f37375 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -235,6 +235,7 @@ void RestoreGlobalState(bool is_powered_on) { values.bg_red.SetGlobal(true); values.bg_green.SetGlobal(true); values.bg_blue.SetGlobal(true); + values.enable_compute_pipelines.SetGlobal(true); // System values.language_index.SetGlobal(true); diff --git a/src/common/settings.h b/src/common/settings.h index 2a1bc52945..ff3c99281d 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -474,6 +474,7 @@ struct Values { SwitchableSetting use_fast_gpu_time{true, "use_fast_gpu_time"}; SwitchableSetting use_vulkan_driver_pipeline_cache{true, "use_vulkan_driver_pipeline_cache"}; + SwitchableSetting enable_compute_pipelines{false, "enable_compute_pipelines"}; SwitchableSetting bg_red{0, "bg_red"}; SwitchableSetting 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 ef4aec4ea8..28818c813d 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( } void Controller_NPad::VibrateControllers( - const std::vector& vibration_device_handles, - const std::vector& vibration_values) { + std::span vibration_device_handles, + std::span vibration_values) { if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) { return; } diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 9cfe298f14..776411261d 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -112,8 +112,8 @@ public: const Core::HID::VibrationValue& vibration_value); void VibrateControllers( - const std::vector& vibration_device_handles, - const std::vector& vibration_values); + std::span vibration_device_handles, + std::span vibration_values); Core::HID::VibrationValue GetLastVibration( 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 87e7b864a1..2bf1d8a273 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) { IPC::RequestParser rp{ctx}; const auto applet_resource_user_id{rp.Pop()}; - const auto handles = ctx.ReadBuffer(0); - const auto vibrations = ctx.ReadBuffer(1); + const auto handle_data = ctx.ReadBuffer(0); + const auto handle_count = ctx.GetReadBufferNumElements(0); + const auto vibration_data = ctx.ReadBuffer(1); + const auto vibration_count = ctx.GetReadBufferNumElements(1); - std::vector vibration_device_handles( - handles.size() / sizeof(Core::HID::VibrationDeviceHandle)); - std::vector vibration_values(vibrations.size() / - sizeof(Core::HID::VibrationValue)); - - std::memcpy(vibration_device_handles.data(), handles.data(), handles.size()); - std::memcpy(vibration_values.data(), vibrations.data(), vibrations.size()); + auto vibration_device_handles = + std::span(reinterpret_cast(handle_data.data()), + handle_count); + auto vibration_values = std::span( + reinterpret_cast(vibration_data.data()), vibration_count); applet_resource->GetController(HidController::NPad) .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 b03143e04c..1c8d294b0e 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 { InvalidHandle, NotSupported, Disabled, + Delayed, Unknown, }; diff --git a/src/input_common/helpers/joycon_protocol/nfc.cpp b/src/input_common/helpers/joycon_protocol/nfc.cpp index 77ea6d5cf2..14818ae332 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() { } DriverResult NfcProtocol::ScanAmiibo(std::vector& data) { + if (update_counter++ < AMIIBO_UPDATE_DELAY) { + return DriverResult::Delayed; + } + update_counter = 0; + LOG_DEBUG(Input, "Start NFC pooling Mode"); ScopedSetBlocking sb(this); DriverResult result{DriverResult::Success}; @@ -87,7 +92,7 @@ DriverResult NfcProtocol::ScanAmiibo(std::vector& data) { result = WaitUntilNfcIsReady(); } if (result == DriverResult::Success) { - result = StartPolling(tag_data); + result = StartPolling(tag_data, 7); } if (result == DriverResult::Success) { result = GetAmiiboData(data); @@ -129,9 +134,8 @@ DriverResult NfcProtocol::WaitUntilNfcIsReady() { return DriverResult::Success; } -DriverResult NfcProtocol::StartPolling(TagFoundData& data) { +DriverResult NfcProtocol::StartPolling(TagFoundData& data, std::size_t timeout_limit) { LOG_DEBUG(Input, "Start Polling for tag"); - constexpr std::size_t timeout_limit = 7; MCUCommandResponse output{}; std::size_t tries = 0; diff --git a/src/input_common/helpers/joycon_protocol/nfc.h b/src/input_common/helpers/joycon_protocol/nfc.h index 11e263e077..4cb992d1d3 100644 --- a/src/input_common/helpers/joycon_protocol/nfc.h +++ b/src/input_common/helpers/joycon_protocol/nfc.h @@ -32,6 +32,9 @@ public: bool IsEnabled() const; private: + // Number of times the function will be delayed until it outputs valid data + static constexpr std::size_t AMIIBO_UPDATE_DELAY = 15; + struct TagFoundData { u8 type; std::vector uuid; @@ -39,7 +42,7 @@ private: DriverResult WaitUntilNfcIsReady(); - DriverResult StartPolling(TagFoundData& data); + DriverResult StartPolling(TagFoundData& data, std::size_t timeout_limit = 1); DriverResult ReadTag(const TagFoundData& data); @@ -56,6 +59,7 @@ private: NFCReadBlockCommand GetReadBlockCommand(NFCPages pages) const; bool is_enabled{}; + std::size_t update_counter{}; }; } // 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 fee510f7b7..07c2b7b8ad 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) { if (ctx.profile.support_vertex_instance_id) { return ctx.OpBitcast(ctx.F32[1], ctx.OpLoad(ctx.U32[1], ctx.vertex_id)); } else { - const Id index{ctx.OpLoad(ctx.U32[1], ctx.vertex_index)}; - const Id base{ctx.OpLoad(ctx.U32[1], ctx.base_vertex)}; - return ctx.OpBitcast(ctx.F32[1], ctx.OpISub(ctx.U32[1], index, base)); + return ctx.OpBitcast(ctx.F32[1], ctx.OpLoad(ctx.U32[1], ctx.vertex_index)); } case IR::Attribute::BaseInstance: 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) { if (ctx.profile.support_vertex_instance_id) { return ctx.OpLoad(ctx.U32[1], ctx.vertex_id); } else { - const Id index{ctx.OpLoad(ctx.U32[1], ctx.vertex_index)}; - const Id base{ctx.OpLoad(ctx.U32[1], ctx.base_vertex)}; - return ctx.OpISub(ctx.U32[1], index, base); + return ctx.OpLoad(ctx.U32[1], ctx.vertex_index); } case IR::Attribute::BaseInstance: 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 639da1e9c1..eeb49444f2 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) { } IR::F32 value{v.ir.CompositeExtract(sample, element)}; if (element < 2) { - IR::U32 casted_value; - if (element == 0) { - casted_value = v.ir.ConvertFToU(32, value); - } else { - casted_value = v.ir.ConvertFToS(16, value); - } + IR::U32 casted_value = v.ir.ConvertFToU(32, value); v.X(dest_reg, v.ir.ShiftLeftLogical(casted_value, v.ir.Imm32(8))); } else { 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 fff57ffa9c..98756e4daf 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 BufferCache

::GetFlushArea(VA template void BufferCache

::DownloadMemory(VAddr cpu_addr, u64 size) { - WaitOnAsyncFlushes(cpu_addr, size); ForEachBufferInRange(cpu_addr, size, [&](BufferId, Buffer& buffer) { DownloadBufferMemory(buffer, cpu_addr, size); }); } -template -void BufferCache

::WaitOnAsyncFlushes(VAddr cpu_addr, u64 size) { - bool must_wait = false; - ForEachInOverlapCounter(async_downloads, cpu_addr, size, - [&](VAddr, VAddr, int) { must_wait = true; }); - bool must_release = false; - ForEachInRangeSet(pending_ranges, cpu_addr, size, [&](VAddr, VAddr) { must_release = true; }); - if (must_release) { - std::function tmp([]() {}); - rasterizer.SignalFence(std::move(tmp)); - } - if (must_wait || must_release) { - rasterizer.ReleaseFences(); - } -} - template void BufferCache

::ClearDownload(IntervalType subtract_interval) { RemoveEachInOverlapCounter(async_downloads, subtract_interval, -1024); uncommitted_ranges.subtract(subtract_interval); - pending_ranges.subtract(subtract_interval); for (auto& interval_set : committed_ranges) { interval_set.subtract(subtract_interval); } @@ -177,7 +159,6 @@ bool BufferCache

::DMACopy(GPUVAddr src_address, GPUVAddr dest_address, u64 am } const IntervalType subtract_interval{*cpu_dest_address, *cpu_dest_address + amount}; - WaitOnAsyncFlushes(*cpu_src_address, static_cast(amount)); ClearDownload(subtract_interval); BufferId buffer_a; @@ -205,7 +186,6 @@ bool BufferCache

::DMACopy(GPUVAddr src_address, GPUVAddr dest_address, u64 am const IntervalType add_interval{new_base_address, new_base_address + size}; tmp_intervals.push_back(add_interval); uncommitted_ranges.add(add_interval); - pending_ranges.add(add_interval); }; ForEachInRangeSet(common_ranges, *cpu_src_address, amount, mirror); // This subtraction in this order is important for overlapping copies. @@ -492,7 +472,6 @@ void BufferCache

::CommitAsyncFlushesHigh() { } MICROPROFILE_SCOPE(GPU_DownloadMemory); - pending_ranges.clear(); auto it = committed_ranges.begin(); while (it != committed_ranges.end()) { auto& current_intervals = *it; @@ -1232,7 +1211,6 @@ void BufferCache

::MarkWrittenBuffer(BufferId buffer_id, VAddr cpu_addr, u32 s const IntervalType base_interval{cpu_addr, cpu_addr + size}; common_ranges.add(base_interval); uncommitted_ranges.add(base_interval); - pending_ranges.add(base_interval); } template @@ -1677,14 +1655,15 @@ typename BufferCache

::Binding BufferCache

::StorageBufferBinding(GPUVAddr s const bool is_nvn_cbuf = cbuf_index == 0; // The NVN driver buffer (index 0) is known to pack the SSBO address followed by its size. if (is_nvn_cbuf) { - return gpu_memory->Read(ssbo_addr + 8); + const u32 ssbo_size = gpu_memory->Read(ssbo_addr + 8); + if (ssbo_size != 0) { + return ssbo_size; + } } // Other titles (notably Doom Eternal) may use STG/LDG on buffer addresses in custom defined // cbufs, which do not store the sizes adjacent to the addresses, so use the fully // mapped buffer size for now. const u32 memory_layout_size = static_cast(gpu_memory->GetMemoryLayoutSize(gpu_addr)); - LOG_INFO(HW_GPU, "Binding storage buffer for cbuf index {}, MemoryLayoutSize 0x{:X}", - cbuf_index, memory_layout_size); return memory_layout_size; }(); const std::optional 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 0445ec47f4..ac00d4d9d7 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: void RunGarbageCollector(); - void WaitOnAsyncFlushes(VAddr cpu_addr, u64 size); - void BindHostIndexBuffer(); void BindHostVertexBuffers(); @@ -547,7 +545,6 @@ private: IntervalSet uncommitted_ranges; IntervalSet common_ranges; IntervalSet cached_ranges; - IntervalSet pending_ranges; std::deque committed_ranges; // Async Buffers diff --git a/src/video_core/host1x/codecs/h264.cpp b/src/video_core/host1x/codecs/h264.cpp index e87bd65fa5..6ce179167c 100644 --- a/src/video_core/host1x/codecs/h264.cpp +++ b/src/video_core/host1x/codecs/h264.cpp @@ -111,7 +111,7 @@ const std::vector& H264::ComposeFrame(const Host1x::NvdecCommon::NvdecRegist writer.WriteUe(0); writer.WriteBit(context.h264_parameter_set.entropy_coding_mode_flag != 0); - writer.WriteBit(false); + writer.WriteBit(context.h264_parameter_set.pic_order_present_flag != 0); writer.WriteUe(0); writer.WriteUe(context.h264_parameter_set.num_refidx_l0_default_active); writer.WriteUe(context.h264_parameter_set.num_refidx_l1_default_active); @@ -129,7 +129,7 @@ const std::vector& H264::ComposeFrame(const Host1x::NvdecCommon::NvdecRegist writer.WriteBit(context.h264_parameter_set.redundant_pic_cnt_present_flag != 0); writer.WriteBit(context.h264_parameter_set.transform_8x8_mode_flag != 0); - writer.WriteBit(true); + writer.WriteBit(true); // pic_scaling_matrix_present_flag for (s32 index = 0; index < 6; index++) { 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 596996bec4..66dfe57334 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 PipelineCache::CreateComputePipeline( PipelineStatistics* statistics, bool build_in_parallel) try { // TODO: Remove this when Intel fixes their shader compiler. // https://github.com/IGCIT/Intel-GPU-Community-Issue-Tracker-IGCIT/issues/159 - if (device.GetDriverID() == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS) { + if (device.GetDriverID() == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS && + !Settings::values.enable_compute_pipelines.GetValue()) { LOG_ERROR(Render_Vulkan, "Skipping 0x{:016x}", key.Hash()); return nullptr; } diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 21c05d2091..c7389f140f 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -718,6 +718,7 @@ void Config::ReadRendererValues() { ReadGlobalSetting(Settings::values.use_asynchronous_shaders); ReadGlobalSetting(Settings::values.use_fast_gpu_time); ReadGlobalSetting(Settings::values.use_vulkan_driver_pipeline_cache); + ReadGlobalSetting(Settings::values.enable_compute_pipelines); ReadGlobalSetting(Settings::values.bg_red); ReadGlobalSetting(Settings::values.bg_green); ReadGlobalSetting(Settings::values.bg_blue); @@ -1370,6 +1371,7 @@ void Config::SaveRendererValues() { WriteGlobalSetting(Settings::values.use_asynchronous_shaders); WriteGlobalSetting(Settings::values.use_fast_gpu_time); WriteGlobalSetting(Settings::values.use_vulkan_driver_pipeline_cache); + WriteGlobalSetting(Settings::values.enable_compute_pipelines); WriteGlobalSetting(Settings::values.bg_red); WriteGlobalSetting(Settings::values.bg_green); WriteGlobalSetting(Settings::values.bg_blue); diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp index 2aaefcc058..8e76a819a9 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_, debug_tab_tab{std::make_unique(system_, this)}, filesystem_tab{std::make_unique(this)}, general_tab{std::make_unique(system_, this)}, - graphics_tab{std::make_unique(system_, this)}, graphics_advanced_tab{std::make_unique(system_, this)}, + graphics_tab{std::make_unique( + system_, [&]() { graphics_advanced_tab->ExposeComputeOption(); }, this)}, hotkeys_tab{std::make_unique(system_.HIDCore(), this)}, input_tab{std::make_unique(system_, this)}, network_tab{std::make_unique(system_, this)}, diff --git a/src/yuzu/configuration/configure_dialog.h b/src/yuzu/configuration/configure_dialog.h index 1f724834aa..a086a07c4e 100644 --- a/src/yuzu/configuration/configure_dialog.h +++ b/src/yuzu/configuration/configure_dialog.h @@ -72,8 +72,8 @@ private: std::unique_ptr debug_tab_tab; std::unique_ptr filesystem_tab; std::unique_ptr general_tab; - std::unique_ptr graphics_tab; std::unique_ptr graphics_advanced_tab; + std::unique_ptr graphics_tab; std::unique_ptr hotkeys_tab; std::unique_ptr input_tab; std::unique_ptr network_tab; diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index 76e5b7499e..f316b598cc 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp @@ -2,9 +2,11 @@ // SPDX-License-Identifier: GPL-2.0-or-later // Include this early to include Vulkan headers how we want to +#include "video_core/vulkan_common/vulkan_device.h" #include "video_core/vulkan_common/vulkan_wrapper.h" #include +#include #include #include #include @@ -74,8 +76,11 @@ static constexpr Settings::VSyncMode PresentModeToSetting(VkPresentModeKHR mode) } } -ConfigureGraphics::ConfigureGraphics(const Core::System& system_, QWidget* parent) - : QWidget(parent), ui{std::make_unique()}, system{system_} { +ConfigureGraphics::ConfigureGraphics(const Core::System& system_, + const std::function& expose_compute_option_, + QWidget* parent) + : QWidget(parent), ui{std::make_unique()}, + expose_compute_option{expose_compute_option_}, system{system_} { vulkan_device = Settings::values.vulkan_device.GetValue(); RetrieveVulkanDevices(); @@ -513,8 +518,7 @@ void ConfigureGraphics::RetrieveVulkanDevices() try { const Common::DynamicLibrary library = OpenLibrary(); const vk::Instance instance = CreateInstance(library, dld, VK_API_VERSION_1_1, wsi.type); const std::vector physical_devices = instance.EnumeratePhysicalDevices(); - vk::SurfaceKHR surface = //< needed to view present modes for a device - CreateSurface(instance, wsi); + vk::SurfaceKHR surface = CreateSurface(instance, wsi); vulkan_devices.clear(); vulkan_devices.reserve(physical_devices.size()); @@ -527,6 +531,17 @@ void ConfigureGraphics::RetrieveVulkanDevices() try { physical_device.GetSurfacePresentModesKHR(*surface); vulkan_devices.push_back(QString::fromStdString(name)); device_present_modes.push_back(present_modes); + + VkPhysicalDeviceDriverProperties driver_properties{}; + driver_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES; + driver_properties.pNext = nullptr; + VkPhysicalDeviceProperties2 properties{}; + properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR; + properties.pNext = &driver_properties; + dld.vkGetPhysicalDeviceProperties2(physical_device, &properties); + if (driver_properties.driverID == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS) { + expose_compute_option(); + } } } catch (const Vulkan::vk::Exception& exception) { 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 901f604a59..364b1cac2d 100644 --- a/src/yuzu/configuration/configure_graphics.h +++ b/src/yuzu/configuration/configure_graphics.h @@ -3,6 +3,7 @@ #pragma once +#include #include #include #include @@ -37,7 +38,9 @@ class ConfigureGraphics : public QWidget { Q_OBJECT public: - explicit ConfigureGraphics(const Core::System& system_, QWidget* parent = nullptr); + explicit ConfigureGraphics(const Core::System& system_, + const std::function& expose_compute_option_, + QWidget* parent = nullptr); ~ConfigureGraphics() override; void ApplyConfiguration(); @@ -81,6 +84,7 @@ private: // selection in the combobox u32 vulkan_device{}; Settings::ShaderBackend shader_backend{}; + const std::function& expose_compute_option; const Core::System& system; }; diff --git a/src/yuzu/configuration/configure_graphics_advanced.cpp b/src/yuzu/configuration/configure_graphics_advanced.cpp index 627ed8b177..1f3e489d05 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_ SetupPerGameUI(); SetConfiguration(); + + ui->enable_compute_pipelines_checkbox->setVisible(false); } ConfigureGraphicsAdvanced::~ConfigureGraphicsAdvanced() = default; @@ -27,6 +29,7 @@ void ConfigureGraphicsAdvanced::SetConfiguration() { ui->async_astc->setEnabled(runtime_lock); ui->use_asynchronous_shaders->setEnabled(runtime_lock); ui->anisotropic_filtering_combobox->setEnabled(runtime_lock); + ui->enable_compute_pipelines_checkbox->setEnabled(runtime_lock); ui->async_present->setChecked(Settings::values.async_presentation.GetValue()); ui->renderer_force_max_clock->setChecked(Settings::values.renderer_force_max_clock.GetValue()); @@ -36,6 +39,8 @@ void ConfigureGraphicsAdvanced::SetConfiguration() { ui->use_fast_gpu_time->setChecked(Settings::values.use_fast_gpu_time.GetValue()); ui->use_vulkan_driver_pipeline_cache->setChecked( Settings::values.use_vulkan_driver_pipeline_cache.GetValue()); + ui->enable_compute_pipelines_checkbox->setChecked( + Settings::values.enable_compute_pipelines.GetValue()); if (Settings::IsConfiguringGlobal()) { ui->gpu_accuracy->setCurrentIndex( @@ -74,6 +79,9 @@ void ConfigureGraphicsAdvanced::ApplyConfiguration() { ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vulkan_driver_pipeline_cache, ui->use_vulkan_driver_pipeline_cache, use_vulkan_driver_pipeline_cache); + ConfigurationShared::ApplyPerGameSetting(&Settings::values.enable_compute_pipelines, + ui->enable_compute_pipelines_checkbox, + enable_compute_pipelines); } void ConfigureGraphicsAdvanced::changeEvent(QEvent* event) { @@ -104,6 +112,8 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() { Settings::values.use_vulkan_driver_pipeline_cache.UsingGlobal()); ui->anisotropic_filtering_combobox->setEnabled( Settings::values.max_anisotropy.UsingGlobal()); + ui->enable_compute_pipelines_checkbox->setEnabled( + Settings::values.enable_compute_pipelines.UsingGlobal()); return; } @@ -125,6 +135,9 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() { ConfigurationShared::SetColoredTristate(ui->use_vulkan_driver_pipeline_cache, Settings::values.use_vulkan_driver_pipeline_cache, use_vulkan_driver_pipeline_cache); + ConfigurationShared::SetColoredTristate(ui->enable_compute_pipelines_checkbox, + Settings::values.enable_compute_pipelines, + enable_compute_pipelines); ConfigurationShared::SetColoredComboBox( ui->gpu_accuracy, ui->label_gpu_accuracy, static_cast(Settings::values.gpu_accuracy.GetValue(true))); @@ -132,3 +145,7 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() { ui->anisotropic_filtering_combobox, ui->af_label, static_cast(Settings::values.max_anisotropy.GetValue(true))); } + +void ConfigureGraphicsAdvanced::ExposeComputeOption() { + ui->enable_compute_pipelines_checkbox->setVisible(true); +} diff --git a/src/yuzu/configuration/configure_graphics_advanced.h b/src/yuzu/configuration/configure_graphics_advanced.h index ae3c109460..1c7b636b96 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.h +++ b/src/yuzu/configuration/configure_graphics_advanced.h @@ -28,6 +28,8 @@ public: void ApplyConfiguration(); void SetConfiguration(); + void ExposeComputeOption(); + private: void changeEvent(QEvent* event) override; void RetranslateUI(); @@ -44,6 +46,7 @@ private: ConfigurationShared::CheckState use_asynchronous_shaders; ConfigurationShared::CheckState use_fast_gpu_time; ConfigurationShared::CheckState use_vulkan_driver_pipeline_cache; + ConfigurationShared::CheckState enable_compute_pipelines; const Core::System& system; }; diff --git a/src/yuzu/configuration/configure_graphics_advanced.ui b/src/yuzu/configuration/configure_graphics_advanced.ui index 9d8cbea090..9ef7c8e8fb 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.ui +++ b/src/yuzu/configuration/configure_graphics_advanced.ui @@ -136,6 +136,17 @@ + + + + Enable compute pipelines, required by some games. This setting only exists for Intel proprietary drivers, and may crash if enabled. +Compute pipelines are always enabled on all other drivers. + + + Enable Compute Pipelines (Intel Vulkan only) + + + diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp index 7e757eafd9..7ac1625869 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 audio_tab = std::make_unique(system_, this); cpu_tab = std::make_unique(system_, this); general_tab = std::make_unique(system_, this); - graphics_tab = std::make_unique(system_, this); graphics_advanced_tab = std::make_unique(system_, this); + graphics_tab = std::make_unique( + system_, [&]() { graphics_advanced_tab->ExposeComputeOption(); }, this); input_tab = std::make_unique(system_, game_config.get(), this); system_tab = std::make_unique(system_, this); diff --git a/src/yuzu/configuration/configure_per_game.h b/src/yuzu/configuration/configure_per_game.h index 4ecc435417..85752f1fa7 100644 --- a/src/yuzu/configuration/configure_per_game.h +++ b/src/yuzu/configuration/configure_per_game.h @@ -75,8 +75,8 @@ private: std::unique_ptr audio_tab; std::unique_ptr cpu_tab; std::unique_ptr general_tab; - std::unique_ptr graphics_tab; std::unique_ptr graphics_advanced_tab; + std::unique_ptr graphics_tab; std::unique_ptr input_tab; std::unique_ptr system_tab; };