diff options
Diffstat (limited to '')
66 files changed, 490 insertions, 263 deletions
@@ -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); |