Merge pull request #416 from oneandonlydean/fix/videoout-flip-release-vblank
fix(videoout): pace the next flip from the vblank a flip was released at
This commit is contained in:
commit
aa23d52878
|
|
@ -394,6 +394,7 @@ void VideoOutDriver::processFlip(FlipRequest& req) {
|
|||
req.cfg->vblankCond.wait(lock, req.cfg->shutdownToken, [&] { return req.cfg->vblankStatus.count >= target || req.cfg->failure || req.cfg->closing; });
|
||||
timing.Mark("vblank_wait");
|
||||
checkConfig(*req.cfg);
|
||||
req.cfg->lastFlipVblank = req.cfg->vblankStatus.count;
|
||||
}
|
||||
require(req.width != 0 && req.height != 0 && req.width <= static_cast<uint32_t>(std::numeric_limits<int>::max()) && req.height <= static_cast<uint32_t>(std::numeric_limits<int>::max()), "invalid window dimensions");
|
||||
window.Ensure(req.width, req.height);
|
||||
|
|
@ -444,7 +445,6 @@ void VideoOutDriver::processFlip(FlipRequest& req) {
|
|||
require(req.cfg->flipStatus.count != std::numeric_limits<uint64_t>::max(), "flip counter overflow");
|
||||
triggerEvents(*req.cfg, VIDEO_OUT_EVENT_FLIP, reinterpret_cast<void*>(req.flipArg));
|
||||
++req.cfg->flipStatus.count;
|
||||
req.cfg->lastFlipVblank = req.cfg->vblankStatus.count;
|
||||
req.cfg->flipStatus.processTime = sceKernelGetProcessTime();
|
||||
req.cfg->flipStatus.processTimeCounter = sceKernelGetProcessTimeCounter();
|
||||
req.cfg->flipStatus.flipArg = req.flipArg;
|
||||
|
|
|
|||
|
|
@ -273,6 +273,31 @@ void testBackToBack() {
|
|||
LibcRunShutdown_nid_postfix();
|
||||
}
|
||||
|
||||
void testReleaseVblank() {
|
||||
const int handle = sceVideoOutOpen(255, 0, 0, nullptr);
|
||||
auto cfg = VideoOutDriver::Get().GetConfig(handle);
|
||||
std::vector<std::byte> allocation(6 * 65536 + 65535);
|
||||
const auto storage = alignedBuffer(allocation);
|
||||
fillBuffer(storage, 259, 137);
|
||||
VideoOutBuffers buffer{storage.data(), nullptr, {nullptr, nullptr}};
|
||||
VideoOutBufferAttribute2 attribute{};
|
||||
sceVideoOutSetBufferAttribute2(&attribute, 0x8000000000000000ull, 0, 259, 137, 0, 0, 0);
|
||||
sceVideoOutRegisterBuffers2(handle, 0, 0, &buffer, 1, &attribute, 0, nullptr);
|
||||
check(sceVideoOutSetFlipRate(handle, 2) == 0, "flip rate was not applied");
|
||||
sceVideoOutSubmitFlip(handle, 0, 1, 1);
|
||||
{
|
||||
std::unique_lock lock(cfg->mutex);
|
||||
const bool done = cfg->vblankCond.wait_for(lock, std::chrono::seconds(15), [&] { return cfg->failure || cfg->flipStatus.count == 1; });
|
||||
if (cfg->failure) std::rethrow_exception(cfg->failure);
|
||||
check(done, "the flip did not complete");
|
||||
check(cfg->vblankStatus.count > 3, "the first presentation did not outlast the vblank it was released at");
|
||||
check(cfg->lastFlipVblank == 3, "the next flip is not paced from the vblank this flip was released at");
|
||||
}
|
||||
sceVideoOutUnregisterBuffers(handle, 0);
|
||||
sceVideoOutClose(handle);
|
||||
LibcRunShutdown_nid_postfix();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
|
@ -281,6 +306,7 @@ int main(int argc, char** argv) {
|
|||
else if (argc == 2 && std::string(argv[1]) == "controls") testControls();
|
||||
else if (argc == 2 && std::string(argv[1]) == "present") testPresentation(false);
|
||||
else if (argc == 2 && std::string(argv[1]) == "backtoback") testBackToBack();
|
||||
else if (argc == 2 && std::string(argv[1]) == "pacing") testReleaseVblank();
|
||||
else if (argc == 2 && std::string(argv[1]) == "unavailable") testPresentation(true);
|
||||
else testLifetime(argc == 2 && std::string(argv[1]) == "reopen");
|
||||
std::puts("VideoOut flip tests passed");
|
||||
|
|
|
|||
Loading…
Reference in New Issue