summaryrefslogtreecommitdiffstats
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) {
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 5f4caaab9..36ffcd693 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -472,6 +472,7 @@ struct Values {
SwitchableSetting<bool> use_fast_gpu_time{true, "use_fast_gpu_time"};
SwitchableSetting<bool> use_vulkan_driver_pipeline_cache{true,
"use_vulkan_driver_pipeline_cache"};
+ SwitchableSetting<bool> enable_compute_pipelines{false, "enable_compute_pipelines"};
SwitchableSetting<u8> bg_red{0, "bg_red"};
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(
}
void Controller_NPad::VibrateControllers(
- const std::vector<Core::HID::VibrationDeviceHandle>& vibration_device_handles,
- const std::vector<Core::HID::VibrationValue>& vibration_values) {
+ std::span<const Core::HID::VibrationDeviceHandle> vibration_device_handles,
+ std::span<const Core::HID::VibrationValue> 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 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:
const Core::HID::VibrationValue& vibration_value);
void VibrateControllers(
- const std::vector<Core::HID::VibrationDeviceHandle>& vibration_device_handles,
- const std::vector<Core::HID::VibrationValue>& vibration_values);
+ std::span<const Core::HID::VibrationDeviceHandle> vibration_device_handles,
+ std::span<const Core::HID::VibrationValue> 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 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) {
IPC::RequestParser rp{ctx};
const auto applet_resource_user_id{rp.Pop<u64>()};
- const auto handles = ctx.ReadBuffer(0);
- const auto vibrations = ctx.ReadBuffer(1);
-
- std::vector<Core::HID::VibrationDeviceHandle> vibration_device_handles(
- handles.size() / sizeof(Core::HID::VibrationDeviceHandle));
- std::vector<Core::HID::VibrationValue> 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());
+ const auto handle_data = ctx.ReadBuffer(0);
+ const auto handle_count = ctx.GetReadBufferNumElements<Core::HID::VibrationDeviceHandle>(0);
+ const auto vibration_data = ctx.ReadBuffer(1);
+ const auto vibration_count = ctx.GetReadBufferNumElements<Core::HID::VibrationValue>(1);
+
+ auto vibration_device_handles =
+ std::span(reinterpret_cast<const Core::HID::VibrationDeviceHandle*>(handle_data.data()),
+ handle_count);
+ auto vibration_values = std::span(
+ reinterpret_cast<const Core::HID::VibrationValue*>(vibration_data.data()), vibration_count);
applet_resource->GetController<Controller_NPad>(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 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 {
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 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() {
}
DriverResult NfcProtocol::ScanAmiibo(std::vector<u8>& 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<u8>& 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 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:
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<u8> 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 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) {
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 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) {
}
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 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
template <class P>
void BufferCache<P>::DownloadMemory(VAddr cpu_addr, u64 size) {
- WaitOnAsyncFlushes(cpu_addr, size);
ForEachBufferInRange(cpu_addr, size, [&](BufferId, Buffer& buffer) {
DownloadBufferMemory(buffer, cpu_addr, size);
});
}
template <class P>
-void BufferCache<P>::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<void()> tmp([]() {});
- rasterizer.SignalFence(std::move(tmp));
- }
- if (must_wait || must_release) {
- rasterizer.ReleaseFences();
- }
-}
-
-template <class P>
void BufferCache<P>::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<P>::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<u32>(amount));
ClearDownload(subtract_interval);
BufferId buffer_a;
@@ -205,7 +186,6 @@ bool BufferCache<P>::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<P>::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<P>::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 <class P>
@@ -1677,14 +1655,15 @@ typename BufferCache<P>::Binding BufferCache<P>::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<u32>(ssbo_addr + 8);
+ const u32 ssbo_size = gpu_memory->Read<u32>(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<u32>(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<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:
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<IntervalSet> committed_ranges;
// 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
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<u8>& 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 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(
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/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) {
const u32 color_attachment = regs.clear_surface.RT;
if (use_color && framebuffer->HasAspectColorBit(color_attachment)) {
- VkClearValue clear_value;
- bool is_integer = false;
- bool is_signed = false;
- size_t int_size = 8;
- for (std::size_t i = 0; i < Tegra::Engines::Maxwell3D::Regs::NumRenderTargets; ++i) {
- const auto& this_rt = regs.rt[i];
- if (this_rt.Address() == 0) {
- continue;
- }
- if (this_rt.format == Tegra::RenderTargetFormat::NONE) {
- continue;
- }
- const auto format =
- VideoCore::Surface::PixelFormatFromRenderTargetFormat(this_rt.format);
- is_integer = IsPixelFormatInteger(format);
- is_signed = IsPixelFormatSignedInteger(format);
- int_size = PixelComponentSizeBitsInteger(format);
- break;
- }
+ const auto format =
+ VideoCore::Surface::PixelFormatFromRenderTargetFormat(regs.rt[color_attachment].format);
+ bool is_integer = IsPixelFormatInteger(format);
+ bool is_signed = IsPixelFormatSignedInteger(format);
+ size_t int_size = PixelComponentSizeBitsInteger(format);
+ VkClearValue clear_value{};
if (!is_integer) {
std::memcpy(clear_value.color.float32, regs.clear_color.data(),
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() {
device_access_memory += mem_properties.memoryHeaps[element].size;
}
if (!is_integrated) {
+ const u64 reserve_memory = std::min<u64>(device_access_memory / 8, 1_GiB);
+ device_access_memory -= reserve_memory;
return;
}
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:
/// Returns whether this allocation is compatible with the arguments.
[[nodiscard]] bool IsCompatible(VkMemoryPropertyFlags flags, u32 type_mask) const {
- return (flags & property_flags) == property_flags && (type_mask & shifted_memory_type) != 0;
+ return (flags & property_flags) == flags && (type_mask & shifted_memory_type) != 0;
}
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() {
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);
@@ -1366,6 +1367,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 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_,
debug_tab_tab{std::make_unique<ConfigureDebugTab>(system_, this)},
filesystem_tab{std::make_unique<ConfigureFilesystem>(this)},
general_tab{std::make_unique<ConfigureGeneral>(system_, this)},
- graphics_tab{std::make_unique<ConfigureGraphics>(system_, this)},
graphics_advanced_tab{std::make_unique<ConfigureGraphicsAdvanced>(system_, this)},
+ graphics_tab{std::make_unique<ConfigureGraphics>(
+ system_, [&]() { graphics_advanced_tab->ExposeComputeOption(); }, this)},
hotkeys_tab{std::make_unique<ConfigureHotkeys>(system_.HIDCore(), this)},
input_tab{std::make_unique<ConfigureInput>(system_, this)},
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:
std::unique_ptr<ConfigureDebugTab> debug_tab_tab;
std::unique_ptr<ConfigureFilesystem> filesystem_tab;
std::unique_ptr<ConfigureGeneral> general_tab;
- std::unique_ptr<ConfigureGraphics> graphics_tab;
std::unique_ptr<ConfigureGraphicsAdvanced> graphics_advanced_tab;
+ std::unique_ptr<ConfigureGraphics> graphics_tab;
std::unique_ptr<ConfigureHotkeys> hotkeys_tab;
std::unique_ptr<ConfigureInput> input_tab;
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 @@
// 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 <algorithm>
+#include <functional>
#include <iosfwd>
#include <iterator>
#include <string>
@@ -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<Ui::ConfigureGraphics>()}, system{system_} {
+ConfigureGraphics::ConfigureGraphics(const Core::System& system_,
+ const std::function<void()>& expose_compute_option_,
+ QWidget* parent)
+ : QWidget(parent), ui{std::make_unique<Ui::ConfigureGraphics>()},
+ 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<VkPhysicalDevice> 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 901f604a5..364b1cac2 100644
--- a/src/yuzu/configuration/configure_graphics.h
+++ b/src/yuzu/configuration/configure_graphics.h
@@ -3,6 +3,7 @@
#pragma once
+#include <functional>
#include <memory>
#include <vector>
#include <QColor>
@@ -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<void()>& 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<void()>& 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 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_
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<int>(Settings::values.gpu_accuracy.GetValue(true)));
@@ -132,3 +145,7 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() {
ui->anisotropic_filtering_combobox, ui->af_label,
static_cast<int>(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 ae3c10946..1c7b636b9 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 9d8cbea09..9ef7c8e8f 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.ui
+++ b/src/yuzu/configuration/configure_graphics_advanced.ui
@@ -137,6 +137,17 @@
</widget>
</item>
<item>
+ <widget class="QCheckBox" name="enable_compute_pipelines_checkbox">
+ <property name="toolTip">
+ <string>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.</string>
+ </property>
+ <property name="text">
+ <string>Enable Compute Pipelines (Intel Vulkan only)</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<widget class="QWidget" name="af_layout" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_1">
<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
connect(poll_timer.get(), &QTimer::timeout, [this] {
const auto buttons = controller->GetNpadButtons();
- if (buttons.raw != Core::HID::NpadButton::None) {
+ const auto home_pressed = controller->GetHomeButtons().home != 0;
+ const auto capture_pressed = controller->GetCaptureButtons().capture != 0;
+ if (home_pressed || capture_pressed) {
SetPollingResult(buttons.raw, false);
return;
}
@@ -154,8 +156,10 @@ void ConfigureHotkeys::ConfigureController(QModelIndex index) {
model->setData(index, previous_key);
return;
}
-
- const QString button_string = tr("Home+%1").arg(GetButtonName(button));
+ const auto home_pressed = this->controller->GetHomeButtons().home != 0;
+ const auto capture_pressed = this->controller->GetCaptureButtons().capture != 0;
+ const QString button_string =
+ GetButtonCombinationName(button, home_pressed, capture_pressed);
const auto [key_sequence_used, used_action] = IsUsedControllerKey(button_string);
@@ -174,72 +178,83 @@ void ConfigureHotkeys::ConfigureController(QModelIndex index) {
poll_timer->start(200); // Check for new inputs every 200ms
// We need to disable configuration to be able to read npad buttons
controller->DisableConfiguration();
- controller->DisableSystemButtons();
}
void ConfigureHotkeys::SetPollingResult(Core::HID::NpadButton button, const bool cancel) {
timeout_timer->stop();
poll_timer->stop();
+ (*input_setter)(button, cancel);
// Re-Enable configuration
controller->EnableConfiguration();
- controller->EnableSystemButtons();
-
- (*input_setter)(button, cancel);
input_setter = std::nullopt;
}
-QString ConfigureHotkeys::GetButtonName(Core::HID::NpadButton button) const {
+QString ConfigureHotkeys::GetButtonCombinationName(Core::HID::NpadButton button,
+ const bool home = false,
+ const bool capture = false) const {
Core::HID::NpadButtonState state{button};
+ QString button_combination;
+ if (home) {
+ button_combination.append(QStringLiteral("Home+"));
+ }
+ if (capture) {
+ button_combination.append(QStringLiteral("Screenshot+"));
+ }
if (state.a) {
- return QStringLiteral("A");
+ button_combination.append(QStringLiteral("A+"));
}
if (state.b) {
- return QStringLiteral("B");
+ button_combination.append(QStringLiteral("B+"));
}
if (state.x) {
- return QStringLiteral("X");
+ button_combination.append(QStringLiteral("X+"));
}
if (state.y) {
- return QStringLiteral("Y");
+ button_combination.append(QStringLiteral("Y+"));
}
if (state.l || state.right_sl || state.left_sl) {
- return QStringLiteral("L");
+ button_combination.append(QStringLiteral("L+"));
}
if (state.r || state.right_sr || state.left_sr) {
- return QStringLiteral("R");
+ button_combination.append(QStringLiteral("R+"));
}
if (state.zl) {
- return QStringLiteral("ZL");
+ button_combination.append(QStringLiteral("ZL+"));
}
if (state.zr) {
- return QStringLiteral("ZR");
+ button_combination.append(QStringLiteral("ZR+"));
}
if (state.left) {
- return QStringLiteral("Dpad_Left");
+ button_combination.append(QStringLiteral("Dpad_Left+"));
}
if (state.right) {
- return QStringLiteral("Dpad_Right");
+ button_combination.append(QStringLiteral("Dpad_Right+"));
}
if (state.up) {
- return QStringLiteral("Dpad_Up");
+ button_combination.append(QStringLiteral("Dpad_Up+"));
}
if (state.down) {
- return QStringLiteral("Dpad_Down");
+ button_combination.append(QStringLiteral("Dpad_Down+"));
}
if (state.stick_l) {
- return QStringLiteral("Left_Stick");
+ button_combination.append(QStringLiteral("Left_Stick+"));
}
if (state.stick_r) {
- return QStringLiteral("Right_Stick");
+ button_combination.append(QStringLiteral("Right_Stick+"));
}
if (state.minus) {
- return QStringLiteral("Minus");
+ button_combination.append(QStringLiteral("Minus+"));
}
if (state.plus) {
- return QStringLiteral("Plus");
+ button_combination.append(QStringLiteral("Plus+"));
+ }
+ if (button_combination.isEmpty()) {
+ return tr("Invalid");
+ } else {
+ button_combination.chop(1);
+ return button_combination;
}
- return tr("Invalid");
}
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:
QStandardItemModel* model;
void SetPollingResult(Core::HID::NpadButton button, bool cancel);
- QString GetButtonName(Core::HID::NpadButton button) const;
+ QString GetButtonCombinationName(Core::HID::NpadButton button, bool home, bool capture) const;
Core::HID::EmulatedController* controller;
std::unique_ptr<QTimer> timeout_timer;
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
audio_tab = std::make_unique<ConfigureAudio>(system_, this);
cpu_tab = std::make_unique<ConfigureCpu>(system_, this);
general_tab = std::make_unique<ConfigureGeneral>(system_, this);
- graphics_tab = std::make_unique<ConfigureGraphics>(system_, this);
graphics_advanced_tab = std::make_unique<ConfigureGraphicsAdvanced>(system_, this);
+ graphics_tab = std::make_unique<ConfigureGraphics>(
+ system_, [&]() { graphics_advanced_tab->ExposeComputeOption(); }, this);
input_tab = std::make_unique<ConfigureInputPerGame>(system_, game_config.get(), this);
system_tab = std::make_unique<ConfigureSystem>(system_, this);
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:
std::unique_ptr<ConfigureAudio> audio_tab;
std::unique_ptr<ConfigureCpu> cpu_tab;
std::unique_ptr<ConfigureGeneral> general_tab;
- std::unique_ptr<ConfigureGraphics> graphics_tab;
std::unique_ptr<ConfigureGraphicsAdvanced> graphics_advanced_tab;
+ std::unique_ptr<ConfigureGraphics> graphics_tab;
std::unique_ptr<ConfigureInputPerGame> input_tab;
std::unique_ptr<ConfigureSystem> system_tab;
};
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() {
UpdateRecentFiles();
}
-void GMainWindow::LinkActionShortcut(QAction* action, const QString& action_name) {
+void GMainWindow::LinkActionShortcut(QAction* action, const QString& action_name,
+ const bool tas_allowed) {
static const QString main_window = QStringLiteral("Main Window");
action->setShortcut(hotkey_registry.GetKeySequence(main_window, action_name));
action->setShortcutContext(hotkey_registry.GetShortcutContext(main_window, action_name));
@@ -1176,7 +1177,14 @@ void GMainWindow::LinkActionShortcut(QAction* action, const QString& action_name
const auto* controller_hotkey =
hotkey_registry.GetControllerHotkey(main_window, action_name, controller);
connect(
- controller_hotkey, &ControllerShortcut::Activated, this, [action] { action->trigger(); },
+ controller_hotkey, &ControllerShortcut::Activated, this,
+ [action, tas_allowed, this] {
+ auto [tas_status, current_tas_frame, total_tas_frames] =
+ input_subsystem->GetTas()->GetStatus();
+ if (tas_allowed || tas_status == InputCommon::TasInput::TasState::Stopped) {
+ action->trigger();
+ }
+ },
Qt::QueuedConnection);
}
@@ -1193,9 +1201,9 @@ void GMainWindow::InitializeHotkeys() {
LinkActionShortcut(ui->action_Show_Status_Bar, QStringLiteral("Toggle Status Bar"));
LinkActionShortcut(ui->action_Fullscreen, QStringLiteral("Fullscreen"));
LinkActionShortcut(ui->action_Capture_Screenshot, QStringLiteral("Capture Screenshot"));
- LinkActionShortcut(ui->action_TAS_Start, QStringLiteral("TAS Start/Stop"));
- LinkActionShortcut(ui->action_TAS_Record, QStringLiteral("TAS Record"));
- LinkActionShortcut(ui->action_TAS_Reset, QStringLiteral("TAS Reset"));
+ LinkActionShortcut(ui->action_TAS_Start, QStringLiteral("TAS Start/Stop"), true);
+ LinkActionShortcut(ui->action_TAS_Record, QStringLiteral("TAS Record"), true);
+ LinkActionShortcut(ui->action_TAS_Reset, QStringLiteral("TAS Reset"), true);
static const QString main_window = QStringLiteral("Main Window");
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:
private:
/// Updates an action's shortcut and text to reflect an updated hotkey from the hotkey registry.
- void LinkActionShortcut(QAction* action, const QString& action_name);
+ void LinkActionShortcut(QAction* action, const QString& action_name,
+ const bool tas_allowed = false);
void RegisterMetaTypes();