mirror of
https://github.com/yuzu-emu/yuzu-android.git
synced 2025-06-25 17:27:52 -05:00
Merge pull request #3955 from FernandoS27/prometheus-2b
Remake Kernel Scheduling, CPU Management & Boot Management (Prometheus)
This commit is contained in:
@ -23,7 +23,7 @@ void Controller_DebugPad::OnRelease() {}
|
||||
|
||||
void Controller_DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
|
||||
std::size_t size) {
|
||||
shared_memory.header.timestamp = core_timing.GetTicks();
|
||||
shared_memory.header.timestamp = core_timing.GetCPUTicks();
|
||||
shared_memory.header.total_entry_count = 17;
|
||||
|
||||
if (!IsControllerActivated()) {
|
||||
|
@ -19,7 +19,7 @@ void Controller_Gesture::OnRelease() {}
|
||||
|
||||
void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
|
||||
std::size_t size) {
|
||||
shared_memory.header.timestamp = core_timing.GetTicks();
|
||||
shared_memory.header.timestamp = core_timing.GetCPUTicks();
|
||||
shared_memory.header.total_entry_count = 17;
|
||||
|
||||
if (!IsControllerActivated()) {
|
||||
|
@ -21,7 +21,7 @@ void Controller_Keyboard::OnRelease() {}
|
||||
|
||||
void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
|
||||
std::size_t size) {
|
||||
shared_memory.header.timestamp = core_timing.GetTicks();
|
||||
shared_memory.header.timestamp = core_timing.GetCPUTicks();
|
||||
shared_memory.header.total_entry_count = 17;
|
||||
|
||||
if (!IsControllerActivated()) {
|
||||
|
@ -19,7 +19,7 @@ void Controller_Mouse::OnRelease() {}
|
||||
|
||||
void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
|
||||
std::size_t size) {
|
||||
shared_memory.header.timestamp = core_timing.GetTicks();
|
||||
shared_memory.header.timestamp = core_timing.GetCPUTicks();
|
||||
shared_memory.header.total_entry_count = 17;
|
||||
|
||||
if (!IsControllerActivated()) {
|
||||
|
@ -328,7 +328,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
||||
const auto& last_entry =
|
||||
main_controller->npad[main_controller->common.last_entry_index];
|
||||
|
||||
main_controller->common.timestamp = core_timing.GetTicks();
|
||||
main_controller->common.timestamp = core_timing.GetCPUTicks();
|
||||
main_controller->common.last_entry_index =
|
||||
(main_controller->common.last_entry_index + 1) % 17;
|
||||
|
||||
|
@ -23,7 +23,7 @@ void Controller_Stubbed::OnUpdate(const Core::Timing::CoreTiming& core_timing, u
|
||||
}
|
||||
|
||||
CommonHeader header{};
|
||||
header.timestamp = core_timing.GetTicks();
|
||||
header.timestamp = core_timing.GetCPUTicks();
|
||||
header.total_entry_count = 17;
|
||||
header.entry_count = 0;
|
||||
header.last_entry_index = 0;
|
||||
|
@ -22,7 +22,7 @@ void Controller_Touchscreen::OnRelease() {}
|
||||
|
||||
void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
|
||||
std::size_t size) {
|
||||
shared_memory.header.timestamp = core_timing.GetTicks();
|
||||
shared_memory.header.timestamp = core_timing.GetCPUTicks();
|
||||
shared_memory.header.total_entry_count = 17;
|
||||
|
||||
if (!IsControllerActivated()) {
|
||||
@ -49,7 +49,7 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin
|
||||
touch_entry.diameter_x = Settings::values.touchscreen.diameter_x;
|
||||
touch_entry.diameter_y = Settings::values.touchscreen.diameter_y;
|
||||
touch_entry.rotation_angle = Settings::values.touchscreen.rotation_angle;
|
||||
const u64 tick = core_timing.GetTicks();
|
||||
const u64 tick = core_timing.GetCPUTicks();
|
||||
touch_entry.delta_time = tick - last_touch;
|
||||
last_touch = tick;
|
||||
touch_entry.finger = Settings::values.touchscreen.finger;
|
||||
|
@ -20,7 +20,7 @@ void Controller_XPad::OnRelease() {}
|
||||
void Controller_XPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
|
||||
std::size_t size) {
|
||||
for (auto& xpad_entry : shared_memory.shared_memory_entries) {
|
||||
xpad_entry.header.timestamp = core_timing.GetTicks();
|
||||
xpad_entry.header.timestamp = core_timing.GetCPUTicks();
|
||||
xpad_entry.header.total_entry_count = 17;
|
||||
|
||||
if (!IsControllerActivated()) {
|
||||
|
@ -39,11 +39,9 @@ namespace Service::HID {
|
||||
|
||||
// Updating period for each HID device.
|
||||
// TODO(ogniK): Find actual polling rate of hid
|
||||
constexpr s64 pad_update_ticks = static_cast<s64>(Core::Hardware::BASE_CLOCK_RATE / 66);
|
||||
[[maybe_unused]] constexpr s64 accelerometer_update_ticks =
|
||||
static_cast<s64>(Core::Hardware::BASE_CLOCK_RATE / 100);
|
||||
[[maybe_unused]] constexpr s64 gyroscope_update_ticks =
|
||||
static_cast<s64>(Core::Hardware::BASE_CLOCK_RATE / 100);
|
||||
constexpr s64 pad_update_ticks = static_cast<s64>(1000000000 / 66);
|
||||
[[maybe_unused]] constexpr s64 accelerometer_update_ticks = static_cast<s64>(1000000000 / 100);
|
||||
[[maybe_unused]] constexpr s64 gyroscope_update_ticks = static_cast<s64>(1000000000 / 100);
|
||||
constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000;
|
||||
|
||||
IAppletResource::IAppletResource(Core::System& system)
|
||||
@ -78,8 +76,8 @@ IAppletResource::IAppletResource(Core::System& system)
|
||||
|
||||
// Register update callbacks
|
||||
pad_update_event =
|
||||
Core::Timing::CreateEvent("HID::UpdatePadCallback", [this](u64 userdata, s64 cycles_late) {
|
||||
UpdateControllers(userdata, cycles_late);
|
||||
Core::Timing::CreateEvent("HID::UpdatePadCallback", [this](u64 userdata, s64 ns_late) {
|
||||
UpdateControllers(userdata, ns_late);
|
||||
});
|
||||
|
||||
// TODO(shinyquagsire23): Other update callbacks? (accel, gyro?)
|
||||
@ -109,7 +107,7 @@ void IAppletResource::GetSharedMemoryHandle(Kernel::HLERequestContext& ctx) {
|
||||
rb.PushCopyObjects(shared_mem);
|
||||
}
|
||||
|
||||
void IAppletResource::UpdateControllers(u64 userdata, s64 cycles_late) {
|
||||
void IAppletResource::UpdateControllers(u64 userdata, s64 ns_late) {
|
||||
auto& core_timing = system.CoreTiming();
|
||||
|
||||
const bool should_reload = Settings::values.is_device_reload_pending.exchange(false);
|
||||
@ -120,7 +118,7 @@ void IAppletResource::UpdateControllers(u64 userdata, s64 cycles_late) {
|
||||
controller->OnUpdate(core_timing, shared_mem->GetPointer(), SHARED_MEMORY_SIZE);
|
||||
}
|
||||
|
||||
core_timing.ScheduleEvent(pad_update_ticks - cycles_late, pad_update_event);
|
||||
core_timing.ScheduleEvent(pad_update_ticks - ns_late, pad_update_event);
|
||||
}
|
||||
|
||||
class IActiveVibrationDeviceList final : public ServiceFramework<IActiveVibrationDeviceList> {
|
||||
|
@ -98,7 +98,7 @@ void IRS::GetImageTransferProcessorState(Kernel::HLERequestContext& ctx) {
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 5};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushRaw<u64>(system.CoreTiming().GetTicks());
|
||||
rb.PushRaw<u64>(system.CoreTiming().GetCPUTicks());
|
||||
rb.PushRaw<u32>(0);
|
||||
}
|
||||
|
||||
|
@ -200,8 +200,7 @@ u32 nvhost_ctrl_gpu::GetGpuTime(const std::vector<u8>& input, std::vector<u8>& o
|
||||
|
||||
IoctlGetGpuTime params{};
|
||||
std::memcpy(¶ms, input.data(), input.size());
|
||||
const auto ns = Core::Timing::CyclesToNs(system.CoreTiming().GetTicks());
|
||||
params.gpu_time = static_cast<u64_le>(ns.count());
|
||||
params.gpu_time = static_cast<u64_le>(system.CoreTiming().GetGlobalTimeNs().count());
|
||||
std::memcpy(output.data(), ¶ms, output.size());
|
||||
return 0;
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "common/logging/log.h"
|
||||
#include "common/microprofile.h"
|
||||
#include "common/scope_exit.h"
|
||||
#include "common/thread.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/core_timing_util.h"
|
||||
@ -27,8 +28,35 @@
|
||||
|
||||
namespace Service::NVFlinger {
|
||||
|
||||
constexpr s64 frame_ticks = static_cast<s64>(Core::Hardware::BASE_CLOCK_RATE / 60);
|
||||
constexpr s64 frame_ticks_30fps = static_cast<s64>(Core::Hardware::BASE_CLOCK_RATE / 30);
|
||||
constexpr s64 frame_ticks = static_cast<s64>(1000000000 / 60);
|
||||
constexpr s64 frame_ticks_30fps = static_cast<s64>(1000000000 / 30);
|
||||
|
||||
void NVFlinger::VSyncThread(NVFlinger& nv_flinger) {
|
||||
nv_flinger.SplitVSync();
|
||||
}
|
||||
|
||||
void NVFlinger::SplitVSync() {
|
||||
system.RegisterHostThread();
|
||||
std::string name = "yuzu:VSyncThread";
|
||||
MicroProfileOnThreadCreate(name.c_str());
|
||||
Common::SetCurrentThreadName(name.c_str());
|
||||
Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
|
||||
s64 delay = 0;
|
||||
while (is_running) {
|
||||
guard->lock();
|
||||
const s64 time_start = system.CoreTiming().GetGlobalTimeNs().count();
|
||||
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();
|
||||
if (next_time > 0) {
|
||||
wait_event->WaitFor(std::chrono::nanoseconds{next_time});
|
||||
}
|
||||
delay = (system.CoreTiming().GetGlobalTimeNs().count() - time_end) - next_time;
|
||||
}
|
||||
}
|
||||
|
||||
NVFlinger::NVFlinger(Core::System& system) : system(system) {
|
||||
displays.emplace_back(0, "Default", system);
|
||||
@ -36,22 +64,36 @@ NVFlinger::NVFlinger(Core::System& system) : system(system) {
|
||||
displays.emplace_back(2, "Edid", system);
|
||||
displays.emplace_back(3, "Internal", system);
|
||||
displays.emplace_back(4, "Null", system);
|
||||
guard = std::make_shared<std::mutex>();
|
||||
|
||||
// Schedule the screen composition events
|
||||
composition_event =
|
||||
Core::Timing::CreateEvent("ScreenComposition", [this](u64 userdata, s64 cycles_late) {
|
||||
Core::Timing::CreateEvent("ScreenComposition", [this](u64 userdata, s64 ns_late) {
|
||||
Lock();
|
||||
Compose();
|
||||
const auto ticks =
|
||||
Settings::values.force_30fps_mode ? frame_ticks_30fps : GetNextTicks();
|
||||
this->system.CoreTiming().ScheduleEvent(std::max<s64>(0LL, ticks - cycles_late),
|
||||
const auto ticks = GetNextTicks();
|
||||
this->system.CoreTiming().ScheduleEvent(std::max<s64>(0LL, ticks - ns_late),
|
||||
composition_event);
|
||||
});
|
||||
|
||||
system.CoreTiming().ScheduleEvent(frame_ticks, composition_event);
|
||||
if (system.IsMulticore()) {
|
||||
is_running = true;
|
||||
wait_event = std::make_unique<Common::Event>();
|
||||
vsync_thread = std::make_unique<std::thread>(VSyncThread, std::ref(*this));
|
||||
} else {
|
||||
system.CoreTiming().ScheduleEvent(frame_ticks, composition_event);
|
||||
}
|
||||
}
|
||||
|
||||
NVFlinger::~NVFlinger() {
|
||||
system.CoreTiming().UnscheduleEvent(composition_event, 0);
|
||||
if (system.IsMulticore()) {
|
||||
is_running = false;
|
||||
wait_event->Set();
|
||||
vsync_thread->join();
|
||||
vsync_thread.reset();
|
||||
wait_event.reset();
|
||||
} else {
|
||||
system.CoreTiming().UnscheduleEvent(composition_event, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void NVFlinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) {
|
||||
@ -199,10 +241,12 @@ void NVFlinger::Compose() {
|
||||
|
||||
auto& gpu = system.GPU();
|
||||
const auto& multi_fence = buffer->get().multi_fence;
|
||||
guard->unlock();
|
||||
for (u32 fence_id = 0; fence_id < multi_fence.num_fences; fence_id++) {
|
||||
const auto& fence = multi_fence.fences[fence_id];
|
||||
gpu.WaitFence(fence.id, fence.value);
|
||||
}
|
||||
guard->lock();
|
||||
|
||||
MicroProfileFlip();
|
||||
|
||||
@ -223,7 +267,7 @@ void NVFlinger::Compose() {
|
||||
|
||||
s64 NVFlinger::GetNextTicks() const {
|
||||
constexpr s64 max_hertz = 120LL;
|
||||
return (Core::Hardware::BASE_CLOCK_RATE * (1LL << swap_interval)) / max_hertz;
|
||||
return (1000000000 * (1LL << swap_interval)) / max_hertz;
|
||||
}
|
||||
|
||||
} // namespace Service::NVFlinger
|
||||
|
@ -4,15 +4,22 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/kernel/object.h"
|
||||
|
||||
namespace Common {
|
||||
class Event;
|
||||
} // namespace Common
|
||||
|
||||
namespace Core::Timing {
|
||||
class CoreTiming;
|
||||
struct EventType;
|
||||
@ -79,6 +86,10 @@ public:
|
||||
|
||||
s64 GetNextTicks() const;
|
||||
|
||||
std::unique_lock<std::mutex> Lock() {
|
||||
return std::unique_lock{*guard};
|
||||
}
|
||||
|
||||
private:
|
||||
/// Finds the display identified by the specified ID.
|
||||
VI::Display* FindDisplay(u64 display_id);
|
||||
@ -92,6 +103,10 @@ private:
|
||||
/// Finds the layer identified by the specified ID in the desired display.
|
||||
const VI::Layer* FindLayer(u64 display_id, u64 layer_id) const;
|
||||
|
||||
static void VSyncThread(NVFlinger& nv_flinger);
|
||||
|
||||
void SplitVSync();
|
||||
|
||||
std::shared_ptr<Nvidia::Module> nvdrv;
|
||||
|
||||
std::vector<VI::Display> displays;
|
||||
@ -108,7 +123,13 @@ private:
|
||||
/// Event that handles screen composition.
|
||||
std::shared_ptr<Core::Timing::EventType> composition_event;
|
||||
|
||||
std::shared_ptr<std::mutex> guard;
|
||||
|
||||
Core::System& system;
|
||||
|
||||
std::unique_ptr<std::thread> vsync_thread;
|
||||
std::unique_ptr<Common::Event> wait_event;
|
||||
std::atomic<bool> is_running{};
|
||||
};
|
||||
|
||||
} // namespace Service::NVFlinger
|
||||
|
@ -142,7 +142,7 @@ void SM::GetService(Kernel::HLERequestContext& ctx) {
|
||||
}
|
||||
|
||||
// Wake the threads waiting on the ServerPort
|
||||
server_port->WakeupAllWaitingThreads();
|
||||
server_port->Signal();
|
||||
|
||||
LOG_DEBUG(Service_SM, "called service={} -> session={}", name, client->GetObjectId());
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
|
||||
|
@ -11,9 +11,8 @@
|
||||
namespace Service::Time::Clock {
|
||||
|
||||
TimeSpanType StandardSteadyClockCore::GetCurrentRawTimePoint(Core::System& system) {
|
||||
const TimeSpanType ticks_time_span{TimeSpanType::FromTicks(
|
||||
Core::Timing::CpuCyclesToClockCycles(system.CoreTiming().GetTicks()),
|
||||
Core::Hardware::CNTFREQ)};
|
||||
const TimeSpanType ticks_time_span{
|
||||
TimeSpanType::FromTicks(system.CoreTiming().GetClockTicks(), Core::Hardware::CNTFREQ)};
|
||||
TimeSpanType raw_time_point{setup_value.nanoseconds + ticks_time_span.nanoseconds};
|
||||
|
||||
if (raw_time_point.nanoseconds < cached_raw_time_point.nanoseconds) {
|
||||
|
@ -11,9 +11,8 @@
|
||||
namespace Service::Time::Clock {
|
||||
|
||||
SteadyClockTimePoint TickBasedSteadyClockCore::GetTimePoint(Core::System& system) {
|
||||
const TimeSpanType ticks_time_span{TimeSpanType::FromTicks(
|
||||
Core::Timing::CpuCyclesToClockCycles(system.CoreTiming().GetTicks()),
|
||||
Core::Hardware::CNTFREQ)};
|
||||
const TimeSpanType ticks_time_span{
|
||||
TimeSpanType::FromTicks(system.CoreTiming().GetClockTicks(), Core::Hardware::CNTFREQ)};
|
||||
|
||||
return {ticks_time_span.ToSeconds(), GetClockSourceId()};
|
||||
}
|
||||
|
@ -234,9 +234,8 @@ void Module::Interface::CalculateMonotonicSystemClockBaseTimePoint(Kernel::HLERe
|
||||
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(
|
||||
Core::Timing::CpuCyclesToClockCycles(system.CoreTiming().GetTicks()),
|
||||
Core::Hardware::CNTFREQ)};
|
||||
const auto ticks{Clock::TimeSpanType::FromTicks(system.CoreTiming().GetClockTicks(),
|
||||
Core::Hardware::CNTFREQ)};
|
||||
const s64 base_time_point{context.offset + current_time_point.time_point -
|
||||
ticks.ToSeconds()};
|
||||
IPC::ResponseBuilder rb{ctx, (sizeof(s64) / 4) + 2};
|
||||
|
@ -30,8 +30,7 @@ void SharedMemory::SetupStandardSteadyClock(Core::System& system,
|
||||
const Common::UUID& clock_source_id,
|
||||
Clock::TimeSpanType current_time_point) {
|
||||
const Clock::TimeSpanType ticks_time_span{Clock::TimeSpanType::FromTicks(
|
||||
Core::Timing::CpuCyclesToClockCycles(system.CoreTiming().GetTicks()),
|
||||
Core::Hardware::CNTFREQ)};
|
||||
system.CoreTiming().GetClockTicks(), Core::Hardware::CNTFREQ)};
|
||||
const Clock::SteadyClockContext context{
|
||||
static_cast<u64>(current_time_point.nanoseconds - ticks_time_span.nanoseconds),
|
||||
clock_source_id};
|
||||
|
@ -511,6 +511,7 @@ private:
|
||||
LOG_DEBUG(Service_VI, "called. id=0x{:08X} transaction={:X}, flags=0x{:08X}", id,
|
||||
static_cast<u32>(transaction), flags);
|
||||
|
||||
nv_flinger->Lock();
|
||||
auto& buffer_queue = nv_flinger->FindBufferQueue(id);
|
||||
|
||||
switch (transaction) {
|
||||
@ -550,6 +551,7 @@ private:
|
||||
[=](std::shared_ptr<Kernel::Thread> thread, Kernel::HLERequestContext& ctx,
|
||||
Kernel::ThreadWakeupReason reason) {
|
||||
// Repeat TransactParcel DequeueBuffer when a buffer is available
|
||||
nv_flinger->Lock();
|
||||
auto& buffer_queue = nv_flinger->FindBufferQueue(id);
|
||||
auto result = buffer_queue.DequeueBuffer(width, height);
|
||||
ASSERT_MSG(result != std::nullopt, "Could not dequeue buffer.");
|
||||
|
Reference in New Issue
Block a user