early-access version 3524

This commit is contained in:
pineappleEA
2023-04-23 14:05:41 +02:00
parent ab28951bc0
commit 4a571b3057
49 changed files with 2542 additions and 1485 deletions

View File

@@ -16,7 +16,6 @@ add_library(core STATIC
core.h
core_timing.cpp
core_timing.h
core_timing_util.h
cpu_manager.cpp
cpu_manager.h
crypto/aes_util.cpp

View File

@@ -16,7 +16,6 @@
#include "common/microprofile.h"
#include "core/core_timing.h"
#include "core/core_timing_util.h"
#include "core/hardware_properties.h"
namespace Core::Timing {
@@ -45,9 +44,7 @@ struct CoreTiming::Event {
}
};
CoreTiming::CoreTiming()
: cpu_clock{Common::CreateBestMatchingClock(Hardware::BASE_CLOCK_RATE, Hardware::CNTFREQ)},
event_clock{Common::CreateStandardWallClock(Hardware::BASE_CLOCK_RATE, Hardware::CNTFREQ)} {}
CoreTiming::CoreTiming() : clock{Common::CreateOptimalClock()} {}
CoreTiming::~CoreTiming() {
Reset();
@@ -180,7 +177,7 @@ void CoreTiming::AddTicks(u64 ticks_to_add) {
void CoreTiming::Idle() {
if (!event_queue.empty()) {
const u64 next_event_time = event_queue.front().time;
const u64 next_ticks = nsToCycles(std::chrono::nanoseconds(next_event_time)) + 10U;
const u64 next_ticks = Common::WallClock::NSToCNTPCT(next_event_time) + 10U;
if (next_ticks > ticks) {
ticks = next_ticks;
}
@@ -193,18 +190,11 @@ void CoreTiming::ResetTicks() {
downcount = MAX_SLICE_LENGTH;
}
u64 CoreTiming::GetCPUTicks() const {
if (is_multicore) [[likely]] {
return cpu_clock->GetCPUCycles();
}
return ticks;
}
u64 CoreTiming::GetClockTicks() const {
if (is_multicore) [[likely]] {
return cpu_clock->GetClockCycles();
return clock->GetCNTPCT();
}
return CpuCyclesToClockCycles(ticks);
return ticks;
}
std::optional<s64> CoreTiming::Advance() {
@@ -297,9 +287,7 @@ void CoreTiming::ThreadLoop() {
}
paused_set = true;
event_clock->Pause(true);
pause_event.Wait();
event_clock->Pause(false);
}
}
@@ -315,25 +303,18 @@ void CoreTiming::Reset() {
has_started = false;
}
std::chrono::nanoseconds CoreTiming::GetCPUTimeNs() const {
if (is_multicore) [[likely]] {
return cpu_clock->GetTimeNS();
}
return CyclesToNs(ticks);
}
std::chrono::nanoseconds CoreTiming::GetGlobalTimeNs() const {
if (is_multicore) [[likely]] {
return event_clock->GetTimeNS();
return clock->GetTimeNS();
}
return CyclesToNs(ticks);
return std::chrono::nanoseconds{Common::WallClock::CNTPCTToNS(ticks)};
}
std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const {
if (is_multicore) [[likely]] {
return event_clock->GetTimeUS();
return clock->GetTimeUS();
}
return CyclesToUs(ticks);
return std::chrono::microseconds{Common::WallClock::CNTPCTToUS(ticks)};
}
} // namespace Core::Timing

View File

@@ -116,15 +116,9 @@ public:
return downcount;
}
/// Returns current time in emulated CPU cycles
u64 GetCPUTicks() const;
/// Returns current time in emulated in Clock cycles
/// Returns the current CNTPCT tick value.
u64 GetClockTicks() const;
/// Returns current time in nanoseconds.
std::chrono::nanoseconds GetCPUTimeNs() const;
/// Returns current time in microseconds.
std::chrono::microseconds GetGlobalTimeUs() const;
@@ -142,8 +136,7 @@ private:
void Reset();
std::unique_ptr<Common::WallClock> cpu_clock;
std::unique_ptr<Common::WallClock> event_clock;
std::unique_ptr<Common::WallClock> clock;
s64 global_timer = 0;

View File

@@ -184,7 +184,8 @@ u64 KScheduler::UpdateHighestPriorityThread(KThread* highest_thread) {
prev_highest_thread != highest_thread) [[likely]] {
if (prev_highest_thread != nullptr) [[likely]] {
IncrementScheduledCount(prev_highest_thread);
prev_highest_thread->SetLastScheduledTick(m_kernel.System().CoreTiming().GetCPUTicks());
prev_highest_thread->SetLastScheduledTick(
m_kernel.System().CoreTiming().GetClockTicks());
}
if (m_state.should_count_idle) {
if (highest_thread != nullptr) [[likely]] {
@@ -351,7 +352,7 @@ void KScheduler::SwitchThread(KThread* next_thread) {
// Update the CPU time tracking variables.
const s64 prev_tick = m_last_context_switch_time;
const s64 cur_tick = m_kernel.System().CoreTiming().GetCPUTicks();
const s64 cur_tick = m_kernel.System().CoreTiming().GetClockTicks();
const s64 tick_diff = cur_tick - prev_tick;
cur_thread->AddCpuTime(m_core_id, tick_diff);
if (cur_process != nullptr) {

View File

@@ -199,9 +199,9 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
if (same_thread && info_sub_id == 0xFFFFFFFFFFFFFFFF) {
const u64 thread_ticks = current_thread->GetCpuTime();
out_ticks = thread_ticks + (core_timing.GetCPUTicks() - prev_ctx_ticks);
out_ticks = thread_ticks + (core_timing.GetClockTicks() - prev_ctx_ticks);
} else if (same_thread && info_sub_id == system.Kernel().CurrentPhysicalCoreIndex()) {
out_ticks = core_timing.GetCPUTicks() - prev_ctx_ticks;
out_ticks = core_timing.GetClockTicks() - prev_ctx_ticks;
}
*result = out_ticks;

View File

@@ -5,7 +5,6 @@
#include "common/settings.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/core_timing_util.h"
#include "core/hid/hid_types.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_readable_event.h"

View File

@@ -92,6 +92,14 @@ Status BufferQueueConsumer::AcquireBuffer(BufferItem* out_buffer,
LOG_DEBUG(Service_Nvnflinger, "acquiring slot={}", slot);
// If the front buffer is still being tracked, update its slot state
if (core->StillTracking(*front)) {
slots[slot].acquire_called = true;
slots[slot].needs_cleanup_on_release = false;
slots[slot].buffer_state = BufferState::Acquired;
slots[slot].fence = Fence::NoFence();
}
// If the buffer has previously been acquired by the consumer, set graphic_buffer to nullptr to
// avoid unnecessarily remapping this buffer on the consumer side.
if (out_buffer->acquire_called) {
@@ -134,13 +142,29 @@ Status BufferQueueConsumer::ReleaseBuffer(s32 slot, u64 frame_number, const Fenc
++current;
}
slots[slot].buffer_state = BufferState::Free;
if (slots[slot].buffer_state == BufferState::Acquired) {
slots[slot].fence = release_fence;
slots[slot].buffer_state = BufferState::Free;
nvmap.FreeHandle(slots[slot].graphic_buffer->BufferId(), true);
nvmap.FreeHandle(slots[slot].graphic_buffer->BufferId(), true);
listener = core->connected_producer_listener;
listener = core->connected_producer_listener;
LOG_DEBUG(Service_Nvnflinger, "releasing slot {}", slot);
LOG_DEBUG(Service_Nvnflinger, "releasing slot {}", slot);
} else if (slots[slot].needs_cleanup_on_release) {
LOG_DEBUG(Service_Nvnflinger, "releasing a stale buffer slot {} (state = {})", slot,
slots[slot].buffer_state);
slots[slot].needs_cleanup_on_release = false;
return Status::StaleBufferSlot;
} else {
LOG_ERROR(Service_Nvnflinger,
"attempted to release buffer slot {} but its state was {}", slot,
slots[slot].buffer_state);
return Status::BadValue;
}
core->SignalDequeueCondition();
}

View File

@@ -86,6 +86,10 @@ void BufferQueueCore::FreeBufferLocked(s32 slot) {
slots[slot].graphic_buffer.reset();
if (slots[slot].buffer_state == BufferState::Acquired) {
slots[slot].needs_cleanup_on_release = true;
}
slots[slot].buffer_state = BufferState::Free;
slots[slot].frame_number = UINT32_MAX;
slots[slot].acquire_called = false;

View File

@@ -31,6 +31,7 @@ struct BufferSlot final {
u64 frame_number{};
Fence fence;
bool acquire_called{};
bool needs_cleanup_on_release{};
bool attached_by_consumer{};
bool is_preallocated{};
};

View File

@@ -46,11 +46,8 @@ void Nvnflinger::SplitVSync(std::stop_token stop_token) {
vsync_signal.wait(false);
vsync_signal.store(false);
guard->lock();
const auto lock_guard = Lock();
Compose();
guard->unlock();
}
}
@@ -70,7 +67,9 @@ Nvnflinger::Nvnflinger(Core::System& system_, HosBinderDriverServer& hos_binder_
[this](std::uintptr_t, s64 time,
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
vsync_signal.store(true);
vsync_signal.notify_all();
const auto lock_guard = Lock();
vsync_signal.notify_one();
return std::chrono::nanoseconds(GetNextTicks());
});
@@ -267,8 +266,9 @@ void Nvnflinger::Compose() {
SCOPE_EXIT({ display.SignalVSyncEvent(); });
// Don't do anything for displays without layers.
if (!display.HasLayers())
if (!display.HasLayers()) {
continue;
}
// TODO(Subv): Support more than 1 layer.
VI::Layer& layer = display.GetLayer(0);

View File

@@ -3,6 +3,8 @@
#pragma once
#include <ratio>
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "common/uuid.h"
@@ -62,18 +64,19 @@ static_assert(std::is_trivially_copyable_v<SystemClockContext>,
/// https://switchbrew.org/wiki/Glue_services#TimeSpanType
struct TimeSpanType {
s64 nanoseconds{};
static constexpr s64 ns_per_second{1000000000ULL};
s64 ToSeconds() const {
return nanoseconds / ns_per_second;
return nanoseconds / std::nano::den;
}
static TimeSpanType FromSeconds(s64 seconds) {
return {seconds * ns_per_second};
return {seconds * std::nano::den};
}
static TimeSpanType FromTicks(u64 ticks, u64 frequency) {
return FromSeconds(static_cast<s64>(ticks) / static_cast<s64>(frequency));
template <u64 Frequency>
static TimeSpanType FromTicks(u64 ticks) {
using TicksToNSRatio = std::ratio<std::nano::den, Frequency>;
return {static_cast<s64>(ticks * TicksToNSRatio::num / TicksToNSRatio::den)};
}
};
static_assert(sizeof(TimeSpanType) == 8, "TimeSpanType is incorrect size");

View File

@@ -10,7 +10,7 @@ namespace Service::Time::Clock {
TimeSpanType StandardSteadyClockCore::GetCurrentRawTimePoint(Core::System& system) {
const TimeSpanType ticks_time_span{
TimeSpanType::FromTicks(system.CoreTiming().GetClockTicks(), Core::Hardware::CNTFREQ)};
TimeSpanType::FromTicks<Core::Hardware::CNTFREQ>(system.CoreTiming().GetClockTicks())};
TimeSpanType raw_time_point{setup_value.nanoseconds + ticks_time_span.nanoseconds};
if (raw_time_point.nanoseconds < cached_raw_time_point.nanoseconds) {

View File

@@ -10,7 +10,7 @@ namespace Service::Time::Clock {
SteadyClockTimePoint TickBasedSteadyClockCore::GetTimePoint(Core::System& system) {
const TimeSpanType ticks_time_span{
TimeSpanType::FromTicks(system.CoreTiming().GetClockTicks(), Core::Hardware::CNTFREQ)};
TimeSpanType::FromTicks<Core::Hardware::CNTFREQ>(system.CoreTiming().GetClockTicks())};
return {ticks_time_span.ToSeconds(), GetClockSourceId()};
}

View File

@@ -240,8 +240,8 @@ void Module::Interface::CalculateMonotonicSystemClockBaseTimePoint(HLERequestCon
const auto current_time_point{steady_clock_core.GetCurrentTimePoint(system)};
if (current_time_point.clock_source_id == context.steady_time_point.clock_source_id) {
const auto ticks{Clock::TimeSpanType::FromTicks(system.CoreTiming().GetClockTicks(),
Core::Hardware::CNTFREQ)};
const auto ticks{Clock::TimeSpanType::FromTicks<Core::Hardware::CNTFREQ>(
system.CoreTiming().GetClockTicks())};
const s64 base_time_point{context.offset + current_time_point.time_point -
ticks.ToSeconds()};
IPC::ResponseBuilder rb{ctx, (sizeof(s64) / 4) + 2};

View File

@@ -21,8 +21,9 @@ SharedMemory::~SharedMemory() = default;
void SharedMemory::SetupStandardSteadyClock(const Common::UUID& clock_source_id,
Clock::TimeSpanType current_time_point) {
const Clock::TimeSpanType ticks_time_span{Clock::TimeSpanType::FromTicks(
system.CoreTiming().GetClockTicks(), Core::Hardware::CNTFREQ)};
const Clock::TimeSpanType ticks_time_span{
Clock::TimeSpanType::FromTicks<Core::Hardware::CNTFREQ>(
system.CoreTiming().GetClockTicks())};
const Clock::SteadyClockContext context{
static_cast<u64>(current_time_point.nanoseconds - ticks_time_span.nanoseconds),
clock_source_id};