Merge pull request #1655 from mohdfaour03/fix/videoout-present-precise-wait

fix(videoout): wait for flips with the high-resolution condition on Windows
This commit is contained in:
Adrià authored and GitHub committed 2026-10-11 11:27:48 +02:00
commit c6ca798fe6
3 files changed
+17 -12

No files matched your search

@@ -9,6 +9,7 @@ add_library(libSceVideoOut SHARED EXCLUDE_FROM_ALL
${CMAKE_CURRENT_SOURCE_DIR}/src/MouseInput.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/KeyboardInput.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/InputMapping.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../libkernel/Time/TimedWait.cpp
)
target_include_directories(libSceVideoOut PRIVATE
@@ -20,6 +20,7 @@
#include "prx/libSceVideoOut/include/DisplayWindow.hpp"
#include "prx/libSceVideoOut/include/BufferReuseTracker.hpp"
#include "prx/libc/include/Shutdown.hpp"
#include "prx/libkernel/Time/include/TimedWait.hpp"
#include "SDL.h"
#include "SceTypes.hpp"
@@ -190,7 +191,7 @@ struct FlipRequest final : AgcDriver::IFlipRequest, std::enable_shared_from_this
struct FlipQueue {
std::mutex mutex;
std::condition_variable changed;
TimedWait::Condition changed;
std::list<std::shared_ptr<FlipRequest>> requests;
std::atomic<std::size_t> reservations = 0;
std::exception_ptr failure;
@@ -29,6 +29,9 @@
namespace {
constexpr std::uint64_t FLIP_ROOM_WAIT_MICROS = 60000000;
constexpr std::uint64_t PRESENT_POLL_MICROS = 10000;
void require(bool condition, const char* reason) {
if (!condition) throw std::runtime_error(std::string("VideoOut: ") + reason);
}
@@ -119,7 +122,7 @@ public:
void WaitForFlipRoom() override {
std::unique_lock queueLock(queue->mutex);
const bool room = queue->changed.wait_for(queueLock, std::chrono::seconds(60), [&] {
const bool room = queue->changed.WaitUntil(queueLock, TimedWait::DeadlineNanos(FLIP_ROOM_WAIT_MICROS), [&] {
return queue->failure || queue->stopping || cfg->shutdownToken.stop_requested() || queue->reservations.load() < VIDEO_OUT_FLIP_QUEUE_CAPACITY;
});
if (queue->failure) std::rethrow_exception(queue->failure);
@@ -164,7 +167,7 @@ public:
if (!cfg->failure) cfg->failure = error;
cfg->vblankCond.notify_all();
}
queue->changed.notify_all();
queue->changed.NotifyAll();
}
private:
@@ -197,7 +200,7 @@ void FlipRequest::Cancel() noexcept {
std::lock_guard lock(cfg->mutex);
ReleaseLocked();
}
queue->changed.notify_all();
queue->changed.NotifyAll();
}
void FlipRequest::GpuReady(const std::shared_ptr<AgcDriver::FrameTiming>& frameTiming) {
@@ -222,7 +225,7 @@ void FlipRequest::GpuReady(const std::shared_ptr<AgcDriver::FrameTiming>& frameT
queue->requests.push_back(shared_from_this());
ready = true;
}
queue->changed.notify_all();
queue->changed.NotifyAll();
// The worker is done once the request is queued: hardware does not stall the command processor
// on a flip, and the title observes completion through flipPendingNum, which processFlip drops
// once the frame's GPU work and its presentation have completed (see Driver::Present). A
@@ -241,7 +244,7 @@ void FlipRequest::Fail(std::exception_ptr error) noexcept {
std::lock_guard lock(cfg->mutex);
if (!cfg->failure) cfg->failure = error;
ReleaseLocked();
queue->changed.notify_all();
queue->changed.NotifyAll();
}
VideoOutDriver& VideoOutDriver::Get() {
@@ -273,12 +276,12 @@ VideoOutDriver::VideoOutDriver() {
} catch (...) {
if (vblankThread.joinable()) {
vblankThread.request_stop();
flipQueue->changed.notify_all();
flipQueue->changed.NotifyAll();
vblankThread.join();
}
if (presentThread.joinable()) {
presentThread.request_stop();
flipQueue->changed.notify_all();
flipQueue->changed.NotifyAll();
presentThread.join();
}
SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER);
@@ -301,7 +304,7 @@ void VideoOutDriver::Shutdown() {
}
presentThread.request_stop();
vblankThread.request_stop();
flipQueue->changed.notify_all();
flipQueue->changed.NotifyAll();
presentThread.join();
vblankThread.join();
{
@@ -377,7 +380,7 @@ bool VideoOutDriver::close(int handle) {
cfg->outputModeEvents.clear();
cfg->vrrStatusEvents.clear();
cfg->vblankCond.notify_all();
flipQueue->changed.notify_all();
flipQueue->changed.NotifyAll();
return true;
}
@@ -570,7 +573,7 @@ void VideoOutDriver::presentLoop(std::stop_token token, std::promise<void>& star
while (!token.stop_requested()) {
{
std::unique_lock lock(flipQueue->mutex);
flipQueue->changed.wait_for(lock, std::chrono::milliseconds(10), [&] { return token.stop_requested() || flipQueue->failure || !flipQueue->requests.empty(); });
flipQueue->changed.WaitUntil(lock, TimedWait::DeadlineNanos(PRESENT_POLL_MICROS), [&] { return token.stop_requested() || flipQueue->failure || !flipQueue->requests.empty(); });
if (flipQueue->failure) std::rethrow_exception(flipQueue->failure);
if (token.stop_requested()) break;
if (!flipQueue->requests.empty()) {
@@ -611,7 +614,7 @@ void VideoOutDriver::presentLoop(std::stop_token token, std::promise<void>& star
}
if (current) {
current.reset();
flipQueue->changed.notify_all();
flipQueue->changed.NotifyAll();
}
}
} catch (const ProcessShutdown&) {