fix(agc): drop a presentation instead of waiting for a swapchain image
The presenter acquired the next swapchain image with a 5 s timeout before completing the guest's flip. With FIFO on Wayland, NVIDIA's driver hands out about one image per second while the window is hidden (another workspace or occluded): vkAcquireNextImageKHR blocked for ~1 s per flip, and the title ran at exactly 1 frame per second. Stack snapshots of Uncharted: Legacy of Thieves Collection (PPSA05684) showed the presenter in drmSyncobjTimelineWait under AcquireImage in every snapshot taken during such a stall, and in none outside them. The acquire no longer waits: VK_NOT_READY or VK_TIMEOUT drops that presentation, as an out-of-date swapchain already does, and the flip completes. APS5_PROFILE_DRAW's [present] line counts the drops. Menu with the window moved to an empty workspace for 50 s: 7.5 fps and about 65 drops per 10 s while hidden (1 fps before), no drops while visible.
This commit is contained in:
parent
5d50886ee4
commit
37d9ef133f
|
|
@ -222,7 +222,7 @@ public:
|
|||
// blit-submit times after the flip packet; noted in-place reads checked
|
||||
// (APS5_FLIP_READ_CHECK=1) and found overwritten before the blit's fence.
|
||||
struct PresentStatistics {
|
||||
std::uint64_t presents, gpuUnread, batchesAheadOfBlit, batchesAfterFlip, readsChecked, readsOverwritten;
|
||||
std::uint64_t presents, gpuUnread, batchesAheadOfBlit, batchesAfterFlip, readsChecked, readsOverwritten, acquireDrops;
|
||||
double gpuBusyMs, gpuGapMs, lastSubmitAfterFlipMs, blitSubmitAfterFlipMs;
|
||||
};
|
||||
static PresentStatistics PresentCounts();
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ void Driver::reportPresents(double waitedMs, std::size_t inFlight) {
|
|||
const auto flips = flipsCounted.load() - previousFlips;
|
||||
const double perFlip = flips != 0 ? 1.0 / static_cast<double>(flips) : 0.0;
|
||||
const auto serial = flipSerial.load();
|
||||
AgcDriver::ProfilePrint_nid_no_patch( "[present] %llu presents over 10 s (%zu may trail on the GPU); %s p50 %.2f ms, p90 %.2f ms, max %.2f ms over %zu; per present: GPU busy %.1f ms, idle gaps %.1f ms (%llu batches without a completion record); per flip: %.1f batches recorded (%.1f unsignaled at the flip); per present: %.1f batches ahead of the blit, %.1f after it; after the flip packet: last submit %.1f ms, blit submit %.1f ms; in-place reads overwritten before execution: %llu of %llu checked\n", static_cast<unsigned long long>(presents), inFlight, inFlight != 0 ? "inflight_wait" : "render_fence_wait", percentile(0.5), percentile(0.9), waits.empty() ? 0.0 : waits.back(), waits.size(), (counts.gpuBusyMs - previous.gpuBusyMs) * perPresent, (counts.gpuGapMs - previous.gpuGapMs) * perPresent, static_cast<unsigned long long>(counts.gpuUnread - previous.gpuUnread), static_cast<double>(serial - windowSerial) * perFlip, static_cast<double>(flipBatchesUnsignaled.load() - previousUnsignaled) * perFlip, static_cast<double>(counts.batchesAheadOfBlit - previous.batchesAheadOfBlit) * perPresent, static_cast<double>(counts.batchesAfterFlip - previous.batchesAfterFlip) * perPresent, (counts.lastSubmitAfterFlipMs - previous.lastSubmitAfterFlipMs) * perPresent, (counts.blitSubmitAfterFlipMs - previous.blitSubmitAfterFlipMs) * perPresent, static_cast<unsigned long long>(counts.readsOverwritten - previous.readsOverwritten), static_cast<unsigned long long>(counts.readsChecked - previous.readsChecked));
|
||||
AgcDriver::ProfilePrint_nid_no_patch( "[present] %llu presents over 10 s (%llu dropped: no free swapchain image; %zu may trail on the GPU); %s p50 %.2f ms, p90 %.2f ms, max %.2f ms over %zu; per present: GPU busy %.1f ms, idle gaps %.1f ms (%llu batches without a completion record); per flip: %.1f batches recorded (%.1f unsignaled at the flip); per present: %.1f batches ahead of the blit, %.1f after it; after the flip packet: last submit %.1f ms, blit submit %.1f ms; in-place reads overwritten before execution: %llu of %llu checked\n", static_cast<unsigned long long>(presents), static_cast<unsigned long long>(counts.acquireDrops - previous.acquireDrops), inFlight, inFlight != 0 ? "inflight_wait" : "render_fence_wait", percentile(0.5), percentile(0.9), waits.empty() ? 0.0 : waits.back(), waits.size(), (counts.gpuBusyMs - previous.gpuBusyMs) * perPresent, (counts.gpuGapMs - previous.gpuGapMs) * perPresent, static_cast<unsigned long long>(counts.gpuUnread - previous.gpuUnread), static_cast<double>(serial - windowSerial) * perFlip, static_cast<double>(flipBatchesUnsignaled.load() - previousUnsignaled) * perFlip, static_cast<double>(counts.batchesAheadOfBlit - previous.batchesAheadOfBlit) * perPresent, static_cast<double>(counts.batchesAfterFlip - previous.batchesAfterFlip) * perPresent, (counts.lastSubmitAfterFlipMs - previous.lastSubmitAfterFlipMs) * perPresent, (counts.blitSubmitAfterFlipMs - previous.blitSubmitAfterFlipMs) * perPresent, static_cast<unsigned long long>(counts.readsOverwritten - previous.readsOverwritten), static_cast<unsigned long long>(counts.readsChecked - previous.readsChecked));
|
||||
previous = counts;
|
||||
previousFlips = flipsCounted.load();
|
||||
previousUnsignaled = flipBatchesUnsignaled.load();
|
||||
|
|
|
|||
|
|
@ -2649,11 +2649,15 @@ bool VulkanDevice::AcquireImage() {
|
|||
std::uint32_t index = 0;
|
||||
timing.Mark("fence_reset");
|
||||
// An out-of-date swapchain (the window changed) drops this frame; the next Resize recreates it.
|
||||
const auto acquired = state->DeviceFunction<PFN_vkAcquireNextImageKHR>("vkAcquireNextImageKHR")(state->device, state->swapchain, 5'000'000'000ULL, VK_NULL_HANDLE, state->acquireFence, &index);
|
||||
const auto acquired = state->DeviceFunction<PFN_vkAcquireNextImageKHR>("vkAcquireNextImageKHR")(state->device, state->swapchain, 0, VK_NULL_HANDLE, state->acquireFence, &index);
|
||||
if (acquired == VK_ERROR_OUT_OF_DATE_KHR) {
|
||||
state->extent = {0, 0};
|
||||
return false;
|
||||
}
|
||||
if (acquired == VK_NOT_READY || acquired == VK_TIMEOUT) {
|
||||
++presentCounters.acquireDrops;
|
||||
return false;
|
||||
}
|
||||
if (acquired != VK_SUBOPTIMAL_KHR) check(acquired, "vkAcquireNextImageKHR");
|
||||
timing.Mark("acquire_image");
|
||||
APS5_LOG_OUT_DEBUG("vkAcquireNextImageKHR index=%u imageCount=%zu", index, state->images.size());
|
||||
|
|
|
|||
Loading…
Reference in New Issue