early-access version 2865

This commit is contained in:
pineappleEA 2022-07-28 04:08:41 +02:00
parent c1feb74617
commit 9533f7c018
8 changed files with 81 additions and 34 deletions

View file

@ -1,7 +1,7 @@
yuzu emulator early access yuzu emulator early access
============= =============
This is the source code for early-access 2864. This is the source code for early-access 2865.
## Legal Notice ## Legal Notice

View file

@ -339,7 +339,7 @@ void CommandBuffer::GenerateDepopPrepareCommand(const s32 node_id, const VoiceSt
cmd.previous_samples = memory_pool->Translate(CpuAddr(voice_state.previous_samples.data()), cmd.previous_samples = memory_pool->Translate(CpuAddr(voice_state.previous_samples.data()),
MaxMixBuffers * sizeof(s32)); MaxMixBuffers * sizeof(s32));
cmd.buffer_count = buffer_count; cmd.buffer_count = buffer_count;
cmd.depop_buffer = memory_pool->Translate(CpuAddr(buffer.data()), buffer_count * sizeof(s32)); cmd.depop_buffer = memory_pool->Translate(CpuAddr(buffer.data()), buffer.size_bytes());
GenerateEnd<DepopPrepareCommand>(cmd); GenerateEnd<DepopPrepareCommand>(cmd);
} }

View file

@ -19,7 +19,7 @@ void DepopPrepareCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor
void DepopPrepareCommand::Process(const ADSP::CommandListProcessor& processor) { void DepopPrepareCommand::Process(const ADSP::CommandListProcessor& processor) {
auto samples{reinterpret_cast<s32*>(previous_samples)}; auto samples{reinterpret_cast<s32*>(previous_samples)};
auto buffer{std::span(reinterpret_cast<s32*>(depop_buffer), buffer_count)}; auto buffer{reinterpret_cast<s32*>(depop_buffer)};
for (u32 i = 0; i < buffer_count; i++) { for (u32 i = 0; i < buffer_count; i++) {
if (samples[i]) { if (samples[i]) {

View file

@ -54,6 +54,10 @@ public:
is_set = false; is_set = false;
} }
[[nodiscard]] bool IsSet() {
return is_set;
}
private: private:
std::condition_variable condvar; std::condition_variable condvar;
std::mutex mutex; std::mutex mutex;

View file

@ -243,17 +243,17 @@ std::optional<s64> CoreTiming::Advance() {
basic_lock.lock(); basic_lock.lock();
if (evt.reschedule_time != 0) { if (evt.reschedule_time != 0) {
// If this event was scheduled into a pause, its time now is going to be way behind.
// Re-set this event to continue from the end of the pause.
auto next_time{evt.time + evt.reschedule_time};
if (evt.time < pause_end_time) {
next_time = pause_end_time + evt.reschedule_time;
}
const auto next_schedule_time{new_schedule_time.has_value() const auto next_schedule_time{new_schedule_time.has_value()
? new_schedule_time.value().count() ? new_schedule_time.value().count()
: evt.reschedule_time}; : evt.reschedule_time};
// If this event was scheduled into a pause, its time now is going to be way behind.
// Re-set this event to continue from the end of the pause.
auto next_time{evt.time + next_schedule_time};
if (evt.time < pause_end_time) {
next_time = pause_end_time + next_schedule_time;
}
event_queue.emplace_back( event_queue.emplace_back(
Event{next_time, event_fifo_id++, evt.user_data, evt.type, next_schedule_time}); Event{next_time, event_fifo_id++, evt.user_data, evt.type, next_schedule_time});
std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>()); std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>());
@ -264,8 +264,7 @@ std::optional<s64> CoreTiming::Advance() {
} }
if (!event_queue.empty()) { if (!event_queue.empty()) {
const s64 next_time = event_queue.front().time - global_timer; return event_queue.front().time;
return next_time;
} else { } else {
return std::nullopt; return std::nullopt;
} }
@ -278,11 +277,28 @@ void CoreTiming::ThreadLoop() {
paused_set = false; paused_set = false;
const auto next_time = Advance(); const auto next_time = Advance();
if (next_time) { if (next_time) {
if (*next_time > 0) { // There are more events left in the queue, sleep until the next event.
std::chrono::nanoseconds next_time_ns = std::chrono::nanoseconds(*next_time); const auto diff_ns{*next_time - GetGlobalTimeNs().count()};
event.WaitFor(next_time_ns); if (diff_ns > 0) {
// Only try to sleep if the remaining time is >= 1ms. Take off 500 microseconds
// from the target time to account for possible over-sleeping, and spin the
// remaining.
const auto sleep_time_ns{diff_ns - 500LL * 1'000LL};
const auto sleep_time_ms{sleep_time_ns / 1'000'000LL};
if (sleep_time_ms >= 1) {
event.WaitFor(std::chrono::nanoseconds(sleep_time_ns));
}
const auto end_time{std::chrono::nanoseconds(*next_time)};
while (!paused && !event.IsSet() && GetGlobalTimeNs() < end_time) {
}
if (event.IsSet()) {
event.Reset();
}
} }
} else { } else {
// Queue is empty, wait until another event is scheduled and signals us to continue.
wait_set = true; wait_set = true;
event.Wait(); event.Wait();
} }

View file

@ -40,20 +40,16 @@ void NVFlinger::SplitVSync(std::stop_token stop_token) {
Common::SetCurrentThreadName(name.c_str()); Common::SetCurrentThreadName(name.c_str());
Common::SetCurrentThreadPriority(Common::ThreadPriority::High); Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
s64 delay = 0;
while (!stop_token.stop_requested()) { while (!stop_token.stop_requested()) {
vsync_signal.wait(false);
vsync_signal.store(false);
guard->lock(); guard->lock();
const s64 time_start = system.CoreTiming().GetGlobalTimeNs().count();
Compose(); Compose();
const auto ticks = GetNextTicks();
const s64 time_end = system.CoreTiming().GetGlobalTimeNs().count();
const s64 time_passed = time_end - time_start;
const s64 next_time = std::max<s64>(0, ticks - time_passed - delay);
guard->unlock(); guard->unlock();
if (next_time > 0) {
std::this_thread::sleep_for(std::chrono::nanoseconds{next_time});
}
delay = (system.CoreTiming().GetGlobalTimeNs().count() - time_end) - next_time;
} }
} }
@ -68,27 +64,41 @@ NVFlinger::NVFlinger(Core::System& system_, HosBinderDriverServer& hos_binder_dr
guard = std::make_shared<std::mutex>(); guard = std::make_shared<std::mutex>();
// Schedule the screen composition events // Schedule the screen composition events
composition_event = Core::Timing::CreateEvent( multi_composition_event = Core::Timing::CreateEvent(
"ScreenComposition",
[this](std::uintptr_t, s64 time,
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
vsync_signal.store(true);
vsync_signal.notify_all();
return std::chrono::nanoseconds(GetNextTicks());
});
single_composition_event = Core::Timing::CreateEvent(
"ScreenComposition", "ScreenComposition",
[this](std::uintptr_t, s64 time, [this](std::uintptr_t, s64 time,
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
const auto lock_guard = Lock(); const auto lock_guard = Lock();
Compose(); Compose();
return std::max(std::chrono::nanoseconds::zero(), return std::chrono::nanoseconds(GetNextTicks());
std::chrono::nanoseconds(GetNextTicks()) - ns_late);
}); });
if (system.IsMulticore()) { if (system.IsMulticore()) {
system.CoreTiming().ScheduleLoopingEvent(frame_ns, frame_ns, multi_composition_event);
vsync_thread = std::jthread([this](std::stop_token token) { SplitVSync(token); }); vsync_thread = std::jthread([this](std::stop_token token) { SplitVSync(token); });
} else { } else {
system.CoreTiming().ScheduleLoopingEvent(frame_ns, frame_ns, composition_event); system.CoreTiming().ScheduleLoopingEvent(frame_ns, frame_ns, single_composition_event);
} }
} }
NVFlinger::~NVFlinger() { NVFlinger::~NVFlinger() {
if (!system.IsMulticore()) { if (system.IsMulticore()) {
system.CoreTiming().UnscheduleEvent(composition_event, 0); system.CoreTiming().UnscheduleEvent(multi_composition_event, {});
vsync_thread.request_stop();
vsync_signal.store(true);
vsync_signal.notify_all();
} else {
system.CoreTiming().UnscheduleEvent(single_composition_event, {});
} }
for (auto& display : displays) { for (auto& display : displays) {

View file

@ -127,12 +127,15 @@ private:
u32 swap_interval = 1; u32 swap_interval = 1;
/// Event that handles screen composition. /// Event that handles screen composition.
std::shared_ptr<Core::Timing::EventType> composition_event; std::shared_ptr<Core::Timing::EventType> multi_composition_event;
std::shared_ptr<Core::Timing::EventType> single_composition_event;
std::shared_ptr<std::mutex> guard; std::shared_ptr<std::mutex> guard;
Core::System& system; Core::System& system;
std::atomic<bool> vsync_signal;
std::jthread vsync_thread; std::jthread vsync_thread;
KernelHelpers::ServiceContext service_context; KernelHelpers::ServiceContext service_context;

View file

@ -1077,12 +1077,26 @@ void GMainWindow::InitializeHotkeys() {
[] { Settings::values.audio_muted = !Settings::values.audio_muted; }); [] { Settings::values.audio_muted = !Settings::values.audio_muted; });
connect_shortcut(QStringLiteral("Audio Volume Down"), [] { connect_shortcut(QStringLiteral("Audio Volume Down"), [] {
const auto current_volume = static_cast<int>(Settings::values.volume.GetValue()); const auto current_volume = static_cast<int>(Settings::values.volume.GetValue());
const auto new_volume = std::max(current_volume - 5, 0); int step = 5;
if (current_volume <= 30) {
step = 2;
}
if (current_volume <= 6) {
step = 1;
}
const auto new_volume = std::max(current_volume - step, 0);
Settings::values.volume.SetValue(static_cast<u8>(new_volume)); Settings::values.volume.SetValue(static_cast<u8>(new_volume));
}); });
connect_shortcut(QStringLiteral("Audio Volume Up"), [] { connect_shortcut(QStringLiteral("Audio Volume Up"), [] {
const auto current_volume = static_cast<int>(Settings::values.volume.GetValue()); const auto current_volume = static_cast<int>(Settings::values.volume.GetValue());
const auto new_volume = std::min(current_volume + 5, 100); int step = 5;
if (current_volume < 30) {
step = 2;
}
if (current_volume < 6) {
step = 1;
}
const auto new_volume = std::min(current_volume + step, 100);
Settings::values.volume.SetValue(static_cast<u8>(new_volume)); Settings::values.volume.SetValue(static_cast<u8>(new_volume));
}); });
connect_shortcut(QStringLiteral("Toggle Framerate Limit"), [] { connect_shortcut(QStringLiteral("Toggle Framerate Limit"), [] {