videoout: added sceVideoOutWaitVblank

This commit is contained in:
psucien 2024-07-20 11:18:04 +02:00 committed by IndecisiveTurtle
parent 621d50e681
commit 4d3b993285
5 changed files with 31 additions and 32 deletions

View file

@ -78,9 +78,7 @@ bool EqueueInternal::TriggerEvent(u64 ident, s16 filter, void* trigger_data) {
std::scoped_lock lock{m_mutex};
for (auto& event : m_events) {
ASSERT_MSG(event.event.filter == filter,
"Event to trigger doesn't match to queue events");
if (event.event.ident == ident) {
if ((event.event.ident == ident) && (event.event.filter == filter)) {
event.Trigger(trigger_data);
has_found = true;
}

View file

@ -234,28 +234,10 @@ bool VideoOutDriver::SubmitFlip(VideoOutPort* port, s32 index, s64 flip_arg,
port->flip_status.flipPendingNum = static_cast<int>(requests.size());
port->flip_status.gcQueueNum = 0;
submit_cond.notify_one();
return true;
}
void VideoOutDriver::Vblank() {
std::scoped_lock lock{mutex};
auto& vblank_status = main_port.vblank_status;
vblank_status.count++;
vblank_status.processTime = Libraries::Kernel::sceKernelGetProcessTime();
vblank_status.tsc = Libraries::Kernel::sceKernelReadTsc();
// Trigger flip events for the port.
for (auto& event : main_port.vblank_events) {
if (event != nullptr) {
event->TriggerEvent(SCE_VIDEO_OUT_EVENT_VBLANK,
Kernel::SceKernelEvent::Filter::VideoOut, nullptr);
}
}
}
void VideoOutDriver::PresentThread(std::stop_token token) {
static constexpr std::chrono::microseconds VblankPeriod{16683};
Common::SetCurrentThreadName("VblankThread");
@ -283,9 +265,15 @@ void VideoOutDriver::PresentThread(std::stop_token token) {
delay = Flip(request);
FRAME_END;
}
vblank_status.count++;
vblank_status.processTime = Libraries::Kernel::sceKernelGetProcessTime();
vblank_status.tsc = Libraries::Kernel::sceKernelReadTsc();
{
// Needs lock here as can be concurrently read by `sceVideoOutGetVblankStatus`
std::unique_lock lock{main_port.vo_mutex};
vblank_status.count++;
vblank_status.processTime = Libraries::Kernel::sceKernelGetProcessTime();
vblank_status.tsc = Libraries::Kernel::sceKernelReadTsc();
main_port.vblank_cv.notify_all();
}
// Trigger flip events for the port.
for (auto& event : main_port.vblank_events) {

View file

@ -3,11 +3,13 @@
#pragma once
#include "common/debug.h"
#include "common/polyfill_thread.h"
#include "core/libraries/videoout/video_out.h"
#include <condition_variable>
#include <mutex>
#include <queue>
#include "common/polyfill_thread.h"
#include "core/libraries/videoout/video_out.h"
namespace Vulkan {
struct Frame;
@ -28,6 +30,7 @@ struct VideoOutPort {
std::vector<Kernel::SceKernelEqueue> vblank_events;
std::mutex vo_mutex;
std::condition_variable vo_cv;
std::condition_variable vblank_cv;
int flip_rate = 0;
s32 FindFreeGroup() const {
@ -84,8 +87,6 @@ public:
bool SubmitFlip(VideoOutPort* port, s32 index, s64 flip_arg, bool is_eop = false);
void Vblank();
private:
struct Request {
Vulkan::Frame* frame;
@ -105,11 +106,8 @@ private:
std::mutex mutex;
VideoOutPort main_port{};
std::condition_variable_any submit_cond;
std::condition_variable done_cond;
std::jthread present_thread;
std::queue<Request> requests;
bool is_neo{};
};
} // namespace Libraries::VideoOut

View file

@ -183,6 +183,7 @@ s32 PS4_SYSV_ABI sceVideoOutGetVblankStatus(int handle, SceVideoOutVblankStatus*
return ORBIS_VIDEO_OUT_ERROR_INVALID_HANDLE;
}
std::unique_lock lock{port->vo_mutex};
*status = port->vblank_status;
return ORBIS_OK;
}
@ -258,6 +259,18 @@ s32 PS4_SYSV_ABI sceVideoOutGetDeviceCapabilityInfo(
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceVideoOutWaitVblank(s32 handle) {
auto* port = driver->GetPort(handle);
if (!port) {
return ORBIS_VIDEO_OUT_ERROR_INVALID_HANDLE;
}
std::unique_lock lock{port->vo_mutex};
const auto prev_counter = port->vblank_status.count;
port->vblank_cv.wait(lock, [&]() { return prev_counter != port->vblank_status.count; });
return ORBIS_OK;
}
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
driver = std::make_unique<VideoOutDriver>(Config::getScreenWidth(), Config::getScreenHeight());
@ -286,6 +299,7 @@ void RegisterLib(Core::Loader::SymbolsResolver* sym) {
sceVideoOutGetVblankStatus);
LIB_FUNCTION("kGVLc3htQE8", "libSceVideoOut", 1, "libSceVideoOut", 0, 0,
sceVideoOutGetDeviceCapabilityInfo);
LIB_FUNCTION("j6RaAUlaLv0", "libSceVideoOut", 1, "libSceVideoOut", 0, 0, sceVideoOutWaitVblank);
// openOrbis appears to have libSceVideoOut_v1 module libSceVideoOut_v1.1
LIB_FUNCTION("Up36PTk687E", "libSceVideoOut", 1, "libSceVideoOut", 1, 1, sceVideoOutOpen);

View file

@ -92,11 +92,12 @@ void PS4_SYSV_ABI sceVideoOutSetBufferAttribute(BufferAttribute* attribute, Pixe
u32 tilingMode, u32 aspectRatio, u32 width,
u32 height, u32 pitchInPixel);
s32 PS4_SYSV_ABI sceVideoOutAddFlipEvent(Kernel::SceKernelEqueue eq, s32 handle, void* udata);
s32 PS4_SYSV_ABI sceVideoOutAddVBlankEvent(Kernel::SceKernelEqueue eq, s32 handle, void* udata);
s32 PS4_SYSV_ABI sceVideoOutAddVblankEvent(Kernel::SceKernelEqueue eq, s32 handle, void* udata);
s32 PS4_SYSV_ABI sceVideoOutRegisterBuffers(s32 handle, s32 startIndex, void* const* addresses,
s32 bufferNum, const BufferAttribute* attribute);
s32 PS4_SYSV_ABI sceVideoOutSetFlipRate(s32 handle, s32 rate);
s32 PS4_SYSV_ABI sceVideoOutIsFlipPending(s32 handle);
s32 PS4_SYSV_ABI sceVideoOutWaitVblank(s32 handle);
s32 PS4_SYSV_ABI sceVideoOutSubmitFlip(s32 handle, s32 bufferIndex, s32 flipMode, s64 flipArg);
s32 PS4_SYSV_ABI sceVideoOutGetFlipStatus(s32 handle, FlipStatus* status);
s32 PS4_SYSV_ABI sceVideoOutGetResolutionStatus(s32 handle, SceVideoOutResolutionStatus* status);