diff --git a/README.md b/README.md index ca8e4541f..3da8d8f40 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 3970. +This is the source code for early-access 3971. ## Legal Notice diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 96de39a4f..0845bdc2d 100755 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -203,6 +203,8 @@ const char* TranslateCategory(Category category) { case Category::Ui: case Category::UiGeneral: return "UI"; + case Category::UiAudio: + return "UiAudio"; case Category::UiLayout: return "UiLayout"; case Category::UiGameList: diff --git a/src/common/settings.h b/src/common/settings.h index 3d70f0919..087c91111 100755 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -153,7 +153,7 @@ struct Values { true, true}; Setting audio_muted{ - linkage, false, "audio_muted", Category::Audio, Specialization::Default, false, true}; + linkage, false, "audio_muted", Category::Audio, Specialization::Default, true, true}; Setting dump_audio_commands{ linkage, false, "dump_audio_commands", Category::Audio, Specialization::Default, false}; diff --git a/src/common/settings_common.h b/src/common/settings_common.h index 1800ab10d..7943223eb 100755 --- a/src/common/settings_common.h +++ b/src/common/settings_common.h @@ -32,6 +32,7 @@ enum class Category : u32 { AddOns, Controls, Ui, + UiAudio, UiGeneral, UiLayout, UiGameList, diff --git a/src/core/hle/kernel/k_page_table_base.cpp b/src/core/hle/kernel/k_page_table_base.cpp index c97b4a6b7..6a57ad55c 100755 --- a/src/core/hle/kernel/k_page_table_base.cpp +++ b/src/core/hle/kernel/k_page_table_base.cpp @@ -68,10 +68,6 @@ public: } }; -void InvalidateEntireInstructionCache(Core::System& system) { - system.InvalidateCpuInstructionCaches(); -} - template void InvalidateInstructionCache(Core::System& system, AddressType addr, u64 size) { system.InvalidateCpuInstructionCacheRange(GetInteger(addr), size); @@ -435,9 +431,6 @@ void KPageTableBase::Finalize() { m_mapped_ipc_server_memory); } - // Invalidate the entire instruction cache. - InvalidateEntireInstructionCache(m_system); - // Close the backing page table, as the destructor is not called for guest objects. m_impl.reset(); } diff --git a/src/core/hle/service/hid/irsensor/clustering_processor.cpp b/src/core/hle/service/hid/irsensor/clustering_processor.cpp index 2ed4b140c..8ea4036d2 100755 --- a/src/core/hle/service/hid/irsensor/clustering_processor.cpp +++ b/src/core/hle/service/hid/irsensor/clustering_processor.cpp @@ -3,16 +3,18 @@ #include +#include "core/core.h" +#include "core/core_timing.h" #include "core/hid/emulated_controller.h" #include "core/hid/hid_core.h" #include "core/hle/service/hid/irsensor/clustering_processor.h" namespace Service::IRS { -ClusteringProcessor::ClusteringProcessor(Core::HID::HIDCore& hid_core_, +ClusteringProcessor::ClusteringProcessor(Core::System& system_, Core::IrSensor::DeviceFormat& device_format, std::size_t npad_index) - : device{device_format} { - npad_device = hid_core_.GetEmulatedControllerByIndex(npad_index); + : device{device_format}, system{system_} { + npad_device = system.HIDCore().GetEmulatedControllerByIndex(npad_index); device.mode = Core::IrSensor::IrSensorMode::ClusteringProcessor; device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; @@ -83,7 +85,7 @@ void ClusteringProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType ty } next_state.sampling_number = camera_data.sample; - next_state.timestamp = next_state.timestamp + 131; + next_state.timestamp = system.CoreTiming().GetGlobalTimeNs().count(); next_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low; shared_memory->clustering_lifo.WriteNextEntry(next_state); diff --git a/src/core/hle/service/hid/irsensor/clustering_processor.h b/src/core/hle/service/hid/irsensor/clustering_processor.h index d1083d176..5b7d8208f 100755 --- a/src/core/hle/service/hid/irsensor/clustering_processor.h +++ b/src/core/hle/service/hid/irsensor/clustering_processor.h @@ -8,6 +8,10 @@ #include "core/hle/service/hid/irs_ring_lifo.h" #include "core/hle/service/hid/irsensor/processor_base.h" +namespace Core { +class System; +} + namespace Core::HID { class EmulatedController; } // namespace Core::HID @@ -15,8 +19,7 @@ class EmulatedController; namespace Service::IRS { class ClusteringProcessor final : public ProcessorBase { public: - explicit ClusteringProcessor(Core::HID::HIDCore& hid_core_, - Core::IrSensor::DeviceFormat& device_format, + explicit ClusteringProcessor(Core::System& system_, Core::IrSensor::DeviceFormat& device_format, std::size_t npad_index); ~ClusteringProcessor() override; @@ -106,5 +109,7 @@ private: Core::IrSensor::DeviceFormat& device; Core::HID::EmulatedController* npad_device; int callback_key{}; + + Core::System& system; }; } // namespace Service::IRS diff --git a/src/core/hle/service/hid/irsensor/moment_processor.cpp b/src/core/hle/service/hid/irsensor/moment_processor.cpp index 3e2fee501..2eccbae8b 100755 --- a/src/core/hle/service/hid/irsensor/moment_processor.cpp +++ b/src/core/hle/service/hid/irsensor/moment_processor.cpp @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later +#include "core/core.h" +#include "core/core_timing.h" #include "core/hid/emulated_controller.h" #include "core/hid/hid_core.h" #include "core/hle/service/hid/irsensor/moment_processor.h" @@ -10,11 +12,10 @@ static constexpr auto format = Core::IrSensor::ImageTransferProcessorFormat::Siz static constexpr std::size_t ImageWidth = 40; static constexpr std::size_t ImageHeight = 30; -MomentProcessor::MomentProcessor(Core::HID::HIDCore& hid_core_, - Core::IrSensor::DeviceFormat& device_format, +MomentProcessor::MomentProcessor(Core::System& system_, Core::IrSensor::DeviceFormat& device_format, std::size_t npad_index) - : device(device_format) { - npad_device = hid_core_.GetEmulatedControllerByIndex(npad_index); + : device(device_format), system{system_} { + npad_device = system.HIDCore().GetEmulatedControllerByIndex(npad_index); device.mode = Core::IrSensor::IrSensorMode::MomentProcessor; device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected; @@ -69,7 +70,7 @@ void MomentProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType type) } next_state.sampling_number = camera_data.sample; - next_state.timestamp = next_state.timestamp + 131; + next_state.timestamp = system.CoreTiming().GetGlobalTimeNs().count(); next_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low; shared_memory->moment_lifo.WriteNextEntry(next_state); diff --git a/src/core/hle/service/hid/irsensor/moment_processor.h b/src/core/hle/service/hid/irsensor/moment_processor.h index bb8fd7479..a5008e6c2 100755 --- a/src/core/hle/service/hid/irsensor/moment_processor.h +++ b/src/core/hle/service/hid/irsensor/moment_processor.h @@ -9,11 +9,19 @@ #include "core/hle/service/hid/irs_ring_lifo.h" #include "core/hle/service/hid/irsensor/processor_base.h" +namespace Core { +class System; +} + +namespace Core::HID { +class EmulatedController; +} // namespace Core::HID + namespace Service::IRS { class MomentProcessor final : public ProcessorBase { public: - explicit MomentProcessor(Core::HID::HIDCore& hid_core_, - Core::IrSensor::DeviceFormat& device_format, std::size_t npad_index); + explicit MomentProcessor(Core::System& system_, Core::IrSensor::DeviceFormat& device_format, + std::size_t npad_index); ~MomentProcessor() override; // Called when the processor is initialized @@ -76,6 +84,8 @@ private: Core::IrSensor::DeviceFormat& device; Core::HID::EmulatedController* npad_device; int callback_key{}; + + Core::System& system; }; } // namespace Service::IRS diff --git a/src/core/memory.cpp b/src/core/memory.cpp index bfdb1694a..c1945911d 100755 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -1,8 +1,10 @@ // SPDX-FileCopyrightText: 2015 Citra Emulator Project +// SPDX-FileCopyrightText: 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include #include +#include #include #include "common/assert.h" @@ -10,6 +12,7 @@ #include "common/common_types.h" #include "common/logging/log.h" #include "common/page_table.h" +#include "common/scope_exit.h" #include "common/settings.h" #include "common/swap.h" #include "core/core.h" @@ -318,7 +321,7 @@ struct Memory::Impl { [&](const Common::ProcessAddress current_vaddr, const std::size_t copy_amount, u8* const host_ptr) { if constexpr (!UNSAFE) { - system.GPU().InvalidateRegion(GetInteger(current_vaddr), copy_amount); + HandleRasterizerWrite(GetInteger(current_vaddr), copy_amount); } std::memcpy(host_ptr, src_buffer, copy_amount); }, @@ -351,7 +354,7 @@ struct Memory::Impl { }, [&](const Common::ProcessAddress current_vaddr, const std::size_t copy_amount, u8* const host_ptr) { - system.GPU().InvalidateRegion(GetInteger(current_vaddr), copy_amount); + HandleRasterizerWrite(GetInteger(current_vaddr), copy_amount); std::memset(host_ptr, 0, copy_amount); }, [](const std::size_t copy_amount) {}); @@ -420,7 +423,7 @@ struct Memory::Impl { const std::size_t block_size) { // dc cvac: Store to point of coherency // CPU flush -> GPU invalidate - system.GPU().InvalidateRegion(GetInteger(current_vaddr), block_size); + HandleRasterizerWrite(GetInteger(current_vaddr), block_size); }; return PerformCacheOperation(dest_addr, size, on_rasterizer); } @@ -430,7 +433,7 @@ struct Memory::Impl { const std::size_t block_size) { // dc civac: Store to point of coherency, and invalidate from cache // CPU flush -> GPU invalidate - system.GPU().InvalidateRegion(GetInteger(current_vaddr), block_size); + HandleRasterizerWrite(GetInteger(current_vaddr), block_size); }; return PerformCacheOperation(dest_addr, size, on_rasterizer); } @@ -767,7 +770,18 @@ struct Memory::Impl { } void HandleRasterizerWrite(VAddr address, size_t size) { - const size_t core = system.GetCurrentHostThreadID(); + constexpr size_t sys_core = Core::Hardware::NUM_CPU_CORES - 1; + const size_t core = std::min(system.GetCurrentHostThreadID(), + sys_core); // any other calls threads go to syscore. + // Guard on sys_core; + if (core == sys_core) [[unlikely]] { + sys_core_guard.lock(); + } + SCOPE_EXIT({ + if (core == sys_core) [[unlikely]] { + sys_core_guard.unlock(); + } + }); auto& current_area = rasterizer_write_areas[core]; VAddr subaddress = address >> YUZU_PAGEBITS; bool do_collection = current_area.last_address == subaddress; @@ -799,6 +813,7 @@ struct Memory::Impl { rasterizer_read_areas{}; std::array rasterizer_write_areas{}; std::span gpu_dirty_managers; + std::mutex sys_core_guard; }; Memory::Memory(Core::System& system_) : system{system_} { diff --git a/src/video_core/fence_manager.h b/src/video_core/fence_manager.h index 667941b7c..139c824d3 100755 --- a/src/video_core/fence_manager.h +++ b/src/video_core/fence_manager.h @@ -86,10 +86,7 @@ public: uncommitted_operations.emplace_back(std::move(func)); } pending_operations.emplace_back(std::move(uncommitted_operations)); - { - std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex}; - QueueFence(new_fence); - } + QueueFence(new_fence); if (!delay_fence) { func(); } diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 6f0f23cb4..fd013e35c 100755 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -132,16 +132,12 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { const bool use_accelerated = rasterizer.AccelerateDisplay(*framebuffer, framebuffer_addr, framebuffer->stride); const bool is_srgb = use_accelerated && screen_info.is_srgb; + RenderScreenshot(*framebuffer, use_accelerated); - { - std::scoped_lock lock{rasterizer.LockCaches()}; - RenderScreenshot(*framebuffer, use_accelerated); - - Frame* frame = present_manager.GetRenderFrame(); - blit_screen.DrawToSwapchain(frame, *framebuffer, use_accelerated, is_srgb); - scheduler.Flush(*frame->render_ready); - present_manager.Present(frame); - } + Frame* frame = present_manager.GetRenderFrame(); + blit_screen.DrawToSwapchain(frame, *framebuffer, use_accelerated, is_srgb); + scheduler.Flush(*frame->render_ready); + present_manager.Present(frame); gpu.RendererFrameEndNotify(); rasterizer.TickFrame(); diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index e5f67521b..66bf2ecc5 100755 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -199,7 +199,7 @@ void RasterizerVulkan::PrepareDraw(bool is_indexed, Func&& draw_func) { if (!pipeline) { return; } - std::scoped_lock lock{LockCaches()}; + std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex}; // update engine as channel may be different. pipeline->SetEngine(maxwell3d, gpu_memory); pipeline->Configure(is_indexed); @@ -710,7 +710,6 @@ void RasterizerVulkan::TiledCacheBarrier() { } void RasterizerVulkan::FlushCommands() { - std::scoped_lock lock{LockCaches()}; if (draw_counter == 0) { return; } @@ -808,7 +807,6 @@ void RasterizerVulkan::FlushWork() { if ((++draw_counter & 7) != 7) { return; } - std::scoped_lock lock{LockCaches()}; if (draw_counter < DRAWS_TO_DISPATCH) { // Send recorded tasks to the worker thread scheduler.DispatchWork(); @@ -1507,7 +1505,7 @@ void RasterizerVulkan::UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs) void RasterizerVulkan::InitializeChannel(Tegra::Control::ChannelState& channel) { CreateChannel(channel); { - std::scoped_lock lock{LockCaches()}; + std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex}; texture_cache.CreateChannel(channel); buffer_cache.CreateChannel(channel); } @@ -1520,7 +1518,7 @@ void RasterizerVulkan::BindChannel(Tegra::Control::ChannelState& channel) { const s32 channel_id = channel.bind_id; BindToChannel(channel_id); { - std::scoped_lock lock{LockCaches()}; + std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex}; texture_cache.BindToChannel(channel_id); buffer_cache.BindToChannel(channel_id); } @@ -1533,7 +1531,7 @@ void RasterizerVulkan::BindChannel(Tegra::Control::ChannelState& channel) { void RasterizerVulkan::ReleaseChannel(s32 channel_id) { EraseChannel(channel_id); { - std::scoped_lock lock{LockCaches()}; + std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex}; texture_cache.EraseChannel(channel_id); buffer_cache.EraseChannel(channel_id); } diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index eec070e2a..b8c637c47 100755 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h @@ -133,10 +133,6 @@ public: void ReleaseChannel(s32 channel_id) override; - std::scoped_lock LockCaches() { - return std::scoped_lock{buffer_cache.mutex, texture_cache.mutex}; - } - private: static constexpr size_t MAX_TEXTURES = 192; static constexpr size_t MAX_IMAGES = 48; diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index e333153cd..77c49aa8e 100755 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -360,6 +360,7 @@ void Config::ReadAudioValues() { qt_config->beginGroup(QStringLiteral("Audio")); ReadCategory(Settings::Category::Audio); + ReadCategory(Settings::Category::UiAudio); qt_config->endGroup(); } @@ -900,6 +901,7 @@ void Config::SaveAudioValues() { qt_config->beginGroup(QStringLiteral("Audio")); WriteCategory(Settings::Category::Audio); + WriteCategory(Settings::Category::UiAudio); qt_config->endGroup(); } diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp index 91a18ab56..1ce365109 100755 --- a/src/yuzu/configuration/configure_audio.cpp +++ b/src/yuzu/configuration/configure_audio.cpp @@ -38,17 +38,21 @@ void ConfigureAudio::Setup(const ConfigurationShared::Builder& builder) { std::map hold; - auto push = [&](Settings::Category category) { + auto push_settings = [&](Settings::Category category) { for (auto* setting : Settings::values.linkage.by_category[category]) { settings.push_back(setting); } + }; + + auto push_ui_settings = [&](Settings::Category category) { for (auto* setting : UISettings::values.linkage.by_category[category]) { settings.push_back(setting); } }; - push(Settings::Category::Audio); - push(Settings::Category::SystemAudio); + push_settings(Settings::Category::Audio); + push_settings(Settings::Category::SystemAudio); + push_ui_settings(Settings::Category::UiAudio); for (auto* setting : settings) { auto* widget = builder.BuildWidget(setting, apply_funcs); diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 448bb512d..7e40f84b3 100755 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -1065,12 +1065,6 @@ void GMainWindow::InitializeWidgets() { volume_slider->setObjectName(QStringLiteral("volume_slider")); volume_slider->setMaximum(200); volume_slider->setPageStep(5); - connect(volume_slider, &QSlider::valueChanged, this, [this](int percentage) { - Settings::values.audio_muted = false; - const auto volume = static_cast(percentage); - Settings::values.volume.SetValue(volume); - UpdateVolumeUI(); - }); volume_popup->layout()->addWidget(volume_slider); volume_button = new VolumeButton(); @@ -1078,6 +1072,12 @@ void GMainWindow::InitializeWidgets() { volume_button->setFocusPolicy(Qt::NoFocus); volume_button->setCheckable(true); UpdateVolumeUI(); + connect(volume_slider, &QSlider::valueChanged, this, [this](int percentage) { + Settings::values.audio_muted = false; + const auto volume = static_cast(percentage); + Settings::values.volume.SetValue(volume); + UpdateVolumeUI(); + }); connect(volume_button, &QPushButton::clicked, this, [&] { UpdateVolumeUI(); volume_popup->setVisible(!volume_popup->isVisible()); diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h index c2c33cb91..043989e34 100755 --- a/src/yuzu/uisettings.h +++ b/src/yuzu/uisettings.h @@ -109,9 +109,13 @@ struct Values { Settings::Specialization::Default, true, true}; - Setting mute_when_in_background{ - linkage, false, "muteWhenInBackground", Category::Audio, Settings::Specialization::Default, - true, true}; + Setting mute_when_in_background{linkage, + false, + "muteWhenInBackground", + Category::UiAudio, + Settings::Specialization::Default, + true, + true}; Setting hide_mouse{ linkage, true, "hideInactiveMouse", Category::UiGeneral, Settings::Specialization::Default, true, true};