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:
commit
c6ca798fe6
|
|
@ -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&) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue