Skip to content

Commit

Permalink
[GPU] Vsync timing requires far less cpu now to be accurate
Browse files Browse the repository at this point in the history
  • Loading branch information
disjtqz authored and Gliniak committed Sep 29, 2023
1 parent 294b968 commit cfecdcb
Showing 1 changed file with 23 additions and 10 deletions.
33 changes: 23 additions & 10 deletions src/xenia/gpu/graphics_system.cc
Expand Up @@ -104,34 +104,47 @@ X_STATUS GraphicsSystem::Setup(cpu::Processor* processor,
vsync_worker_running_ = true;
vsync_worker_thread_ = kernel::object_ref<kernel::XHostThread>(
new kernel::XHostThread(kernel_state_, 128 * 1024, 0, [this]() {
double vsync_duration_d =
const double vsync_duration_d =
cvars::vsync
? std::max<double>(
5.0, 1000.0 / static_cast<double>(cvars::vsync_fps))
: 1.0;
uint64_t last_frame_time = Clock::QueryGuestTickCount();
while (vsync_worker_running_) {
uint64_t current_time = Clock::QueryGuestTickCount();
// Sleep for 90% of the vblank duration, spin for 10%
const double duration_scalar = 0.90;

uint64_t tick_freq = Clock::guest_tick_frequency();
uint64_t time_delta = current_time - last_frame_time;
double elapsed_d = static_cast<double>(time_delta) /
(static_cast<double>(tick_freq) / 1000.0);
while (vsync_worker_running_) {
const uint64_t current_time = Clock::QueryGuestTickCount();
const uint64_t tick_freq = Clock::guest_tick_frequency();
const uint64_t time_delta = current_time - last_frame_time;
const double elapsed_d = static_cast<double>(time_delta) /
(static_cast<double>(tick_freq) / 1000.0);
if (elapsed_d >= vsync_duration_d) {
MarkVblank();
last_frame_time = current_time;

// TODO(disjtqz): should recalculate the remaining time to a vblank
// after MarkVblank, no idea how long the guest code normally takes
MarkVblank();
if (cvars::vsync) {
const uint64_t estimated_nanoseconds = static_cast<uint64_t>(
(vsync_duration_d * 1000000.0) *
duration_scalar); // 1000 microseconds = 1 ms

threading::NanoSleep(estimated_nanoseconds);
}
}
if (!cvars::vsync) {
xe::threading::Sleep(std::chrono::milliseconds(1));
}
}
}
return 0;
}));
// As we run vblank interrupts the debugger must be able to suspend us.
vsync_worker_thread_->set_can_debugger_suspend(true);
vsync_worker_thread_->set_name("GPU VSync");
vsync_worker_thread_->Create();
vsync_worker_thread_->thread()->set_priority(threading::ThreadPriority::kLowest);
vsync_worker_thread_->thread()->set_priority(
threading::ThreadPriority::kLowest);
if (cvars::trace_gpu_stream) {
BeginTracing();
}
Expand Down

0 comments on commit cfecdcb

Please sign in to comment.