summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--src/common/scratch_buffer.h9
-rw-r--r--src/common/settings.cpp1
-rw-r--r--src/common/settings.h3
-rw-r--r--src/core/file_sys/savedata_factory.cpp4
-rw-r--r--src/core/hle/service/am/am.cpp33
-rw-r--r--src/core/hle/service/am/am.h1
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.cpp17
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.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/core/hle/service/nfc/common/device.cpp35
-rw-r--r--src/core/hle/service/nfc/common/device.h2
-rw-r--r--src/core/hle/service/nvnflinger/buffer_queue_producer.cpp5
-rw-r--r--src/core/hle/service/nvnflinger/parcel.h72
-rw-r--r--src/core/hle/service/time/clock_types.h12
-rw-r--r--src/core/hle/service/time/time_sharedmemory.cpp19
-rw-r--r--src/core/hle/service/time/time_sharedmemory.h5
-rw-r--r--src/core/hle/service/vi/vi.cpp12
-rw-r--r--src/input_common/drivers/sdl_driver.cpp35
-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.h37
-rw-r--r--src/video_core/buffer_cache/buffer_cache_base.h3
-rw-r--r--src/video_core/engines/sw_blitter/blitter.cpp25
-rw-r--r--src/video_core/host1x/codecs/h264.cpp4
-rw-r--r--src/video_core/renderer_vulkan/pipeline_helper.h6
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.cpp10
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.h9
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pass.cpp39
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pass.h14
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pipeline.cpp12
-rw-r--r--src/video_core/renderer_vulkan/vk_compute_pipeline.h4
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp10
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.h5
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.cpp11
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.h5
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp18
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.h3
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp5
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.h6
-rw-r--r--src/video_core/renderer_vulkan/vk_update_descriptor.h6
-rw-r--r--src/video_core/texture_cache/texture_cache.h2
-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.cpp4
-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_input_advanced.cpp2
-rw-r--r--src/yuzu/configuration/configure_input_advanced.ui22
-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
-rw-r--r--src/yuzu_cmd/config.cpp1
66 files changed, 490 insertions, 263 deletions
diff --git a/README.md b/README.md
index 7f0461e5e..fd705ad70 100644
--- a/README.md
+++ b/README.md
@@ -83,5 +83,3 @@ If you wish to support us a different way, please join our [Discord](https://dis
## License
yuzu is licensed under the GPLv3 (or any later version). Refer to the [LICENSE.txt](https://github.com/yuzu-emu/yuzu/blob/master/LICENSE.txt) file.
-
-The [Skyline-Emulator Team](https://github.com/skyline-emu/skyline) may choose to use the code from these contributors under the GPL-3.0-or-later OR MPL-2.0: [FernandoS27](https://github.com/FernandoS27), [lioncash](https://github.com/lioncash), [bunnei](https://github.com/bunnei), [ReinUsesLisp](https://github.com/ReinUsesLisp), [Morph1984](https://github.com/Morph1984), [ogniK5377](https://github.com/ogniK5377), [german77](https://github.com/german77), [ameerj](https://github.com/ameerj), [Kelebek1](https://github.com/Kelebek1) and [lat9nq](https://github.com/lat9nq)
diff --git a/src/common/scratch_buffer.h b/src/common/scratch_buffer.h
index 26d4e76dc..a69a5a7af 100644
--- a/src/common/scratch_buffer.h
+++ b/src/common/scratch_buffer.h
@@ -23,7 +23,10 @@ public:
buffer{Common::make_unique_for_overwrite<T[]>(initial_capacity)} {}
~ScratchBuffer() = default;
+ ScratchBuffer(const ScratchBuffer&) = delete;
+ ScratchBuffer& operator=(const ScratchBuffer&) = delete;
ScratchBuffer(ScratchBuffer&&) = default;
+ ScratchBuffer& operator=(ScratchBuffer&&) = default;
/// This will only grow the buffer's capacity if size is greater than the current capacity.
/// The previously held data will remain intact.
@@ -87,6 +90,12 @@ public:
return buffer_capacity;
}
+ void swap(ScratchBuffer& other) noexcept {
+ std::swap(last_requested_size, other.last_requested_size);
+ std::swap(buffer_capacity, other.buffer_capacity);
+ std::swap(buffer, other.buffer);
+ }
+
private:
size_t last_requested_size{};
size_t buffer_capacity{};
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 f4eb4e3cd..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"};
@@ -535,6 +536,8 @@ struct Values {
Setting<bool> enable_ir_sensor{false, "enable_ir_sensor"};
Setting<std::string> ir_sensor_device{"auto", "ir_sensor_device"};
+ Setting<bool> random_amiibo_id{false, "random_amiibo_id"};
+
// Data Storage
Setting<bool> use_virtual_sd{true, "use_virtual_sd"};
Setting<bool> gamecard_inserted{false, "gamecard_inserted"};
diff --git a/src/core/file_sys/savedata_factory.cpp b/src/core/file_sys/savedata_factory.cpp
index 769065b6f..70b36f170 100644
--- a/src/core/file_sys/savedata_factory.cpp
+++ b/src/core/file_sys/savedata_factory.cpp
@@ -82,9 +82,9 @@ std::string GetFutureSaveDataPath(SaveDataSpaceId space_id, SaveDataType type, u
// Only detect account/device saves from the future location.
switch (type) {
case SaveDataType::SaveData:
- return fmt::format("{}/account/{}/{:016X}/1", space_id_path, uuid.RawString(), title_id);
+ return fmt::format("{}/account/{}/{:016X}/0", space_id_path, uuid.RawString(), title_id);
case SaveDataType::DeviceSaveData:
- return fmt::format("{}/device/{:016X}/1", space_id_path, title_id);
+ return fmt::format("{}/device/{:016X}/0", space_id_path, title_id);
default:
return "";
}
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index e59de844c..a2375508a 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -13,6 +13,7 @@
#include "core/file_sys/savedata_factory.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_transfer_memory.h"
+#include "core/hle/result.h"
#include "core/hle/service/acc/profile_manager.h"
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/applet_ae.h"
@@ -1335,7 +1336,7 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_)
{24, nullptr, "GetLaunchStorageInfoForDebug"},
{25, &IApplicationFunctions::ExtendSaveData, "ExtendSaveData"},
{26, &IApplicationFunctions::GetSaveDataSize, "GetSaveDataSize"},
- {27, nullptr, "CreateCacheStorage"},
+ {27, &IApplicationFunctions::CreateCacheStorage, "CreateCacheStorage"},
{28, nullptr, "GetSaveDataSizeMax"},
{29, nullptr, "GetCacheStorageMax"},
{30, &IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed, "BeginBlockingHomeButtonShortAndLongPressed"},
@@ -1738,6 +1739,36 @@ void IApplicationFunctions::GetSaveDataSize(HLERequestContext& ctx) {
rb.Push(size.journal);
}
+void IApplicationFunctions::CreateCacheStorage(HLERequestContext& ctx) {
+ struct InputParameters {
+ u16 index;
+ s64 size;
+ s64 journal_size;
+ };
+ static_assert(sizeof(InputParameters) == 24);
+
+ struct OutputParameters {
+ u32 storage_target;
+ u64 required_size;
+ };
+ static_assert(sizeof(OutputParameters) == 16);
+
+ IPC::RequestParser rp{ctx};
+ const auto params = rp.PopRaw<InputParameters>();
+
+ LOG_WARNING(Service_AM, "(STUBBED) called with index={}, size={:#x}, journal_size={:#x}",
+ params.index, params.size, params.journal_size);
+
+ const OutputParameters resp{
+ .storage_target = 1,
+ .required_size = 0,
+ };
+
+ IPC::ResponseBuilder rb{ctx, 6};
+ rb.Push(ResultSuccess);
+ rb.PushRaw(resp);
+}
+
void IApplicationFunctions::QueryApplicationPlayStatistics(HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index 0dbc6485e..d4fd163da 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -333,6 +333,7 @@ private:
void GetPseudoDeviceId(HLERequestContext& ctx);
void ExtendSaveData(HLERequestContext& ctx);
void GetSaveDataSize(HLERequestContext& ctx);
+ void CreateCacheStorage(HLERequestContext& ctx);
void BeginBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx);
void EndBlockingHomeButtonShortAndLongPressed(HLERequestContext& ctx);
void BeginBlockingHomeButton(HLERequestContext& ctx);
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp
index 9e559d97e..f73a864c3 100644
--- a/src/core/hle/service/filesystem/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp_srv.cpp
@@ -24,8 +24,10 @@
#include "core/file_sys/savedata_factory.h"
#include "core/file_sys/system_archive/system_archive.h"
#include "core/file_sys/vfs.h"
+#include "core/hle/result.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/filesystem/fsp_srv.h"
+#include "core/hle/service/hle_ipc.h"
#include "core/hle/service/ipc_helpers.h"
#include "core/reporter.h"
@@ -552,9 +554,9 @@ public:
// Write the data to memory
ctx.WriteBuffer(begin, range_size);
- IPC::ResponseBuilder rb{ctx, 3};
+ IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
- rb.Push<u32>(static_cast<u32>(actual_entries));
+ rb.Push<u64>(actual_entries);
}
private:
@@ -712,7 +714,7 @@ FSP_SRV::FSP_SRV(Core::System& system_)
{59, nullptr, "WriteSaveDataFileSystemExtraData"},
{60, nullptr, "OpenSaveDataInfoReader"},
{61, &FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId, "OpenSaveDataInfoReaderBySaveDataSpaceId"},
- {62, nullptr, "OpenCacheStorageList"},
+ {62, &FSP_SRV::OpenSaveDataInfoReaderOnlyCacheStorage, "OpenSaveDataInfoReaderOnlyCacheStorage"},
{64, nullptr, "OpenSaveDataInternalStorageFileSystem"},
{65, nullptr, "UpdateSaveDataMacForDebug"},
{66, nullptr, "WriteSaveDataFileSystemExtraData2"},
@@ -921,6 +923,15 @@ void FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId(HLERequestContext& ctx) {
std::make_shared<ISaveDataInfoReader>(system, space, fsc));
}
+void FSP_SRV::OpenSaveDataInfoReaderOnlyCacheStorage(HLERequestContext& ctx) {
+ LOG_WARNING(Service_FS, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(ResultSuccess);
+ rb.PushIpcInterface<ISaveDataInfoReader>(system, FileSys::SaveDataSpaceId::TemporaryStorage,
+ fsc);
+}
+
void FSP_SRV::WriteSaveDataFileSystemExtraDataBySaveDataAttribute(HLERequestContext& ctx) {
LOG_WARNING(Service_FS, "(STUBBED) called.");
diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp_srv.h
index 49f17c7c3..4f3c2f6de 100644
--- a/src/core/hle/service/filesystem/fsp_srv.h
+++ b/src/core/hle/service/filesystem/fsp_srv.h
@@ -42,6 +42,7 @@ private:
void OpenSaveDataFileSystem(HLERequestContext& ctx);
void OpenReadOnlySaveDataFileSystem(HLERequestContext& ctx);
void OpenSaveDataInfoReaderBySaveDataSpaceId(HLERequestContext& ctx);
+ void OpenSaveDataInfoReaderOnlyCacheStorage(HLERequestContext& ctx);
void WriteSaveDataFileSystemExtraDataBySaveDataAttribute(HLERequestContext& ctx);
void ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute(HLERequestContext& ctx);
void OpenDataStorageByCurrentProcess(HLERequestContext& ctx);
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/core/hle/service/nfc/common/device.cpp b/src/core/hle/service/nfc/common/device.cpp
index e5de65ce0..322bde2ed 100644
--- a/src/core/hle/service/nfc/common/device.cpp
+++ b/src/core/hle/service/nfc/common/device.cpp
@@ -48,9 +48,6 @@ NfcDevice::NfcDevice(Core::HID::NpadIdType npad_id_, Core::System& system_,
};
is_controller_set = true;
callback_key = npad_device->SetCallback(engine_callback);
-
- auto& standard_steady_clock{system.GetTimeManager().GetStandardSteadyClockCore()};
- current_posix_time = standard_steady_clock.GetCurrentTimePoint(system).time_point;
}
NfcDevice::~NfcDevice() {
@@ -227,11 +224,21 @@ Result NfcDevice::GetTagInfo(NFP::TagInfo& tag_info, bool is_mifare) const {
return ResultWrongDeviceState;
}
+ UniqueSerialNumber uuid = encrypted_tag_data.uuid.uid;
+
+ // Generate random UUID to bypass amiibo load limits
+ if (Settings::values.random_amiibo_id) {
+ Common::TinyMT rng{};
+ rng.Initialize(static_cast<u32>(GetCurrentPosixTime()));
+ rng.GenerateRandomBytes(uuid.data(), sizeof(UniqueSerialNumber));
+ uuid[3] = 0x88 ^ uuid[0] ^ uuid[1] ^ uuid[2];
+ }
+
if (is_mifare) {
tag_info = {
- .uuid = encrypted_tag_data.uuid.uid,
+ .uuid = uuid,
.uuid_extension = {},
- .uuid_length = static_cast<u8>(encrypted_tag_data.uuid.uid.size()),
+ .uuid_length = static_cast<u8>(uuid.size()),
.protocol = NfcProtocol::TypeA,
.tag_type = TagType::Type4,
};
@@ -240,9 +247,9 @@ Result NfcDevice::GetTagInfo(NFP::TagInfo& tag_info, bool is_mifare) const {
// Protocol and tag type may change here
tag_info = {
- .uuid = encrypted_tag_data.uuid.uid,
+ .uuid = uuid,
.uuid_extension = {},
- .uuid_length = static_cast<u8>(encrypted_tag_data.uuid.uid.size()),
+ .uuid_length = static_cast<u8>(uuid.size()),
.protocol = NfcProtocol::TypeA,
.tag_type = TagType::Type2,
};
@@ -406,7 +413,7 @@ Result NfcDevice::Flush() {
auto& settings = tag_data.settings;
- const auto& current_date = GetAmiiboDate(current_posix_time);
+ const auto& current_date = GetAmiiboDate(GetCurrentPosixTime());
if (settings.write_date.raw_date != current_date.raw_date) {
settings.write_date = current_date;
UpdateSettingsCrc();
@@ -525,6 +532,7 @@ Result NfcDevice::GetModelInfo(NFP::ModelInfo& model_info) const {
}
const auto& model_info_data = encrypted_tag_data.user_memory.model_info;
+
model_info = {
.character_id = model_info_data.character_id,
.character_variant = model_info_data.character_variant,
@@ -669,6 +677,7 @@ Result NfcDevice::DeleteRegisterInfo() {
}
Common::TinyMT rng{};
+ rng.Initialize(static_cast<u32>(GetCurrentPosixTime()));
rng.GenerateRandomBytes(&tag_data.owner_mii, sizeof(tag_data.owner_mii));
rng.GenerateRandomBytes(&tag_data.settings.amiibo_name, sizeof(tag_data.settings.amiibo_name));
rng.GenerateRandomBytes(&tag_data.unknown, sizeof(u8));
@@ -701,7 +710,7 @@ Result NfcDevice::SetRegisterInfoPrivate(const NFP::RegisterInfoPrivate& registe
auto& settings = tag_data.settings;
if (tag_data.settings.settings.amiibo_initialized == 0) {
- settings.init_date = GetAmiiboDate(current_posix_time);
+ settings.init_date = GetAmiiboDate(GetCurrentPosixTime());
settings.write_date.raw_date = 0;
}
@@ -868,6 +877,7 @@ Result NfcDevice::SetApplicationArea(std::span<const u8> data) {
}
Common::TinyMT rng{};
+ rng.Initialize(static_cast<u32>(GetCurrentPosixTime()));
std::memcpy(tag_data.application_area.data(), data.data(), data.size());
// Fill remaining data with random numbers
rng.GenerateRandomBytes(tag_data.application_area.data() + data.size(),
@@ -924,6 +934,7 @@ Result NfcDevice::RecreateApplicationArea(u32 access_id, std::span<const u8> dat
}
Common::TinyMT rng{};
+ rng.Initialize(static_cast<u32>(GetCurrentPosixTime()));
std::memcpy(tag_data.application_area.data(), data.data(), data.size());
// Fill remaining data with random numbers
rng.GenerateRandomBytes(tag_data.application_area.data() + data.size(),
@@ -973,6 +984,7 @@ Result NfcDevice::DeleteApplicationArea() {
}
Common::TinyMT rng{};
+ rng.Initialize(static_cast<u32>(GetCurrentPosixTime()));
rng.GenerateRandomBytes(tag_data.application_area.data(), sizeof(NFP::ApplicationArea));
rng.GenerateRandomBytes(&tag_data.application_id, sizeof(u64));
rng.GenerateRandomBytes(&tag_data.application_area_id, sizeof(u32));
@@ -1189,6 +1201,11 @@ NFP::AmiiboDate NfcDevice::GetAmiiboDate(s64 posix_time) const {
return amiibo_date;
}
+u64 NfcDevice::GetCurrentPosixTime() const {
+ auto& standard_steady_clock{system.GetTimeManager().GetStandardSteadyClockCore()};
+ return standard_steady_clock.GetCurrentTimePoint(system).time_point;
+}
+
u64 NfcDevice::RemoveVersionByte(u64 application_id) const {
return application_id & ~(0xfULL << NFP::application_id_version_offset);
}
diff --git a/src/core/hle/service/nfc/common/device.h b/src/core/hle/service/nfc/common/device.h
index 654eda98e..98e1945c1 100644
--- a/src/core/hle/service/nfc/common/device.h
+++ b/src/core/hle/service/nfc/common/device.h
@@ -105,6 +105,7 @@ private:
NFP::AmiiboName GetAmiiboName(const NFP::AmiiboSettings& settings) const;
void SetAmiiboName(NFP::AmiiboSettings& settings, const NFP::AmiiboName& amiibo_name);
NFP::AmiiboDate GetAmiiboDate(s64 posix_time) const;
+ u64 GetCurrentPosixTime() const;
u64 RemoveVersionByte(u64 application_id) const;
void UpdateSettingsCrc();
void UpdateRegisterInfoCrc();
@@ -127,7 +128,6 @@ private:
bool is_data_moddified{};
bool is_app_area_open{};
bool is_plain_amiibo{};
- s64 current_posix_time{};
NFP::MountTarget mount_target{NFP::MountTarget::None};
NFP::NTAG215File tag_data{};
diff --git a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp
index cd0a13094..b16f9933f 100644
--- a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp
+++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp
@@ -793,6 +793,7 @@ Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot,
std::scoped_lock lock{core->mutex};
slots[slot] = {};
+ slots[slot].fence = Fence::NoFence();
slots[slot].graphic_buffer = buffer;
slots[slot].frame_number = 0;
@@ -854,7 +855,7 @@ void BufferQueueProducer::Transact(HLERequestContext& ctx, TransactionId code, u
status = DequeueBuffer(&slot, &fence, is_async, width, height, pixel_format, usage);
parcel_out.Write(slot);
- parcel_out.WriteObject(&fence);
+ parcel_out.WriteFlattenedObject(&fence);
break;
}
case TransactionId::RequestBuffer: {
@@ -864,7 +865,7 @@ void BufferQueueProducer::Transact(HLERequestContext& ctx, TransactionId code, u
status = RequestBuffer(slot, &buf);
- parcel_out.WriteObject(buf);
+ parcel_out.WriteFlattenedObject(buf);
break;
}
case TransactionId::QueueBuffer: {
diff --git a/src/core/hle/service/nvnflinger/parcel.h b/src/core/hle/service/nvnflinger/parcel.h
index d1b6201e0..fb56d75d7 100644
--- a/src/core/hle/service/nvnflinger/parcel.h
+++ b/src/core/hle/service/nvnflinger/parcel.h
@@ -117,61 +117,67 @@ private:
class OutputParcel final {
public:
- static constexpr std::size_t DefaultBufferSize = 0x40;
-
- OutputParcel() : buffer(DefaultBufferSize) {}
-
- template <typename T>
- explicit OutputParcel(const T& out_data) : buffer(DefaultBufferSize) {
- Write(out_data);
- }
+ OutputParcel() = default;
template <typename T>
void Write(const T& val) {
- static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable.");
-
- if (buffer.size() < write_index + sizeof(T)) {
- buffer.resize(buffer.size() + sizeof(T) + DefaultBufferSize);
- }
-
- std::memcpy(buffer.data() + write_index, &val, sizeof(T));
- write_index += sizeof(T);
- write_index = Common::AlignUp(write_index, 4);
+ this->WriteImpl(val, m_data_buffer);
}
template <typename T>
- void WriteObject(const T* ptr) {
- static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable.");
-
+ void WriteFlattenedObject(const T* ptr) {
if (!ptr) {
- Write<u32>(0);
+ this->Write<u32>(0);
return;
}
- Write<u32>(1);
- Write<s64>(sizeof(T));
- Write(*ptr);
+ this->Write<u32>(1);
+ this->Write<s64>(sizeof(T));
+ this->Write(*ptr);
}
template <typename T>
- void WriteObject(const std::shared_ptr<T> ptr) {
- WriteObject(ptr.get());
+ void WriteFlattenedObject(const std::shared_ptr<T> ptr) {
+ this->WriteFlattenedObject(ptr.get());
+ }
+
+ template <typename T>
+ void WriteInterface(const T& val) {
+ this->WriteImpl(val, m_data_buffer);
+ this->WriteImpl(0U, m_object_buffer);
}
std::vector<u8> Serialize() const {
+ std::vector<u8> output_buffer(sizeof(ParcelHeader) + m_data_buffer.size() +
+ m_object_buffer.size());
+
ParcelHeader header{};
- header.data_size = static_cast<u32>(write_index - sizeof(ParcelHeader));
+ header.data_size = static_cast<u32>(m_data_buffer.size());
header.data_offset = sizeof(ParcelHeader);
- header.objects_size = 4;
- header.objects_offset = static_cast<u32>(sizeof(ParcelHeader) + header.data_size);
- std::memcpy(buffer.data(), &header, sizeof(ParcelHeader));
+ header.objects_size = static_cast<u32>(m_object_buffer.size());
+ header.objects_offset = header.data_offset + header.data_size;
+
+ std::memcpy(output_buffer.data(), &header, sizeof(header));
+ std::ranges::copy(m_data_buffer, output_buffer.data() + header.data_offset);
+ std::ranges::copy(m_object_buffer, output_buffer.data() + header.objects_offset);
+
+ return output_buffer;
+ }
+
+private:
+ template <typename T>
+ requires(std::is_trivially_copyable_v<T>)
+ void WriteImpl(const T& val, std::vector<u8>& buffer) {
+ const size_t aligned_size = Common::AlignUp(sizeof(T), 4);
+ const size_t old_size = buffer.size();
+ buffer.resize(old_size + aligned_size);
- return buffer;
+ std::memcpy(buffer.data() + old_size, &val, sizeof(T));
}
private:
- mutable std::vector<u8> buffer;
- std::size_t write_index = sizeof(ParcelHeader);
+ std::vector<u8> m_data_buffer;
+ std::vector<u8> m_object_buffer;
};
} // namespace Service::android
diff --git a/src/core/hle/service/time/clock_types.h b/src/core/hle/service/time/clock_types.h
index ed1eb5b2d..e6293ffb9 100644
--- a/src/core/hle/service/time/clock_types.h
+++ b/src/core/hle/service/time/clock_types.h
@@ -59,6 +59,18 @@ static_assert(sizeof(SystemClockContext) == 0x20, "SystemClockContext is incorre
static_assert(std::is_trivially_copyable_v<SystemClockContext>,
"SystemClockContext must be trivially copyable");
+struct ContinuousAdjustmentTimePoint {
+ s64 measurement_offset;
+ s64 diff_scale;
+ u32 shift_amount;
+ s64 lower;
+ s64 upper;
+ Common::UUID clock_source_id;
+};
+static_assert(sizeof(ContinuousAdjustmentTimePoint) == 0x38);
+static_assert(std::is_trivially_copyable_v<ContinuousAdjustmentTimePoint>,
+ "ContinuousAdjustmentTimePoint must be trivially copyable");
+
/// https://switchbrew.org/wiki/Glue_services#TimeSpanType
struct TimeSpanType {
s64 nanoseconds{};
diff --git a/src/core/hle/service/time/time_sharedmemory.cpp b/src/core/hle/service/time/time_sharedmemory.cpp
index ff53a7d6f..ce1c85bcc 100644
--- a/src/core/hle/service/time/time_sharedmemory.cpp
+++ b/src/core/hle/service/time/time_sharedmemory.cpp
@@ -30,6 +30,25 @@ void SharedMemory::SetupStandardSteadyClock(const Common::UUID& clock_source_id,
}
void SharedMemory::UpdateLocalSystemClockContext(const Clock::SystemClockContext& context) {
+ // lower and upper are related to the measurement point for the steady time point,
+ // and compare equal on boot
+ const s64 time_point_ns = context.steady_time_point.time_point * 1'000'000'000LL;
+
+ // This adjusts for some sort of time skew
+ // Both 0 on boot
+ const s64 diff_scale = 0;
+ const u32 shift_amount = 0;
+
+ const Clock::ContinuousAdjustmentTimePoint adjustment{
+ .measurement_offset = system.CoreTiming().GetGlobalTimeNs().count(),
+ .diff_scale = diff_scale,
+ .shift_amount = shift_amount,
+ .lower = time_point_ns,
+ .upper = time_point_ns,
+ .clock_source_id = context.steady_time_point.clock_source_id,
+ };
+
+ StoreToLockFreeAtomicType(&GetFormat()->continuous_adjustment_timepoint, adjustment);
StoreToLockFreeAtomicType(&GetFormat()->standard_local_system_clock_context, context);
}
diff --git a/src/core/hle/service/time/time_sharedmemory.h b/src/core/hle/service/time/time_sharedmemory.h
index 044a4d24e..c89be9765 100644
--- a/src/core/hle/service/time/time_sharedmemory.h
+++ b/src/core/hle/service/time/time_sharedmemory.h
@@ -65,14 +65,15 @@ public:
LockFreeAtomicType<Clock::SystemClockContext> standard_local_system_clock_context;
LockFreeAtomicType<Clock::SystemClockContext> standard_network_system_clock_context;
LockFreeAtomicType<bool> is_standard_user_system_clock_automatic_correction_enabled;
- u32 format_version;
+ LockFreeAtomicType<Clock::ContinuousAdjustmentTimePoint> continuous_adjustment_timepoint;
};
static_assert(offsetof(Format, standard_steady_clock_timepoint) == 0x0);
static_assert(offsetof(Format, standard_local_system_clock_context) == 0x38);
static_assert(offsetof(Format, standard_network_system_clock_context) == 0x80);
static_assert(offsetof(Format, is_standard_user_system_clock_automatic_correction_enabled) ==
0xc8);
- static_assert(sizeof(Format) == 0xd8, "Format is an invalid size");
+ static_assert(offsetof(Format, continuous_adjustment_timepoint) == 0xd0);
+ static_assert(sizeof(Format) == 0x148, "Format is an invalid size");
void SetupStandardSteadyClock(const Common::UUID& clock_source_id,
Clock::TimeSpanType current_time_point);
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index 68eab5133..1b193f00c 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -64,8 +64,8 @@ public:
private:
const u32 magic = 2;
const u32 process_id = 1;
- const u32 id;
- INSERT_PADDING_WORDS(3);
+ const u64 id;
+ INSERT_PADDING_WORDS(2);
std::array<u8, 8> dispdrv = {'d', 'i', 's', 'p', 'd', 'r', 'v', '\0'};
INSERT_PADDING_WORDS(2);
};
@@ -608,7 +608,9 @@ private:
return;
}
- const auto parcel = android::OutputParcel{NativeWindow{*buffer_queue_id}};
+ android::OutputParcel parcel;
+ parcel.WriteInterface(NativeWindow{*buffer_queue_id});
+
const auto buffer_size = ctx.WriteBuffer(parcel.Serialize());
IPC::ResponseBuilder rb{ctx, 4};
@@ -654,7 +656,9 @@ private:
return;
}
- const auto parcel = android::OutputParcel{NativeWindow{*buffer_queue_id}};
+ android::OutputParcel parcel;
+ parcel.WriteInterface(NativeWindow{*buffer_queue_id});
+
const auto buffer_size = ctx.WriteBuffer(parcel.Serialize());
IPC::ResponseBuilder rb{ctx, 6};
diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp
index 7f9e8dbb9..9a0439bb5 100644
--- a/src/input_common/drivers/sdl_driver.cpp
+++ b/src/input_common/drivers/sdl_driver.cpp
@@ -109,14 +109,37 @@ public:
}
bool RumblePlay(const Common::Input::VibrationStatus vibration) {
- constexpr u32 rumble_max_duration_ms = 1000;
+ constexpr u32 rumble_max_duration_ms = 2000;
+ constexpr f32 low_start_sensitivity_limit = 140.0;
+ constexpr f32 low_width_sensitivity_limit = 400.0;
+ constexpr f32 high_start_sensitivity_limit = 200.0;
+ constexpr f32 high_width_sensitivity_limit = 700.0;
+ // Try to provide some feeling of the frequency by reducing the amplitude depending on it.
+ f32 low_frequency_scale = 1.0;
+ if (vibration.low_frequency > low_start_sensitivity_limit) {
+ low_frequency_scale =
+ std::max(1.0f - (vibration.low_frequency - low_start_sensitivity_limit) /
+ low_width_sensitivity_limit,
+ 0.3f);
+ }
+ f32 low_amplitude = vibration.low_amplitude * low_frequency_scale;
+
+ f32 high_frequency_scale = 1.0;
+ if (vibration.high_frequency > high_start_sensitivity_limit) {
+ high_frequency_scale =
+ std::max(1.0f - (vibration.high_frequency - high_start_sensitivity_limit) /
+ high_width_sensitivity_limit,
+ 0.3f);
+ }
+ f32 high_amplitude = vibration.high_amplitude * high_frequency_scale;
+
if (sdl_controller) {
- return SDL_GameControllerRumble(
- sdl_controller.get(), static_cast<u16>(vibration.low_amplitude),
- static_cast<u16>(vibration.high_amplitude), rumble_max_duration_ms) != -1;
+ return SDL_GameControllerRumble(sdl_controller.get(), static_cast<u16>(low_amplitude),
+ static_cast<u16>(high_amplitude),
+ rumble_max_duration_ms) != -1;
} else if (sdl_joystick) {
- return SDL_JoystickRumble(sdl_joystick.get(), static_cast<u16>(vibration.low_amplitude),
- static_cast<u16>(vibration.high_amplitude),
+ return SDL_JoystickRumble(sdl_joystick.get(), static_cast<u16>(low_amplitude),
+ static_cast<u16>(high_amplitude),
rumble_max_duration_ms) != -1;
}
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 6624919a4..98756e4da 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -96,12 +96,12 @@ void BufferCache<P>::TickFrame() {
template <class P>
void BufferCache<P>::WriteMemory(VAddr cpu_addr, u64 size) {
- memory_tracker.MarkRegionAsCpuModified(cpu_addr, size);
if (memory_tracker.IsRegionGpuModified(cpu_addr, size)) {
const IntervalType subtract_interval{cpu_addr, cpu_addr + size};
ClearDownload(subtract_interval);
common_ranges.subtract(subtract_interval);
}
+ memory_tracker.MarkRegionAsCpuModified(cpu_addr, size);
}
template <class P>
@@ -122,41 +122,24 @@ std::optional<VideoCore::RasterizerDownloadArea> BufferCache<P>::GetFlushArea(VA
area->preemtive = true;
return area;
};
+ area->preemtive =
+ !IsRegionGpuModified(cpu_addr_start_aligned, cpu_addr_end_aligned - cpu_addr_start_aligned);
memory_tracker.MarkRegionAsPreflushable(cpu_addr_start_aligned,
cpu_addr_end_aligned - cpu_addr_start_aligned);
- area->preemtive = !IsRegionGpuModified(cpu_addr, size);
return area;
}
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);
}
@@ -176,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;
@@ -204,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.
@@ -491,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;
@@ -1223,16 +1203,14 @@ void BufferCache<P>::UpdateComputeTextureBuffers() {
template <class P>
void BufferCache<P>::MarkWrittenBuffer(BufferId buffer_id, VAddr cpu_addr, u32 size) {
- memory_tracker.MarkRegionAsGpuModified(cpu_addr, size);
-
if (memory_tracker.IsRegionCpuModified(cpu_addr, size)) {
SynchronizeBuffer(slot_buffers[buffer_id], cpu_addr, size);
}
+ memory_tracker.MarkRegionAsGpuModified(cpu_addr, size);
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/engines/sw_blitter/blitter.cpp b/src/video_core/engines/sw_blitter/blitter.cpp
index 3c9f38559..ff88cd03d 100644
--- a/src/video_core/engines/sw_blitter/blitter.cpp
+++ b/src/video_core/engines/sw_blitter/blitter.cpp
@@ -5,6 +5,7 @@
#include <cmath>
#include <vector>
+#include "common/scratch_buffer.h"
#include "video_core/engines/sw_blitter/blitter.h"
#include "video_core/engines/sw_blitter/converter.h"
#include "video_core/memory_manager.h"
@@ -112,11 +113,11 @@ void Bilinear(std::span<const f32> input, std::span<f32> output, size_t src_widt
} // namespace
struct SoftwareBlitEngine::BlitEngineImpl {
- std::vector<u8> tmp_buffer;
- std::vector<u8> src_buffer;
- std::vector<u8> dst_buffer;
- std::vector<f32> intermediate_src;
- std::vector<f32> intermediate_dst;
+ Common::ScratchBuffer<u8> tmp_buffer;
+ Common::ScratchBuffer<u8> src_buffer;
+ Common::ScratchBuffer<u8> dst_buffer;
+ Common::ScratchBuffer<f32> intermediate_src;
+ Common::ScratchBuffer<f32> intermediate_dst;
ConverterFactory converter_factory;
};
@@ -158,14 +159,14 @@ bool SoftwareBlitEngine::Blit(Fermi2D::Surface& src, Fermi2D::Surface& dst,
const auto src_bytes_per_pixel = BytesPerBlock(PixelFormatFromRenderTargetFormat(src.format));
const auto dst_bytes_per_pixel = BytesPerBlock(PixelFormatFromRenderTargetFormat(dst.format));
const size_t src_size = get_surface_size(src, src_bytes_per_pixel);
- impl->tmp_buffer.resize(src_size);
+ impl->tmp_buffer.resize_destructive(src_size);
memory_manager.ReadBlock(src.Address(), impl->tmp_buffer.data(), src_size);
const size_t src_copy_size = src_extent_x * src_extent_y * src_bytes_per_pixel;
const size_t dst_copy_size = dst_extent_x * dst_extent_y * dst_bytes_per_pixel;
- impl->src_buffer.resize(src_copy_size);
+ impl->src_buffer.resize_destructive(src_copy_size);
const bool no_passthrough =
src.format != dst.format || src_extent_x != dst_extent_x || src_extent_y != dst_extent_y;
@@ -177,8 +178,10 @@ bool SoftwareBlitEngine::Blit(Fermi2D::Surface& src, Fermi2D::Surface& dst,
const auto convertion_phase_ir = [&]() {
auto* input_converter = impl->converter_factory.GetFormatConverter(src.format);
- impl->intermediate_src.resize((src_copy_size / src_bytes_per_pixel) * ir_components);
- impl->intermediate_dst.resize((dst_copy_size / dst_bytes_per_pixel) * ir_components);
+ impl->intermediate_src.resize_destructive((src_copy_size / src_bytes_per_pixel) *
+ ir_components);
+ impl->intermediate_dst.resize_destructive((dst_copy_size / dst_bytes_per_pixel) *
+ ir_components);
input_converter->ConvertTo(impl->src_buffer, impl->intermediate_src);
if (config.filter != Fermi2D::Filter::Bilinear) {
@@ -195,7 +198,7 @@ bool SoftwareBlitEngine::Blit(Fermi2D::Surface& src, Fermi2D::Surface& dst,
// Do actual Blit
- impl->dst_buffer.resize(dst_copy_size);
+ impl->dst_buffer.resize_destructive(dst_copy_size);
if (src.linear == Fermi2D::MemoryLayout::BlockLinear) {
UnswizzleSubrect(impl->src_buffer, impl->tmp_buffer, src_bytes_per_pixel, src.width,
src.height, src.depth, config.src_x0, config.src_y0, src_extent_x,
@@ -218,7 +221,7 @@ bool SoftwareBlitEngine::Blit(Fermi2D::Surface& src, Fermi2D::Surface& dst,
}
const size_t dst_size = get_surface_size(dst, dst_bytes_per_pixel);
- impl->tmp_buffer.resize(dst_size);
+ impl->tmp_buffer.resize_destructive(dst_size);
memory_manager.ReadBlock(dst.Address(), impl->tmp_buffer.data(), dst_size);
if (dst.linear == Fermi2D::MemoryLayout::BlockLinear) {
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/pipeline_helper.h b/src/video_core/renderer_vulkan/pipeline_helper.h
index 28b893e25..983e1c2e1 100644
--- a/src/video_core/renderer_vulkan/pipeline_helper.h
+++ b/src/video_core/renderer_vulkan/pipeline_helper.h
@@ -176,7 +176,7 @@ public:
};
inline void PushImageDescriptors(TextureCache& texture_cache,
- UpdateDescriptorQueue& update_descriptor_queue,
+ GuestDescriptorQueue& guest_descriptor_queue,
const Shader::Info& info, RescalingPushConstant& rescaling,
const VkSampler*& samplers,
const VideoCommon::ImageViewInOut*& views) {
@@ -190,7 +190,7 @@ inline void PushImageDescriptors(TextureCache& texture_cache,
const VkSampler sampler{*(samplers++)};
ImageView& image_view{texture_cache.GetImageView(image_view_id)};
const VkImageView vk_image_view{image_view.Handle(desc.type)};
- update_descriptor_queue.AddSampledImage(vk_image_view, sampler);
+ guest_descriptor_queue.AddSampledImage(vk_image_view, sampler);
rescaling.PushTexture(texture_cache.IsRescaling(image_view));
}
}
@@ -201,7 +201,7 @@ inline void PushImageDescriptors(TextureCache& texture_cache,
texture_cache.MarkModification(image_view.image_id);
}
const VkImageView vk_image_view{image_view.StorageView(desc.type, desc.format)};
- update_descriptor_queue.AddImage(vk_image_view);
+ guest_descriptor_queue.AddImage(vk_image_view);
rescaling.PushImage(texture_cache.IsRescaling(image_view));
}
}
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
index 510602e8e..9627eb129 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
@@ -298,12 +298,14 @@ private:
BufferCacheRuntime::BufferCacheRuntime(const Device& device_, MemoryAllocator& memory_allocator_,
Scheduler& scheduler_, StagingBufferPool& staging_pool_,
- UpdateDescriptorQueue& update_descriptor_queue_,
+ GuestDescriptorQueue& guest_descriptor_queue_,
+ ComputePassDescriptorQueue& compute_pass_descriptor_queue,
DescriptorPool& descriptor_pool)
: device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_},
- staging_pool{staging_pool_}, update_descriptor_queue{update_descriptor_queue_},
- uint8_pass(device, scheduler, descriptor_pool, staging_pool, update_descriptor_queue),
- quad_index_pass(device, scheduler, descriptor_pool, staging_pool, update_descriptor_queue) {
+ staging_pool{staging_pool_}, guest_descriptor_queue{guest_descriptor_queue_},
+ uint8_pass(device, scheduler, descriptor_pool, staging_pool, compute_pass_descriptor_queue),
+ quad_index_pass(device, scheduler, descriptor_pool, staging_pool,
+ compute_pass_descriptor_queue) {
quad_array_index_buffer = std::make_shared<QuadArrayIndexBuffer>(device_, memory_allocator_,
scheduler_, staging_pool_);
quad_strip_index_buffer = std::make_shared<QuadStripIndexBuffer>(device_, memory_allocator_,
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h
index 879f1ed94..5e9602905 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.h
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h
@@ -63,7 +63,8 @@ class BufferCacheRuntime {
public:
explicit BufferCacheRuntime(const Device& device_, MemoryAllocator& memory_manager_,
Scheduler& scheduler_, StagingBufferPool& staging_pool_,
- UpdateDescriptorQueue& update_descriptor_queue_,
+ GuestDescriptorQueue& guest_descriptor_queue,
+ ComputePassDescriptorQueue& compute_pass_descriptor_queue,
DescriptorPool& descriptor_pool);
void Finish();
@@ -116,12 +117,12 @@ public:
void BindTextureBuffer(Buffer& buffer, u32 offset, u32 size,
VideoCore::Surface::PixelFormat format) {
- update_descriptor_queue.AddTexelBuffer(buffer.View(offset, size, format));
+ guest_descriptor_queue.AddTexelBuffer(buffer.View(offset, size, format));
}
private:
void BindBuffer(VkBuffer buffer, u32 offset, u32 size) {
- update_descriptor_queue.AddBuffer(buffer, offset, size);
+ guest_descriptor_queue.AddBuffer(buffer, offset, size);
}
void ReserveNullBuffer();
@@ -130,7 +131,7 @@ private:
MemoryAllocator& memory_allocator;
Scheduler& scheduler;
StagingBufferPool& staging_pool;
- UpdateDescriptorQueue& update_descriptor_queue;
+ GuestDescriptorQueue& guest_descriptor_queue;
std::shared_ptr<QuadArrayIndexBuffer> quad_array_index_buffer;
std::shared_ptr<QuadStripIndexBuffer> quad_strip_index_buffer;
diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.cpp b/src/video_core/renderer_vulkan/vk_compute_pass.cpp
index 1a316b6eb..3bc8553e1 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pass.cpp
+++ b/src/video_core/renderer_vulkan/vk_compute_pass.cpp
@@ -200,12 +200,12 @@ ComputePass::~ComputePass() = default;
Uint8Pass::Uint8Pass(const Device& device_, Scheduler& scheduler_, DescriptorPool& descriptor_pool,
StagingBufferPool& staging_buffer_pool_,
- UpdateDescriptorQueue& update_descriptor_queue_)
+ ComputePassDescriptorQueue& compute_pass_descriptor_queue_)
: ComputePass(device_, descriptor_pool, INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS,
INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE, INPUT_OUTPUT_BANK_INFO, {},
VULKAN_UINT8_COMP_SPV),
scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_},
- update_descriptor_queue{update_descriptor_queue_} {}
+ compute_pass_descriptor_queue{compute_pass_descriptor_queue_} {}
Uint8Pass::~Uint8Pass() = default;
@@ -214,10 +214,10 @@ std::pair<VkBuffer, VkDeviceSize> Uint8Pass::Assemble(u32 num_vertices, VkBuffer
const u32 staging_size = static_cast<u32>(num_vertices * sizeof(u16));
const auto staging = staging_buffer_pool.Request(staging_size, MemoryUsage::DeviceLocal);
- update_descriptor_queue.Acquire();
- update_descriptor_queue.AddBuffer(src_buffer, src_offset, num_vertices);
- update_descriptor_queue.AddBuffer(staging.buffer, staging.offset, staging_size);
- const void* const descriptor_data{update_descriptor_queue.UpdateData()};
+ compute_pass_descriptor_queue.Acquire();
+ compute_pass_descriptor_queue.AddBuffer(src_buffer, src_offset, num_vertices);
+ compute_pass_descriptor_queue.AddBuffer(staging.buffer, staging.offset, staging_size);
+ const void* const descriptor_data{compute_pass_descriptor_queue.UpdateData()};
scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([this, descriptor_data, num_vertices](vk::CommandBuffer cmdbuf) {
@@ -242,12 +242,12 @@ std::pair<VkBuffer, VkDeviceSize> Uint8Pass::Assemble(u32 num_vertices, VkBuffer
QuadIndexedPass::QuadIndexedPass(const Device& device_, Scheduler& scheduler_,
DescriptorPool& descriptor_pool_,
StagingBufferPool& staging_buffer_pool_,
- UpdateDescriptorQueue& update_descriptor_queue_)
+ ComputePassDescriptorQueue& compute_pass_descriptor_queue_)
: ComputePass(device_, descriptor_pool_, INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS,
INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE, INPUT_OUTPUT_BANK_INFO,
COMPUTE_PUSH_CONSTANT_RANGE<sizeof(u32) * 3>, VULKAN_QUAD_INDEXED_COMP_SPV),
scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_},
- update_descriptor_queue{update_descriptor_queue_} {}
+ compute_pass_descriptor_queue{compute_pass_descriptor_queue_} {}
QuadIndexedPass::~QuadIndexedPass() = default;
@@ -272,10 +272,10 @@ std::pair<VkBuffer, VkDeviceSize> QuadIndexedPass::Assemble(
const std::size_t staging_size = num_tri_vertices * sizeof(u32);
const auto staging = staging_buffer_pool.Request(staging_size, MemoryUsage::DeviceLocal);
- update_descriptor_queue.Acquire();
- update_descriptor_queue.AddBuffer(src_buffer, src_offset, input_size);
- update_descriptor_queue.AddBuffer(staging.buffer, staging.offset, staging_size);
- const void* const descriptor_data{update_descriptor_queue.UpdateData()};
+ compute_pass_descriptor_queue.Acquire();
+ compute_pass_descriptor_queue.AddBuffer(src_buffer, src_offset, input_size);
+ compute_pass_descriptor_queue.AddBuffer(staging.buffer, staging.offset, staging_size);
+ const void* const descriptor_data{compute_pass_descriptor_queue.UpdateData()};
scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([this, descriptor_data, num_tri_vertices, base_vertex, index_shift,
@@ -304,13 +304,14 @@ std::pair<VkBuffer, VkDeviceSize> QuadIndexedPass::Assemble(
ASTCDecoderPass::ASTCDecoderPass(const Device& device_, Scheduler& scheduler_,
DescriptorPool& descriptor_pool_,
StagingBufferPool& staging_buffer_pool_,
- UpdateDescriptorQueue& update_descriptor_queue_,
+ ComputePassDescriptorQueue& compute_pass_descriptor_queue_,
MemoryAllocator& memory_allocator_)
: ComputePass(device_, descriptor_pool_, ASTC_DESCRIPTOR_SET_BINDINGS,
ASTC_PASS_DESCRIPTOR_UPDATE_TEMPLATE_ENTRY, ASTC_BANK_INFO,
COMPUTE_PUSH_CONSTANT_RANGE<sizeof(AstcPushConstants)>, ASTC_DECODER_COMP_SPV),
scheduler{scheduler_}, staging_buffer_pool{staging_buffer_pool_},
- update_descriptor_queue{update_descriptor_queue_}, memory_allocator{memory_allocator_} {}
+ compute_pass_descriptor_queue{compute_pass_descriptor_queue_}, memory_allocator{
+ memory_allocator_} {}
ASTCDecoderPass::~ASTCDecoderPass() = default;
@@ -358,11 +359,11 @@ void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map,
const u32 num_dispatches_y = Common::DivCeil(swizzle.num_tiles.height, 8U);
const u32 num_dispatches_z = image.info.resources.layers;
- update_descriptor_queue.Acquire();
- update_descriptor_queue.AddBuffer(map.buffer, input_offset,
- image.guest_size_bytes - swizzle.buffer_offset);
- update_descriptor_queue.AddImage(image.StorageImageView(swizzle.level));
- const void* const descriptor_data{update_descriptor_queue.UpdateData()};
+ compute_pass_descriptor_queue.Acquire();
+ compute_pass_descriptor_queue.AddBuffer(map.buffer, input_offset,
+ image.guest_size_bytes - swizzle.buffer_offset);
+ compute_pass_descriptor_queue.AddImage(image.StorageImageView(swizzle.level));
+ const void* const descriptor_data{compute_pass_descriptor_queue.UpdateData()};
// To unswizzle the ASTC data
const auto params = MakeBlockLinearSwizzle2DParams(swizzle, image.info);
diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.h b/src/video_core/renderer_vulkan/vk_compute_pass.h
index c4c8fa081..dd3927376 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pass.h
+++ b/src/video_core/renderer_vulkan/vk_compute_pass.h
@@ -9,6 +9,7 @@
#include "common/common_types.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/renderer_vulkan/vk_descriptor_pool.h"
+#include "video_core/renderer_vulkan/vk_update_descriptor.h"
#include "video_core/vulkan_common/vulkan_memory_allocator.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
@@ -21,7 +22,6 @@ namespace Vulkan {
class Device;
class StagingBufferPool;
class Scheduler;
-class UpdateDescriptorQueue;
class Image;
struct StagingBufferRef;
@@ -50,7 +50,7 @@ class Uint8Pass final : public ComputePass {
public:
explicit Uint8Pass(const Device& device_, Scheduler& scheduler_,
DescriptorPool& descriptor_pool_, StagingBufferPool& staging_buffer_pool_,
- UpdateDescriptorQueue& update_descriptor_queue_);
+ ComputePassDescriptorQueue& compute_pass_descriptor_queue_);
~Uint8Pass();
/// Assemble uint8 indices into an uint16 index buffer
@@ -61,7 +61,7 @@ public:
private:
Scheduler& scheduler;
StagingBufferPool& staging_buffer_pool;
- UpdateDescriptorQueue& update_descriptor_queue;
+ ComputePassDescriptorQueue& compute_pass_descriptor_queue;
};
class QuadIndexedPass final : public ComputePass {
@@ -69,7 +69,7 @@ public:
explicit QuadIndexedPass(const Device& device_, Scheduler& scheduler_,
DescriptorPool& descriptor_pool_,
StagingBufferPool& staging_buffer_pool_,
- UpdateDescriptorQueue& update_descriptor_queue_);
+ ComputePassDescriptorQueue& compute_pass_descriptor_queue_);
~QuadIndexedPass();
std::pair<VkBuffer, VkDeviceSize> Assemble(
@@ -79,7 +79,7 @@ public:
private:
Scheduler& scheduler;
StagingBufferPool& staging_buffer_pool;
- UpdateDescriptorQueue& update_descriptor_queue;
+ ComputePassDescriptorQueue& compute_pass_descriptor_queue;
};
class ASTCDecoderPass final : public ComputePass {
@@ -87,7 +87,7 @@ public:
explicit ASTCDecoderPass(const Device& device_, Scheduler& scheduler_,
DescriptorPool& descriptor_pool_,
StagingBufferPool& staging_buffer_pool_,
- UpdateDescriptorQueue& update_descriptor_queue_,
+ ComputePassDescriptorQueue& compute_pass_descriptor_queue_,
MemoryAllocator& memory_allocator_);
~ASTCDecoderPass();
@@ -97,7 +97,7 @@ public:
private:
Scheduler& scheduler;
StagingBufferPool& staging_buffer_pool;
- UpdateDescriptorQueue& update_descriptor_queue;
+ ComputePassDescriptorQueue& compute_pass_descriptor_queue;
MemoryAllocator& memory_allocator;
};
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
index 2a0f0dbf0..733e70d9d 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
@@ -26,13 +26,13 @@ using Tegra::Texture::TexturePair;
ComputePipeline::ComputePipeline(const Device& device_, vk::PipelineCache& pipeline_cache_,
DescriptorPool& descriptor_pool,
- UpdateDescriptorQueue& update_descriptor_queue_,
+ GuestDescriptorQueue& guest_descriptor_queue_,
Common::ThreadWorker* thread_worker,
PipelineStatistics* pipeline_statistics,
VideoCore::ShaderNotify* shader_notify, const Shader::Info& info_,
vk::ShaderModule spv_module_)
- : device{device_}, pipeline_cache(pipeline_cache_),
- update_descriptor_queue{update_descriptor_queue_}, info{info_},
+ : device{device_},
+ pipeline_cache(pipeline_cache_), guest_descriptor_queue{guest_descriptor_queue_}, info{info_},
spv_module(std::move(spv_module_)) {
if (shader_notify) {
shader_notify->MarkShaderBuilding();
@@ -99,7 +99,7 @@ ComputePipeline::ComputePipeline(const Device& device_, vk::PipelineCache& pipel
void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
Tegra::MemoryManager& gpu_memory, Scheduler& scheduler,
BufferCache& buffer_cache, TextureCache& texture_cache) {
- update_descriptor_queue.Acquire();
+ guest_descriptor_queue.Acquire();
buffer_cache.SetComputeUniformBufferState(info.constant_buffer_mask, &uniform_buffer_sizes);
buffer_cache.UnbindComputeStorageBuffers();
@@ -194,7 +194,7 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
RescalingPushConstant rescaling;
const VkSampler* samplers_it{samplers.data()};
const VideoCommon::ImageViewInOut* views_it{views.data()};
- PushImageDescriptors(texture_cache, update_descriptor_queue, info, rescaling, samplers_it,
+ PushImageDescriptors(texture_cache, guest_descriptor_queue, info, rescaling, samplers_it,
views_it);
if (!is_built.load(std::memory_order::relaxed)) {
@@ -204,7 +204,7 @@ void ComputePipeline::Configure(Tegra::Engines::KeplerCompute& kepler_compute,
build_condvar.wait(lock, [this] { return is_built.load(std::memory_order::relaxed); });
});
}
- const void* const descriptor_data{update_descriptor_queue.UpdateData()};
+ const void* const descriptor_data{guest_descriptor_queue.UpdateData()};
const bool is_rescaling = !info.texture_descriptors.empty() || !info.image_descriptors.empty();
scheduler.Record([this, descriptor_data, is_rescaling,
rescaling_data = rescaling.Data()](vk::CommandBuffer cmdbuf) {
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.h b/src/video_core/renderer_vulkan/vk_compute_pipeline.h
index 78d77027f..d1a1e2c46 100644
--- a/src/video_core/renderer_vulkan/vk_compute_pipeline.h
+++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.h
@@ -30,7 +30,7 @@ class ComputePipeline {
public:
explicit ComputePipeline(const Device& device, vk::PipelineCache& pipeline_cache,
DescriptorPool& descriptor_pool,
- UpdateDescriptorQueue& update_descriptor_queue,
+ GuestDescriptorQueue& guest_descriptor_queue,
Common::ThreadWorker* thread_worker,
PipelineStatistics* pipeline_statistics,
VideoCore::ShaderNotify* shader_notify, const Shader::Info& info,
@@ -48,7 +48,7 @@ public:
private:
const Device& device;
vk::PipelineCache& pipeline_cache;
- UpdateDescriptorQueue& update_descriptor_queue;
+ GuestDescriptorQueue& guest_descriptor_queue;
Shader::Info info;
VideoCommon::ComputeUniformBufferSizes uniform_buffer_sizes{};
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
index baedc4424..f1bcd5cd6 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -236,13 +236,13 @@ GraphicsPipeline::GraphicsPipeline(
Scheduler& scheduler_, BufferCache& buffer_cache_, TextureCache& texture_cache_,
vk::PipelineCache& pipeline_cache_, VideoCore::ShaderNotify* shader_notify,
const Device& device_, DescriptorPool& descriptor_pool,
- UpdateDescriptorQueue& update_descriptor_queue_, Common::ThreadWorker* worker_thread,
+ GuestDescriptorQueue& guest_descriptor_queue_, Common::ThreadWorker* worker_thread,
PipelineStatistics* pipeline_statistics, RenderPassCache& render_pass_cache,
const GraphicsPipelineCacheKey& key_, std::array<vk::ShaderModule, NUM_STAGES> stages,
const std::array<const Shader::Info*, NUM_STAGES>& infos)
: key{key_}, device{device_}, texture_cache{texture_cache_}, buffer_cache{buffer_cache_},
pipeline_cache(pipeline_cache_), scheduler{scheduler_},
- update_descriptor_queue{update_descriptor_queue_}, spv_modules{std::move(stages)} {
+ guest_descriptor_queue{guest_descriptor_queue_}, spv_modules{std::move(stages)} {
if (shader_notify) {
shader_notify->MarkShaderBuilding();
}
@@ -449,7 +449,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
buffer_cache.UpdateGraphicsBuffers(is_indexed);
buffer_cache.BindHostGeometryBuffers(is_indexed);
- update_descriptor_queue.Acquire();
+ guest_descriptor_queue.Acquire();
RescalingPushConstant rescaling;
RenderAreaPushConstant render_area;
@@ -457,7 +457,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
const VideoCommon::ImageViewInOut* views_it{views.data()};
const auto prepare_stage{[&](size_t stage) LAMBDA_FORCEINLINE {
buffer_cache.BindHostStageBuffers(stage);
- PushImageDescriptors(texture_cache, update_descriptor_queue, stage_infos[stage], rescaling,
+ PushImageDescriptors(texture_cache, guest_descriptor_queue, stage_infos[stage], rescaling,
samplers_it, views_it);
const auto& info{stage_infos[0]};
if (info.uses_render_area) {
@@ -499,7 +499,7 @@ void GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling,
const bool is_rescaling{texture_cache.IsRescaling()};
const bool update_rescaling{scheduler.UpdateRescaling(is_rescaling)};
const bool bind_pipeline{scheduler.UpdateGraphicsPipeline(this)};
- const void* const descriptor_data{update_descriptor_queue.UpdateData()};
+ const void* const descriptor_data{guest_descriptor_queue.UpdateData()};
scheduler.Record([this, descriptor_data, bind_pipeline, rescaling_data = rescaling.Data(),
is_rescaling, update_rescaling,
uses_render_area = render_area.uses_render_area,
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h
index 67c657d0e..99e56e9ad 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h
@@ -64,7 +64,6 @@ class RenderPassCache;
class RescalingPushConstant;
class RenderAreaPushConstant;
class Scheduler;
-class UpdateDescriptorQueue;
class GraphicsPipeline {
static constexpr size_t NUM_STAGES = Tegra::Engines::Maxwell3D::Regs::MaxShaderStage;
@@ -74,7 +73,7 @@ public:
Scheduler& scheduler, BufferCache& buffer_cache, TextureCache& texture_cache,
vk::PipelineCache& pipeline_cache, VideoCore::ShaderNotify* shader_notify,
const Device& device, DescriptorPool& descriptor_pool,
- UpdateDescriptorQueue& update_descriptor_queue, Common::ThreadWorker* worker_thread,
+ GuestDescriptorQueue& guest_descriptor_queue, Common::ThreadWorker* worker_thread,
PipelineStatistics* pipeline_statistics, RenderPassCache& render_pass_cache,
const GraphicsPipelineCacheKey& key, std::array<vk::ShaderModule, NUM_STAGES> stages,
const std::array<const Shader::Info*, NUM_STAGES>& infos);
@@ -133,7 +132,7 @@ private:
BufferCache& buffer_cache;
vk::PipelineCache& pipeline_cache;
Scheduler& scheduler;
- UpdateDescriptorQueue& update_descriptor_queue;
+ GuestDescriptorQueue& guest_descriptor_queue;
void (*configure_func)(GraphicsPipeline*, bool){};
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index a318d643e..66dfe5733 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -277,11 +277,11 @@ bool GraphicsPipelineCacheKey::operator==(const GraphicsPipelineCacheKey& rhs) c
PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device_,
Scheduler& scheduler_, DescriptorPool& descriptor_pool_,
- UpdateDescriptorQueue& update_descriptor_queue_,
+ GuestDescriptorQueue& guest_descriptor_queue_,
RenderPassCache& render_pass_cache_, BufferCache& buffer_cache_,
TextureCache& texture_cache_, VideoCore::ShaderNotify& shader_notify_)
: VideoCommon::ShaderCache{rasterizer_}, device{device_}, scheduler{scheduler_},
- descriptor_pool{descriptor_pool_}, update_descriptor_queue{update_descriptor_queue_},
+ descriptor_pool{descriptor_pool_}, guest_descriptor_queue{guest_descriptor_queue_},
render_pass_cache{render_pass_cache_}, buffer_cache{buffer_cache_},
texture_cache{texture_cache_}, shader_notify{shader_notify_},
use_asynchronous_shaders{Settings::values.use_asynchronous_shaders.GetValue()},
@@ -643,7 +643,7 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline(
Common::ThreadWorker* const thread_worker{build_in_parallel ? &workers : nullptr};
return std::make_unique<GraphicsPipeline>(
scheduler, buffer_cache, texture_cache, vulkan_pipeline_cache, &shader_notify, device,
- descriptor_pool, update_descriptor_queue, thread_worker, statistics, render_pass_cache, key,
+ descriptor_pool, guest_descriptor_queue, thread_worker, statistics, render_pass_cache, key,
std::move(modules), infos);
} catch (const Shader::Exception& exception) {
@@ -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;
}
@@ -722,7 +723,7 @@ std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline(
}
Common::ThreadWorker* const thread_worker{build_in_parallel ? &workers : nullptr};
return std::make_unique<ComputePipeline>(device, vulkan_pipeline_cache, descriptor_pool,
- update_descriptor_queue, thread_worker, statistics,
+ guest_descriptor_queue, thread_worker, statistics,
&shader_notify, program.info, std::move(spv_module));
} catch (const Shader::Exception& exception) {
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.h b/src/video_core/renderer_vulkan/vk_pipeline_cache.h
index 5171912d7..15aa7e224 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.h
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.h
@@ -82,7 +82,6 @@ class PipelineStatistics;
class RasterizerVulkan;
class RenderPassCache;
class Scheduler;
-class UpdateDescriptorQueue;
using VideoCommon::ShaderInfo;
@@ -102,7 +101,7 @@ class PipelineCache : public VideoCommon::ShaderCache {
public:
explicit PipelineCache(RasterizerVulkan& rasterizer, const Device& device, Scheduler& scheduler,
DescriptorPool& descriptor_pool,
- UpdateDescriptorQueue& update_descriptor_queue,
+ GuestDescriptorQueue& guest_descriptor_queue,
RenderPassCache& render_pass_cache, BufferCache& buffer_cache,
TextureCache& texture_cache, VideoCore::ShaderNotify& shader_notify_);
~PipelineCache();
@@ -144,7 +143,7 @@ private:
const Device& device;
Scheduler& scheduler;
DescriptorPool& descriptor_pool;
- UpdateDescriptorQueue& update_descriptor_queue;
+ GuestDescriptorQueue& guest_descriptor_queue;
RenderPassCache& render_pass_cache;
BufferCache& buffer_cache;
TextureCache& texture_cache;
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index cbf23552c..8d3a9736b 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -160,17 +160,16 @@ RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra
: RasterizerAccelerated{cpu_memory_}, gpu{gpu_}, screen_info{screen_info_}, device{device_},
memory_allocator{memory_allocator_}, state_tracker{state_tracker_}, scheduler{scheduler_},
staging_pool(device, memory_allocator, scheduler), descriptor_pool(device, scheduler),
- update_descriptor_queue(device, scheduler),
- blit_image(device, scheduler, state_tracker, descriptor_pool),
- render_pass_cache(device), texture_cache_runtime{device, scheduler,
- memory_allocator, staging_pool,
- blit_image, render_pass_cache,
- descriptor_pool, update_descriptor_queue},
+ guest_descriptor_queue(device, scheduler), compute_pass_descriptor_queue(device, scheduler),
+ blit_image(device, scheduler, state_tracker, descriptor_pool), render_pass_cache(device),
+ texture_cache_runtime{
+ device, scheduler, memory_allocator, staging_pool,
+ blit_image, render_pass_cache, descriptor_pool, compute_pass_descriptor_queue},
texture_cache(texture_cache_runtime, *this),
buffer_cache_runtime(device, memory_allocator, scheduler, staging_pool,
- update_descriptor_queue, descriptor_pool),
+ guest_descriptor_queue, compute_pass_descriptor_queue, descriptor_pool),
buffer_cache(*this, cpu_memory_, buffer_cache_runtime),
- pipeline_cache(*this, device, scheduler, descriptor_pool, update_descriptor_queue,
+ pipeline_cache(*this, device, scheduler, descriptor_pool, guest_descriptor_queue,
render_pass_cache, buffer_cache, texture_cache, gpu.ShaderNotify()),
query_cache{*this, cpu_memory_, device, scheduler},
accelerate_dma(buffer_cache, texture_cache, scheduler),
@@ -656,7 +655,8 @@ void RasterizerVulkan::FlushCommands() {
void RasterizerVulkan::TickFrame() {
draw_counter = 0;
- update_descriptor_queue.TickFrame();
+ guest_descriptor_queue.TickFrame();
+ compute_pass_descriptor_queue.TickFrame();
fence_manager.TickFrame();
staging_pool.TickFrame();
{
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h
index 9bd422850..b39710b3c 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.h
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.h
@@ -184,7 +184,8 @@ private:
StagingBufferPool staging_pool;
DescriptorPool descriptor_pool;
- UpdateDescriptorQueue update_descriptor_queue;
+ GuestDescriptorQueue guest_descriptor_queue;
+ ComputePassDescriptorQueue compute_pass_descriptor_queue;
BlitImageHelper blit_image;
RenderPassCache render_pass_cache;
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index 9ca7751c5..4d0481f2a 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -798,13 +798,13 @@ TextureCacheRuntime::TextureCacheRuntime(const Device& device_, Scheduler& sched
BlitImageHelper& blit_image_helper_,
RenderPassCache& render_pass_cache_,
DescriptorPool& descriptor_pool,
- UpdateDescriptorQueue& update_descriptor_queue)
+ ComputePassDescriptorQueue& compute_pass_descriptor_queue)
: device{device_}, scheduler{scheduler_}, memory_allocator{memory_allocator_},
staging_buffer_pool{staging_buffer_pool_}, blit_image_helper{blit_image_helper_},
render_pass_cache{render_pass_cache_}, resolution{Settings::values.resolution_info} {
if (Settings::values.accelerate_astc) {
astc_decoder_pass.emplace(device, scheduler, descriptor_pool, staging_buffer_pool,
- update_descriptor_queue, memory_allocator);
+ compute_pass_descriptor_queue, memory_allocator);
}
}
@@ -1864,6 +1864,7 @@ void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime,
num_layers = std::max(num_layers, color_buffer->range.extent.layers);
images[num_images] = color_buffer->ImageHandle();
image_ranges[num_images] = MakeSubresourceRange(color_buffer);
+ rt_map[index] = num_images;
samples = color_buffer->Samples();
++num_images;
}
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h
index 6f360177a..4166b3d20 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.h
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.h
@@ -34,7 +34,6 @@ class ImageView;
class Framebuffer;
class RenderPassCache;
class StagingBufferPool;
-class UpdateDescriptorQueue;
class Scheduler;
class TextureCacheRuntime {
@@ -45,7 +44,7 @@ public:
BlitImageHelper& blit_image_helper_,
RenderPassCache& render_pass_cache_,
DescriptorPool& descriptor_pool,
- UpdateDescriptorQueue& update_descriptor_queue);
+ ComputePassDescriptorQueue& compute_pass_descriptor_queue);
void Finish();
@@ -335,7 +334,7 @@ public:
}
[[nodiscard]] bool HasAspectColorBit(size_t index) const noexcept {
- return (image_ranges.at(index).aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) != 0;
+ return (image_ranges.at(rt_map[index]).aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) != 0;
}
[[nodiscard]] bool HasAspectDepthBit() const noexcept {
@@ -355,6 +354,7 @@ private:
u32 num_images = 0;
std::array<VkImage, 9> images{};
std::array<VkImageSubresourceRange, 9> image_ranges{};
+ std::array<size_t, NUM_RT> rt_map{};
bool has_depth{};
bool has_stencil{};
};
diff --git a/src/video_core/renderer_vulkan/vk_update_descriptor.h b/src/video_core/renderer_vulkan/vk_update_descriptor.h
index 1c1a7020b..310fb551a 100644
--- a/src/video_core/renderer_vulkan/vk_update_descriptor.h
+++ b/src/video_core/renderer_vulkan/vk_update_descriptor.h
@@ -32,7 +32,7 @@ class UpdateDescriptorQueue final {
// This should be plenty for the vast majority of cases. Most desktop platforms only
// provide up to 3 swapchain images.
static constexpr size_t FRAMES_IN_FLIGHT = 5;
- static constexpr size_t FRAME_PAYLOAD_SIZE = 0x10000;
+ static constexpr size_t FRAME_PAYLOAD_SIZE = 0x20000;
static constexpr size_t PAYLOAD_SIZE = FRAME_PAYLOAD_SIZE * FRAMES_IN_FLIGHT;
public:
@@ -86,4 +86,8 @@ private:
std::array<DescriptorUpdateEntry, PAYLOAD_SIZE> payload;
};
+// TODO: should these be separate classes instead?
+using GuestDescriptorQueue = UpdateDescriptorQueue;
+using ComputePassDescriptorQueue = UpdateDescriptorQueue;
+
} // namespace Vulkan
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index e1198dcf8..b24086fce 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -1469,7 +1469,7 @@ std::optional<typename TextureCache<P>::BlitImages> TextureCache<P>::GetBlitImag
if (!copy.must_accelerate) {
do {
if (!src_id && !dst_id) {
- return std::nullopt;
+ break;
}
if (src_id && True(slot_images[src_id].flags & ImageFlagBits::GpuModified)) {
break;
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp
index 6ffca2af2..161f050b8 100644
--- a/src/video_core/vulkan_common/vulkan_device.cpp
+++ b/src/video_core/vulkan_common/vulkan_device.cpp
@@ -1009,6 +1009,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 a49d12266..70737c54e 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -443,6 +443,7 @@ void Config::ReadControlValues() {
ReadBasicSetting(Settings::values.mouse_panning_sensitivity);
ReadBasicSetting(Settings::values.enable_joycon_driver);
ReadBasicSetting(Settings::values.enable_procon_driver);
+ ReadBasicSetting(Settings::values.random_amiibo_id);
ReadBasicSetting(Settings::values.tas_enable);
ReadBasicSetting(Settings::values.tas_loop);
@@ -715,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);
@@ -1150,6 +1152,7 @@ void Config::SaveControlValues() {
WriteBasicSetting(Settings::values.enable_raw_input);
WriteBasicSetting(Settings::values.enable_joycon_driver);
WriteBasicSetting(Settings::values.enable_procon_driver);
+ WriteBasicSetting(Settings::values.random_amiibo_id);
WriteBasicSetting(Settings::values.keyboard_enabled);
WriteBasicSetting(Settings::values.emulate_analog_keyboard);
WriteBasicSetting(Settings::values.mouse_panning_sensitivity);
@@ -1364,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_input_advanced.cpp b/src/yuzu/configuration/configure_input_advanced.cpp
index 8d81322f3..f13156434 100644
--- a/src/yuzu/configuration/configure_input_advanced.cpp
+++ b/src/yuzu/configuration/configure_input_advanced.cpp
@@ -140,6 +140,7 @@ void ConfigureInputAdvanced::ApplyConfiguration() {
Settings::values.enable_ir_sensor = ui->enable_ir_sensor->isChecked();
Settings::values.enable_joycon_driver = ui->enable_joycon_driver->isChecked();
Settings::values.enable_procon_driver = ui->enable_procon_driver->isChecked();
+ Settings::values.random_amiibo_id = ui->random_amiibo_id->isChecked();
}
void ConfigureInputAdvanced::LoadConfiguration() {
@@ -176,6 +177,7 @@ void ConfigureInputAdvanced::LoadConfiguration() {
ui->enable_ir_sensor->setChecked(Settings::values.enable_ir_sensor.GetValue());
ui->enable_joycon_driver->setChecked(Settings::values.enable_joycon_driver.GetValue());
ui->enable_procon_driver->setChecked(Settings::values.enable_procon_driver.GetValue());
+ ui->random_amiibo_id->setChecked(Settings::values.random_amiibo_id.GetValue());
UpdateUIEnabled();
}
diff --git a/src/yuzu/configuration/configure_input_advanced.ui b/src/yuzu/configuration/configure_input_advanced.ui
index 0eb2b34bc..2e8b13660 100644
--- a/src/yuzu/configuration/configure_input_advanced.ui
+++ b/src/yuzu/configuration/configure_input_advanced.ui
@@ -2728,6 +2728,22 @@
</widget>
</item>
<item row="7" column="0">
+ <widget class="QCheckBox" name="random_amiibo_id">
+ <property name="toolTip">
+ <string>Allows unlimited uses of the same Amiibo in games that would otherwise limit you to one use.</string>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>23</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Use random Amiibo ID</string>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="0">
<widget class="QCheckBox" name="mouse_panning">
<property name="minimumSize">
<size>
@@ -2740,7 +2756,7 @@
</property>
</widget>
</item>
- <item row="7" column="2">
+ <item row="8" column="2">
<widget class="QSpinBox" name="mouse_panning_sensitivity">
<property name="toolTip">
<string>Mouse sensitivity</string>
@@ -2762,14 +2778,14 @@
</property>
</widget>
</item>
- <item row="8" column="0">
+ <item row="9" column="0">
<widget class="QLabel" name="motion_touch">
<property name="text">
<string>Motion / Touch</string>
</property>
</widget>
</item>
- <item row="8" column="2">
+ <item row="9" column="2">
<widget class="QPushButton" name="buttonMotionTouch">
<property name="text">
<string>Configure</string>
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();
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
index abe7092fc..dc9a3d68f 100644
--- a/src/yuzu_cmd/config.cpp
+++ b/src/yuzu_cmd/config.cpp
@@ -169,6 +169,7 @@ void Config::ReadValues() {
ReadSetting("ControlsGeneral", Settings::values.enable_raw_input);
ReadSetting("ControlsGeneral", Settings::values.enable_joycon_driver);
ReadSetting("ControlsGeneral", Settings::values.enable_procon_driver);
+ ReadSetting("ControlsGeneral", Settings::values.random_amiibo_id);
ReadSetting("ControlsGeneral", Settings::values.emulate_analog_keyboard);
ReadSetting("ControlsGeneral", Settings::values.vibration_enabled);
ReadSetting("ControlsGeneral", Settings::values.enable_accurate_vibrations);