early-access version 3971
This commit is contained in:
parent
b1b49d9789
commit
44caed8bb2
18 changed files with 88 additions and 62 deletions
|
@ -1,7 +1,7 @@
|
||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 3970.
|
This is the source code for early-access 3971.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
|
|
@ -203,6 +203,8 @@ const char* TranslateCategory(Category category) {
|
||||||
case Category::Ui:
|
case Category::Ui:
|
||||||
case Category::UiGeneral:
|
case Category::UiGeneral:
|
||||||
return "UI";
|
return "UI";
|
||||||
|
case Category::UiAudio:
|
||||||
|
return "UiAudio";
|
||||||
case Category::UiLayout:
|
case Category::UiLayout:
|
||||||
return "UiLayout";
|
return "UiLayout";
|
||||||
case Category::UiGameList:
|
case Category::UiGameList:
|
||||||
|
|
|
@ -153,7 +153,7 @@ struct Values {
|
||||||
true,
|
true,
|
||||||
true};
|
true};
|
||||||
Setting<bool, false> audio_muted{
|
Setting<bool, false> audio_muted{
|
||||||
linkage, false, "audio_muted", Category::Audio, Specialization::Default, false, true};
|
linkage, false, "audio_muted", Category::Audio, Specialization::Default, true, true};
|
||||||
Setting<bool, false> dump_audio_commands{
|
Setting<bool, false> dump_audio_commands{
|
||||||
linkage, false, "dump_audio_commands", Category::Audio, Specialization::Default, false};
|
linkage, false, "dump_audio_commands", Category::Audio, Specialization::Default, false};
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ enum class Category : u32 {
|
||||||
AddOns,
|
AddOns,
|
||||||
Controls,
|
Controls,
|
||||||
Ui,
|
Ui,
|
||||||
|
UiAudio,
|
||||||
UiGeneral,
|
UiGeneral,
|
||||||
UiLayout,
|
UiLayout,
|
||||||
UiGameList,
|
UiGameList,
|
||||||
|
|
|
@ -68,10 +68,6 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void InvalidateEntireInstructionCache(Core::System& system) {
|
|
||||||
system.InvalidateCpuInstructionCaches();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename AddressType>
|
template <typename AddressType>
|
||||||
void InvalidateInstructionCache(Core::System& system, AddressType addr, u64 size) {
|
void InvalidateInstructionCache(Core::System& system, AddressType addr, u64 size) {
|
||||||
system.InvalidateCpuInstructionCacheRange(GetInteger(addr), size);
|
system.InvalidateCpuInstructionCacheRange(GetInteger(addr), size);
|
||||||
|
@ -435,9 +431,6 @@ void KPageTableBase::Finalize() {
|
||||||
m_mapped_ipc_server_memory);
|
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.
|
// Close the backing page table, as the destructor is not called for guest objects.
|
||||||
m_impl.reset();
|
m_impl.reset();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,16 +3,18 @@
|
||||||
|
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
|
#include "core/core.h"
|
||||||
|
#include "core/core_timing.h"
|
||||||
#include "core/hid/emulated_controller.h"
|
#include "core/hid/emulated_controller.h"
|
||||||
#include "core/hid/hid_core.h"
|
#include "core/hid/hid_core.h"
|
||||||
#include "core/hle/service/hid/irsensor/clustering_processor.h"
|
#include "core/hle/service/hid/irsensor/clustering_processor.h"
|
||||||
|
|
||||||
namespace Service::IRS {
|
namespace Service::IRS {
|
||||||
ClusteringProcessor::ClusteringProcessor(Core::HID::HIDCore& hid_core_,
|
ClusteringProcessor::ClusteringProcessor(Core::System& system_,
|
||||||
Core::IrSensor::DeviceFormat& device_format,
|
Core::IrSensor::DeviceFormat& device_format,
|
||||||
std::size_t npad_index)
|
std::size_t npad_index)
|
||||||
: device{device_format} {
|
: device{device_format}, system{system_} {
|
||||||
npad_device = hid_core_.GetEmulatedControllerByIndex(npad_index);
|
npad_device = system.HIDCore().GetEmulatedControllerByIndex(npad_index);
|
||||||
|
|
||||||
device.mode = Core::IrSensor::IrSensorMode::ClusteringProcessor;
|
device.mode = Core::IrSensor::IrSensorMode::ClusteringProcessor;
|
||||||
device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected;
|
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.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;
|
next_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low;
|
||||||
shared_memory->clustering_lifo.WriteNextEntry(next_state);
|
shared_memory->clustering_lifo.WriteNextEntry(next_state);
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,10 @@
|
||||||
#include "core/hle/service/hid/irs_ring_lifo.h"
|
#include "core/hle/service/hid/irs_ring_lifo.h"
|
||||||
#include "core/hle/service/hid/irsensor/processor_base.h"
|
#include "core/hle/service/hid/irsensor/processor_base.h"
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Core::HID {
|
namespace Core::HID {
|
||||||
class EmulatedController;
|
class EmulatedController;
|
||||||
} // namespace Core::HID
|
} // namespace Core::HID
|
||||||
|
@ -15,8 +19,7 @@ class EmulatedController;
|
||||||
namespace Service::IRS {
|
namespace Service::IRS {
|
||||||
class ClusteringProcessor final : public ProcessorBase {
|
class ClusteringProcessor final : public ProcessorBase {
|
||||||
public:
|
public:
|
||||||
explicit ClusteringProcessor(Core::HID::HIDCore& hid_core_,
|
explicit ClusteringProcessor(Core::System& system_, Core::IrSensor::DeviceFormat& device_format,
|
||||||
Core::IrSensor::DeviceFormat& device_format,
|
|
||||||
std::size_t npad_index);
|
std::size_t npad_index);
|
||||||
~ClusteringProcessor() override;
|
~ClusteringProcessor() override;
|
||||||
|
|
||||||
|
@ -106,5 +109,7 @@ private:
|
||||||
Core::IrSensor::DeviceFormat& device;
|
Core::IrSensor::DeviceFormat& device;
|
||||||
Core::HID::EmulatedController* npad_device;
|
Core::HID::EmulatedController* npad_device;
|
||||||
int callback_key{};
|
int callback_key{};
|
||||||
|
|
||||||
|
Core::System& system;
|
||||||
};
|
};
|
||||||
} // namespace Service::IRS
|
} // namespace Service::IRS
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// 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/emulated_controller.h"
|
||||||
#include "core/hid/hid_core.h"
|
#include "core/hid/hid_core.h"
|
||||||
#include "core/hle/service/hid/irsensor/moment_processor.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 ImageWidth = 40;
|
||||||
static constexpr std::size_t ImageHeight = 30;
|
static constexpr std::size_t ImageHeight = 30;
|
||||||
|
|
||||||
MomentProcessor::MomentProcessor(Core::HID::HIDCore& hid_core_,
|
MomentProcessor::MomentProcessor(Core::System& system_, Core::IrSensor::DeviceFormat& device_format,
|
||||||
Core::IrSensor::DeviceFormat& device_format,
|
|
||||||
std::size_t npad_index)
|
std::size_t npad_index)
|
||||||
: device(device_format) {
|
: device(device_format), system{system_} {
|
||||||
npad_device = hid_core_.GetEmulatedControllerByIndex(npad_index);
|
npad_device = system.HIDCore().GetEmulatedControllerByIndex(npad_index);
|
||||||
|
|
||||||
device.mode = Core::IrSensor::IrSensorMode::MomentProcessor;
|
device.mode = Core::IrSensor::IrSensorMode::MomentProcessor;
|
||||||
device.camera_status = Core::IrSensor::IrCameraStatus::Unconnected;
|
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.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;
|
next_state.ambient_noise_level = Core::IrSensor::CameraAmbientNoiseLevel::Low;
|
||||||
shared_memory->moment_lifo.WriteNextEntry(next_state);
|
shared_memory->moment_lifo.WriteNextEntry(next_state);
|
||||||
|
|
||||||
|
|
|
@ -9,11 +9,19 @@
|
||||||
#include "core/hle/service/hid/irs_ring_lifo.h"
|
#include "core/hle/service/hid/irs_ring_lifo.h"
|
||||||
#include "core/hle/service/hid/irsensor/processor_base.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 {
|
namespace Service::IRS {
|
||||||
class MomentProcessor final : public ProcessorBase {
|
class MomentProcessor final : public ProcessorBase {
|
||||||
public:
|
public:
|
||||||
explicit MomentProcessor(Core::HID::HIDCore& hid_core_,
|
explicit MomentProcessor(Core::System& system_, Core::IrSensor::DeviceFormat& device_format,
|
||||||
Core::IrSensor::DeviceFormat& device_format, std::size_t npad_index);
|
std::size_t npad_index);
|
||||||
~MomentProcessor() override;
|
~MomentProcessor() override;
|
||||||
|
|
||||||
// Called when the processor is initialized
|
// Called when the processor is initialized
|
||||||
|
@ -76,6 +84,8 @@ private:
|
||||||
Core::IrSensor::DeviceFormat& device;
|
Core::IrSensor::DeviceFormat& device;
|
||||||
Core::HID::EmulatedController* npad_device;
|
Core::HID::EmulatedController* npad_device;
|
||||||
int callback_key{};
|
int callback_key{};
|
||||||
|
|
||||||
|
Core::System& system;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::IRS
|
} // namespace Service::IRS
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
// SPDX-FileCopyrightText: 2015 Citra Emulator Project
|
// SPDX-FileCopyrightText: 2015 Citra Emulator Project
|
||||||
|
// SPDX-FileCopyrightText: 2018 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <mutex>
|
||||||
#include <span>
|
#include <span>
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
|
@ -10,6 +12,7 @@
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/page_table.h"
|
#include "common/page_table.h"
|
||||||
|
#include "common/scope_exit.h"
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "common/swap.h"
|
#include "common/swap.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
|
@ -318,7 +321,7 @@ struct Memory::Impl {
|
||||||
[&](const Common::ProcessAddress current_vaddr, const std::size_t copy_amount,
|
[&](const Common::ProcessAddress current_vaddr, const std::size_t copy_amount,
|
||||||
u8* const host_ptr) {
|
u8* const host_ptr) {
|
||||||
if constexpr (!UNSAFE) {
|
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);
|
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,
|
[&](const Common::ProcessAddress current_vaddr, const std::size_t copy_amount,
|
||||||
u8* const host_ptr) {
|
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);
|
std::memset(host_ptr, 0, copy_amount);
|
||||||
},
|
},
|
||||||
[](const std::size_t copy_amount) {});
|
[](const std::size_t copy_amount) {});
|
||||||
|
@ -420,7 +423,7 @@ struct Memory::Impl {
|
||||||
const std::size_t block_size) {
|
const std::size_t block_size) {
|
||||||
// dc cvac: Store to point of coherency
|
// dc cvac: Store to point of coherency
|
||||||
// CPU flush -> GPU invalidate
|
// 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);
|
return PerformCacheOperation(dest_addr, size, on_rasterizer);
|
||||||
}
|
}
|
||||||
|
@ -430,7 +433,7 @@ struct Memory::Impl {
|
||||||
const std::size_t block_size) {
|
const std::size_t block_size) {
|
||||||
// dc civac: Store to point of coherency, and invalidate from cache
|
// dc civac: Store to point of coherency, and invalidate from cache
|
||||||
// CPU flush -> GPU invalidate
|
// 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);
|
return PerformCacheOperation(dest_addr, size, on_rasterizer);
|
||||||
}
|
}
|
||||||
|
@ -767,7 +770,18 @@ struct Memory::Impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleRasterizerWrite(VAddr address, size_t size) {
|
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];
|
auto& current_area = rasterizer_write_areas[core];
|
||||||
VAddr subaddress = address >> YUZU_PAGEBITS;
|
VAddr subaddress = address >> YUZU_PAGEBITS;
|
||||||
bool do_collection = current_area.last_address == subaddress;
|
bool do_collection = current_area.last_address == subaddress;
|
||||||
|
@ -799,6 +813,7 @@ struct Memory::Impl {
|
||||||
rasterizer_read_areas{};
|
rasterizer_read_areas{};
|
||||||
std::array<GPUDirtyState, Core::Hardware::NUM_CPU_CORES> rasterizer_write_areas{};
|
std::array<GPUDirtyState, Core::Hardware::NUM_CPU_CORES> rasterizer_write_areas{};
|
||||||
std::span<Core::GPUDirtyMemoryManager> gpu_dirty_managers;
|
std::span<Core::GPUDirtyMemoryManager> gpu_dirty_managers;
|
||||||
|
std::mutex sys_core_guard;
|
||||||
};
|
};
|
||||||
|
|
||||||
Memory::Memory(Core::System& system_) : system{system_} {
|
Memory::Memory(Core::System& system_) : system{system_} {
|
||||||
|
|
|
@ -86,10 +86,7 @@ public:
|
||||||
uncommitted_operations.emplace_back(std::move(func));
|
uncommitted_operations.emplace_back(std::move(func));
|
||||||
}
|
}
|
||||||
pending_operations.emplace_back(std::move(uncommitted_operations));
|
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) {
|
if (!delay_fence) {
|
||||||
func();
|
func();
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,16 +132,12 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
|
||||||
const bool use_accelerated =
|
const bool use_accelerated =
|
||||||
rasterizer.AccelerateDisplay(*framebuffer, framebuffer_addr, framebuffer->stride);
|
rasterizer.AccelerateDisplay(*framebuffer, framebuffer_addr, framebuffer->stride);
|
||||||
const bool is_srgb = use_accelerated && screen_info.is_srgb;
|
const bool is_srgb = use_accelerated && screen_info.is_srgb;
|
||||||
|
|
||||||
{
|
|
||||||
std::scoped_lock lock{rasterizer.LockCaches()};
|
|
||||||
RenderScreenshot(*framebuffer, use_accelerated);
|
RenderScreenshot(*framebuffer, use_accelerated);
|
||||||
|
|
||||||
Frame* frame = present_manager.GetRenderFrame();
|
Frame* frame = present_manager.GetRenderFrame();
|
||||||
blit_screen.DrawToSwapchain(frame, *framebuffer, use_accelerated, is_srgb);
|
blit_screen.DrawToSwapchain(frame, *framebuffer, use_accelerated, is_srgb);
|
||||||
scheduler.Flush(*frame->render_ready);
|
scheduler.Flush(*frame->render_ready);
|
||||||
present_manager.Present(frame);
|
present_manager.Present(frame);
|
||||||
}
|
|
||||||
|
|
||||||
gpu.RendererFrameEndNotify();
|
gpu.RendererFrameEndNotify();
|
||||||
rasterizer.TickFrame();
|
rasterizer.TickFrame();
|
||||||
|
|
|
@ -199,7 +199,7 @@ void RasterizerVulkan::PrepareDraw(bool is_indexed, Func&& draw_func) {
|
||||||
if (!pipeline) {
|
if (!pipeline) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::scoped_lock lock{LockCaches()};
|
std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
|
||||||
// update engine as channel may be different.
|
// update engine as channel may be different.
|
||||||
pipeline->SetEngine(maxwell3d, gpu_memory);
|
pipeline->SetEngine(maxwell3d, gpu_memory);
|
||||||
pipeline->Configure(is_indexed);
|
pipeline->Configure(is_indexed);
|
||||||
|
@ -710,7 +710,6 @@ void RasterizerVulkan::TiledCacheBarrier() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterizerVulkan::FlushCommands() {
|
void RasterizerVulkan::FlushCommands() {
|
||||||
std::scoped_lock lock{LockCaches()};
|
|
||||||
if (draw_counter == 0) {
|
if (draw_counter == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -808,7 +807,6 @@ void RasterizerVulkan::FlushWork() {
|
||||||
if ((++draw_counter & 7) != 7) {
|
if ((++draw_counter & 7) != 7) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::scoped_lock lock{LockCaches()};
|
|
||||||
if (draw_counter < DRAWS_TO_DISPATCH) {
|
if (draw_counter < DRAWS_TO_DISPATCH) {
|
||||||
// Send recorded tasks to the worker thread
|
// Send recorded tasks to the worker thread
|
||||||
scheduler.DispatchWork();
|
scheduler.DispatchWork();
|
||||||
|
@ -1507,7 +1505,7 @@ void RasterizerVulkan::UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs)
|
||||||
void RasterizerVulkan::InitializeChannel(Tegra::Control::ChannelState& channel) {
|
void RasterizerVulkan::InitializeChannel(Tegra::Control::ChannelState& channel) {
|
||||||
CreateChannel(channel);
|
CreateChannel(channel);
|
||||||
{
|
{
|
||||||
std::scoped_lock lock{LockCaches()};
|
std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
|
||||||
texture_cache.CreateChannel(channel);
|
texture_cache.CreateChannel(channel);
|
||||||
buffer_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;
|
const s32 channel_id = channel.bind_id;
|
||||||
BindToChannel(channel_id);
|
BindToChannel(channel_id);
|
||||||
{
|
{
|
||||||
std::scoped_lock lock{LockCaches()};
|
std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
|
||||||
texture_cache.BindToChannel(channel_id);
|
texture_cache.BindToChannel(channel_id);
|
||||||
buffer_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) {
|
void RasterizerVulkan::ReleaseChannel(s32 channel_id) {
|
||||||
EraseChannel(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);
|
texture_cache.EraseChannel(channel_id);
|
||||||
buffer_cache.EraseChannel(channel_id);
|
buffer_cache.EraseChannel(channel_id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,10 +133,6 @@ public:
|
||||||
|
|
||||||
void ReleaseChannel(s32 channel_id) override;
|
void ReleaseChannel(s32 channel_id) override;
|
||||||
|
|
||||||
std::scoped_lock<std::recursive_mutex, std::recursive_mutex> LockCaches() {
|
|
||||||
return std::scoped_lock{buffer_cache.mutex, texture_cache.mutex};
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr size_t MAX_TEXTURES = 192;
|
static constexpr size_t MAX_TEXTURES = 192;
|
||||||
static constexpr size_t MAX_IMAGES = 48;
|
static constexpr size_t MAX_IMAGES = 48;
|
||||||
|
|
|
@ -360,6 +360,7 @@ void Config::ReadAudioValues() {
|
||||||
qt_config->beginGroup(QStringLiteral("Audio"));
|
qt_config->beginGroup(QStringLiteral("Audio"));
|
||||||
|
|
||||||
ReadCategory(Settings::Category::Audio);
|
ReadCategory(Settings::Category::Audio);
|
||||||
|
ReadCategory(Settings::Category::UiAudio);
|
||||||
|
|
||||||
qt_config->endGroup();
|
qt_config->endGroup();
|
||||||
}
|
}
|
||||||
|
@ -900,6 +901,7 @@ void Config::SaveAudioValues() {
|
||||||
qt_config->beginGroup(QStringLiteral("Audio"));
|
qt_config->beginGroup(QStringLiteral("Audio"));
|
||||||
|
|
||||||
WriteCategory(Settings::Category::Audio);
|
WriteCategory(Settings::Category::Audio);
|
||||||
|
WriteCategory(Settings::Category::UiAudio);
|
||||||
|
|
||||||
qt_config->endGroup();
|
qt_config->endGroup();
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,17 +38,21 @@ void ConfigureAudio::Setup(const ConfigurationShared::Builder& builder) {
|
||||||
|
|
||||||
std::map<u32, QWidget*> hold;
|
std::map<u32, QWidget*> hold;
|
||||||
|
|
||||||
auto push = [&](Settings::Category category) {
|
auto push_settings = [&](Settings::Category category) {
|
||||||
for (auto* setting : Settings::values.linkage.by_category[category]) {
|
for (auto* setting : Settings::values.linkage.by_category[category]) {
|
||||||
settings.push_back(setting);
|
settings.push_back(setting);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto push_ui_settings = [&](Settings::Category category) {
|
||||||
for (auto* setting : UISettings::values.linkage.by_category[category]) {
|
for (auto* setting : UISettings::values.linkage.by_category[category]) {
|
||||||
settings.push_back(setting);
|
settings.push_back(setting);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
push(Settings::Category::Audio);
|
push_settings(Settings::Category::Audio);
|
||||||
push(Settings::Category::SystemAudio);
|
push_settings(Settings::Category::SystemAudio);
|
||||||
|
push_ui_settings(Settings::Category::UiAudio);
|
||||||
|
|
||||||
for (auto* setting : settings) {
|
for (auto* setting : settings) {
|
||||||
auto* widget = builder.BuildWidget(setting, apply_funcs);
|
auto* widget = builder.BuildWidget(setting, apply_funcs);
|
||||||
|
|
|
@ -1065,12 +1065,6 @@ void GMainWindow::InitializeWidgets() {
|
||||||
volume_slider->setObjectName(QStringLiteral("volume_slider"));
|
volume_slider->setObjectName(QStringLiteral("volume_slider"));
|
||||||
volume_slider->setMaximum(200);
|
volume_slider->setMaximum(200);
|
||||||
volume_slider->setPageStep(5);
|
volume_slider->setPageStep(5);
|
||||||
connect(volume_slider, &QSlider::valueChanged, this, [this](int percentage) {
|
|
||||||
Settings::values.audio_muted = false;
|
|
||||||
const auto volume = static_cast<u8>(percentage);
|
|
||||||
Settings::values.volume.SetValue(volume);
|
|
||||||
UpdateVolumeUI();
|
|
||||||
});
|
|
||||||
volume_popup->layout()->addWidget(volume_slider);
|
volume_popup->layout()->addWidget(volume_slider);
|
||||||
|
|
||||||
volume_button = new VolumeButton();
|
volume_button = new VolumeButton();
|
||||||
|
@ -1078,6 +1072,12 @@ void GMainWindow::InitializeWidgets() {
|
||||||
volume_button->setFocusPolicy(Qt::NoFocus);
|
volume_button->setFocusPolicy(Qt::NoFocus);
|
||||||
volume_button->setCheckable(true);
|
volume_button->setCheckable(true);
|
||||||
UpdateVolumeUI();
|
UpdateVolumeUI();
|
||||||
|
connect(volume_slider, &QSlider::valueChanged, this, [this](int percentage) {
|
||||||
|
Settings::values.audio_muted = false;
|
||||||
|
const auto volume = static_cast<u8>(percentage);
|
||||||
|
Settings::values.volume.SetValue(volume);
|
||||||
|
UpdateVolumeUI();
|
||||||
|
});
|
||||||
connect(volume_button, &QPushButton::clicked, this, [&] {
|
connect(volume_button, &QPushButton::clicked, this, [&] {
|
||||||
UpdateVolumeUI();
|
UpdateVolumeUI();
|
||||||
volume_popup->setVisible(!volume_popup->isVisible());
|
volume_popup->setVisible(!volume_popup->isVisible());
|
||||||
|
|
|
@ -109,9 +109,13 @@ struct Values {
|
||||||
Settings::Specialization::Default,
|
Settings::Specialization::Default,
|
||||||
true,
|
true,
|
||||||
true};
|
true};
|
||||||
Setting<bool> mute_when_in_background{
|
Setting<bool> mute_when_in_background{linkage,
|
||||||
linkage, false, "muteWhenInBackground", Category::Audio, Settings::Specialization::Default,
|
false,
|
||||||
true, true};
|
"muteWhenInBackground",
|
||||||
|
Category::UiAudio,
|
||||||
|
Settings::Specialization::Default,
|
||||||
|
true,
|
||||||
|
true};
|
||||||
Setting<bool> hide_mouse{
|
Setting<bool> hide_mouse{
|
||||||
linkage, true, "hideInactiveMouse", Category::UiGeneral, Settings::Specialization::Default,
|
linkage, true, "hideInactiveMouse", Category::UiGeneral, Settings::Specialization::Default,
|
||||||
true, true};
|
true, true};
|
||||||
|
|
Loading…
Reference in a new issue