libraries: videoout: better flip status handling

This commit is contained in:
psucien 2024-08-13 19:18:08 +02:00
parent c94190b69b
commit 01e66bb548
3 changed files with 28 additions and 21 deletions

View File

@ -174,14 +174,19 @@ std::chrono::microseconds VideoOutDriver::Flip(const Request& req) {
// Update flip status. // Update flip status.
auto* port = req.port; auto* port = req.port;
auto& flip_status = port->flip_status; {
flip_status.count++; std::unique_lock lock{port->port_mutex};
flip_status.processTime = Libraries::Kernel::sceKernelGetProcessTime(); auto& flip_status = port->flip_status;
flip_status.tsc = Libraries::Kernel::sceKernelReadTsc(); flip_status.count++;
flip_status.submitTsc = Libraries::Kernel::sceKernelReadTsc(); flip_status.processTime = Libraries::Kernel::sceKernelGetProcessTime();
flip_status.flipArg = req.flip_arg; flip_status.tsc = Libraries::Kernel::sceKernelReadTsc();
flip_status.currentBuffer = req.index; flip_status.flipArg = req.flip_arg;
flip_status.flipPendingNum = static_cast<int>(requests.size()); flip_status.currentBuffer = req.index;
if (req.eop) {
--flip_status.gcQueueNum;
}
--flip_status.flipPendingNum;
}
// Trigger flip events for the port. // Trigger flip events for the port.
for (auto& event : port->flip_events) { for (auto& event : port->flip_events) {
@ -203,15 +208,18 @@ std::chrono::microseconds VideoOutDriver::Flip(const Request& req) {
bool VideoOutDriver::SubmitFlip(VideoOutPort* port, s32 index, s64 flip_arg, bool VideoOutDriver::SubmitFlip(VideoOutPort* port, s32 index, s64 flip_arg,
bool is_eop /*= false*/) { bool is_eop /*= false*/) {
u32 num_requests_pending{};
{ {
std::scoped_lock lock{mutex}; std::unique_lock lock{port->port_mutex};
num_requests_pending = requests.size(); if (index != -1 && port->flip_status.flipPendingNum >= port->NumRegisteredBuffers()) {
} LOG_ERROR(Lib_VideoOut, "Flip queue is full");
return false;
}
if (index != -1 && num_requests_pending >= port->NumRegisteredBuffers()) { if (is_eop) {
LOG_ERROR(Lib_VideoOut, "Flip queue is full"); ++port->flip_status.gcQueueNum;
return false; }
++port->flip_status.flipPendingNum; // integral GPU and CPU pending flips counter
port->flip_status.submitTsc = Libraries::Kernel::sceKernelReadTsc();
} }
if (!is_eop) { if (!is_eop) {
@ -226,9 +234,6 @@ bool VideoOutDriver::SubmitFlip(VideoOutPort* port, s32 index, s64 flip_arg,
SubmitFlipInternal(port, index, flip_arg, is_eop); SubmitFlipInternal(port, index, flip_arg, is_eop);
} }
port->flip_status.flipPendingNum = num_requests_pending + 1;
port->flip_status.gcQueueNum = 0;
return true; return true;
} }
@ -249,7 +254,6 @@ void VideoOutDriver::SubmitFlipInternal(VideoOutPort* port, s32 index, s64 flip_
.port = port, .port = port,
.index = index, .index = index,
.flip_arg = flip_arg, .flip_arg = flip_arg,
.submit_tsc = Libraries::Kernel::sceKernelReadTsc(),
.eop = is_eop, .eop = is_eop,
}); });
} }

View File

@ -29,6 +29,7 @@ struct VideoOutPort {
std::vector<Kernel::SceKernelEqueue> flip_events; std::vector<Kernel::SceKernelEqueue> flip_events;
std::vector<Kernel::SceKernelEqueue> vblank_events; std::vector<Kernel::SceKernelEqueue> vblank_events;
std::mutex vo_mutex; std::mutex vo_mutex;
std::mutex port_mutex;
std::condition_variable vo_cv; std::condition_variable vo_cv;
std::condition_variable vblank_cv; std::condition_variable vblank_cv;
int flip_rate = 0; int flip_rate = 0;
@ -93,7 +94,6 @@ private:
VideoOutPort* port; VideoOutPort* port;
s32 index; s32 index;
s64 flip_arg; s64 flip_arg;
u64 submit_tsc;
bool eop; bool eop;
operator bool() const noexcept { operator bool() const noexcept {

View File

@ -113,7 +113,9 @@ s32 PS4_SYSV_ABI sceVideoOutSetFlipRate(s32 handle, s32 rate) {
s32 PS4_SYSV_ABI sceVideoOutIsFlipPending(s32 handle) { s32 PS4_SYSV_ABI sceVideoOutIsFlipPending(s32 handle) {
LOG_INFO(Lib_VideoOut, "called"); LOG_INFO(Lib_VideoOut, "called");
s32 pending = driver->GetPort(handle)->flip_status.flipPendingNum; auto* port = driver->GetPort(handle);
std::unique_lock lock{port->port_mutex};
s32 pending = port->flip_status.flipPendingNum;
return pending; return pending;
} }
@ -161,6 +163,7 @@ s32 PS4_SYSV_ABI sceVideoOutGetFlipStatus(s32 handle, FlipStatus* status) {
return ORBIS_VIDEO_OUT_ERROR_INVALID_HANDLE; return ORBIS_VIDEO_OUT_ERROR_INVALID_HANDLE;
} }
std::unique_lock lock{port->port_mutex};
*status = port->flip_status; *status = port->flip_status;
LOG_INFO(Lib_VideoOut, LOG_INFO(Lib_VideoOut,