mirror of
https://github.com/InstanceBrick/nightcap.git
synced 2026-10-18 17:00:50 +02:00
456 lines
18 KiB
C++
456 lines
18 KiB
C++
#include "window/vulkan_present_progress_gate.h"
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
namespace mocktail {
|
|
namespace window {
|
|
namespace {
|
|
|
|
constexpr uint64_t kFirstFrameTicksNs = 1000;
|
|
|
|
TEST(VulkanPresentProgressGateTest, IgnoresProgressOutsideActiveLifetime) {
|
|
VulkanPresentProgressGate gate;
|
|
VulkanPresentStallReport report;
|
|
|
|
gate.NotifyFramePresented(kFirstFrameTicksNs, 1);
|
|
EXPECT_FALSE(gate.Poll(
|
|
kFirstFrameTicksNs + VulkanPresentProgressGate::kStallThresholdNs, true,
|
|
&report));
|
|
|
|
ASSERT_TRUE(gate.Activate());
|
|
EXPECT_FALSE(gate.Activate());
|
|
gate.NotifyFramePresented(kFirstFrameTicksNs, 1);
|
|
gate.Deactivate();
|
|
EXPECT_FALSE(gate.Poll(
|
|
kFirstFrameTicksNs + VulkanPresentProgressGate::kStallThresholdNs, true,
|
|
&report));
|
|
}
|
|
|
|
TEST(VulkanPresentProgressGateTest, ReportsRenderStallBeforeHostPresentOnce) {
|
|
VulkanPresentProgressGate gate;
|
|
ASSERT_TRUE(gate.Activate());
|
|
gate.NotifyFramePresented(kFirstFrameTicksNs, 240);
|
|
|
|
VulkanPresentStallReport report;
|
|
EXPECT_FALSE(gate.Poll(
|
|
kFirstFrameTicksNs + VulkanPresentProgressGate::kStallThresholdNs - 1,
|
|
true, &report));
|
|
ASSERT_TRUE(gate.Poll(
|
|
kFirstFrameTicksNs + VulkanPresentProgressGate::kStallThresholdNs, true,
|
|
&report));
|
|
EXPECT_EQ(report.stage, VulkanPresentStallStage::kBeforeHostPresent);
|
|
EXPECT_EQ(report.frame_count, 240u);
|
|
EXPECT_EQ(report.host_present_count, 0u);
|
|
EXPECT_FALSE(gate.Poll(
|
|
kFirstFrameTicksNs + VulkanPresentProgressGate::kStallThresholdNs + 1,
|
|
true, &report));
|
|
}
|
|
|
|
TEST(VulkanPresentProgressGateTest, IdentifiesBlockedHostPresent) {
|
|
VulkanPresentProgressGate gate;
|
|
ASSERT_TRUE(gate.Activate());
|
|
gate.NotifyFramePresented(kFirstFrameTicksNs, 7);
|
|
constexpr uint64_t kHostCallTicksNs = 2000;
|
|
gate.NotifyHostPresentBegin(kHostCallTicksNs);
|
|
|
|
VulkanPresentStallReport report;
|
|
ASSERT_TRUE(
|
|
gate.Poll(kHostCallTicksNs + VulkanPresentProgressGate::kStallThresholdNs,
|
|
true, &report));
|
|
EXPECT_EQ(report.stage, VulkanPresentStallStage::kInsideHostPresent);
|
|
EXPECT_EQ(report.frame_count, 7u);
|
|
EXPECT_EQ(report.host_present_count, 1u);
|
|
}
|
|
|
|
TEST(VulkanPresentProgressGateTest,
|
|
WorkerHostPresentRemainsSecondaryToRenderGap) {
|
|
VulkanPresentProgressGate gate;
|
|
ASSERT_TRUE(gate.Activate());
|
|
constexpr uint64_t kRenderThreadId = 4040;
|
|
constexpr uint64_t kWorkerThreadId = 4141;
|
|
gate.NotifyFramePresented(kFirstFrameTicksNs, 8, kRenderThreadId);
|
|
constexpr uint64_t kHostCallTicksNs = kFirstFrameTicksNs + 100;
|
|
const uint64_t sequence =
|
|
gate.NotifyHostPresentBegin(kHostCallTicksNs, kWorkerThreadId);
|
|
ASSERT_NE(sequence, 0u);
|
|
|
|
VulkanPresentStallReport report;
|
|
ASSERT_TRUE(
|
|
gate.Poll(kHostCallTicksNs +
|
|
VulkanPresentProgressGate::kStallThresholdNs,
|
|
true, &report));
|
|
EXPECT_EQ(report.stage, VulkanPresentStallStage::kBeforeHostPresent);
|
|
EXPECT_EQ(report.call_sequence, 0u);
|
|
EXPECT_STREQ(report.oldest_active_call_name, "vkQueuePresentKHR(host)");
|
|
EXPECT_EQ(report.oldest_active_call_sequence, sequence);
|
|
EXPECT_EQ(report.oldest_active_call_thread_id, kWorkerThreadId);
|
|
}
|
|
|
|
TEST(VulkanPresentProgressGateTest, OldHostEndCannotClearNewHostCall) {
|
|
VulkanPresentProgressGate gate;
|
|
ASSERT_TRUE(gate.Activate());
|
|
constexpr uint64_t kRenderThreadId = 4241;
|
|
gate.NotifyFramePresented(kFirstFrameTicksNs, 9, kRenderThreadId);
|
|
const uint64_t old_sequence = gate.NotifyHostPresentBegin(
|
|
kFirstFrameTicksNs + 50, kRenderThreadId);
|
|
ASSERT_NE(old_sequence, 0u);
|
|
constexpr uint64_t kNewHostCallTicksNs = kFirstFrameTicksNs + 100;
|
|
const uint64_t new_sequence =
|
|
gate.NotifyHostPresentBegin(kNewHostCallTicksNs, kRenderThreadId);
|
|
ASSERT_NE(new_sequence, 0u);
|
|
gate.NotifyHostPresentEnd(old_sequence);
|
|
|
|
VulkanPresentStallReport report;
|
|
ASSERT_TRUE(
|
|
gate.Poll(kNewHostCallTicksNs +
|
|
VulkanPresentProgressGate::kStallThresholdNs,
|
|
true, &report));
|
|
EXPECT_EQ(report.stage, VulkanPresentStallStage::kInsideHostPresent);
|
|
EXPECT_EQ(report.call_sequence, new_sequence);
|
|
EXPECT_EQ(report.thread_id, kRenderThreadId);
|
|
}
|
|
|
|
TEST(VulkanPresentProgressGateTest, IdentifiesBlockedVulkanCallAndThread) {
|
|
VulkanPresentProgressGate gate;
|
|
ASSERT_TRUE(gate.Activate());
|
|
gate.NotifyFramePresented(kFirstFrameTicksNs, 11);
|
|
constexpr uint64_t kCallTicksNs = 3000;
|
|
constexpr uint64_t kThreadId = 4242;
|
|
const uint64_t sequence =
|
|
gate.NotifyCallBegin("vkWaitForFences", kCallTicksNs, kThreadId);
|
|
ASSERT_NE(sequence, 0u);
|
|
|
|
VulkanPresentStallReport report;
|
|
ASSERT_TRUE(
|
|
gate.Poll(kCallTicksNs + VulkanPresentProgressGate::kStallThresholdNs,
|
|
true, &report));
|
|
EXPECT_EQ(report.stage, VulkanPresentStallStage::kInsideVulkanCall);
|
|
EXPECT_STREQ(report.call_name, "vkWaitForFences");
|
|
EXPECT_EQ(report.call_sequence, sequence);
|
|
EXPECT_EQ(report.thread_id, kThreadId);
|
|
EXPECT_EQ(report.frame_count, 11u);
|
|
}
|
|
|
|
TEST(VulkanPresentProgressGateTest, RecentCallDoesNotHideExistingRenderGap) {
|
|
VulkanPresentProgressGate gate;
|
|
ASSERT_TRUE(gate.Activate());
|
|
gate.NotifyFramePresented(kFirstFrameTicksNs, 12);
|
|
const uint64_t call_ticks =
|
|
kFirstFrameTicksNs + VulkanPresentProgressGate::kStallThresholdNs - 100;
|
|
const uint64_t sequence =
|
|
gate.NotifyCallBegin("vkQueueSubmit", call_ticks, 5150);
|
|
ASSERT_NE(sequence, 0u);
|
|
|
|
VulkanPresentStallReport report;
|
|
ASSERT_TRUE(gate.Poll(
|
|
kFirstFrameTicksNs + VulkanPresentProgressGate::kStallThresholdNs, true,
|
|
&report));
|
|
EXPECT_EQ(report.stage, VulkanPresentStallStage::kBeforeHostPresent);
|
|
EXPECT_EQ(report.elapsed_ns,
|
|
VulkanPresentProgressGate::kStallThresholdNs);
|
|
|
|
ASSERT_TRUE(gate.Poll(
|
|
call_ticks + VulkanPresentProgressGate::kStallThresholdNs, true,
|
|
&report));
|
|
EXPECT_EQ(report.stage, VulkanPresentStallStage::kInsideVulkanCall);
|
|
EXPECT_EQ(report.call_sequence, sequence);
|
|
}
|
|
|
|
TEST(VulkanPresentProgressGateTest,
|
|
CallStartedBeforeLatestFrameIsSecondaryToRenderGap) {
|
|
VulkanPresentProgressGate gate;
|
|
ASSERT_TRUE(gate.Activate());
|
|
constexpr uint64_t kWorkerThreadId = 6160;
|
|
const uint64_t sequence =
|
|
gate.NotifyCallBegin("vkWaitSemaphores", kFirstFrameTicksNs,
|
|
kWorkerThreadId);
|
|
ASSERT_NE(sequence, 0u);
|
|
constexpr uint64_t kLaterFrameTicksNs = kFirstFrameTicksNs + 1000;
|
|
constexpr uint64_t kRenderThreadId = 6260;
|
|
gate.NotifyFramePresented(kLaterFrameTicksNs, 13, kRenderThreadId);
|
|
const uint64_t stalled_ticks =
|
|
kLaterFrameTicksNs + VulkanPresentProgressGate::kStallThresholdNs;
|
|
|
|
VulkanPresentStallReport report;
|
|
ASSERT_TRUE(gate.Poll(stalled_ticks, true, &report));
|
|
EXPECT_EQ(report.stage, VulkanPresentStallStage::kBeforeHostPresent);
|
|
EXPECT_EQ(report.call_name, nullptr);
|
|
EXPECT_EQ(report.call_sequence, 0u);
|
|
EXPECT_EQ(report.thread_id, 0u);
|
|
EXPECT_EQ(report.elapsed_ns,
|
|
VulkanPresentProgressGate::kStallThresholdNs);
|
|
EXPECT_EQ(report.last_present_thread_id, kRenderThreadId);
|
|
EXPECT_STREQ(report.oldest_active_call_name, "vkWaitSemaphores");
|
|
EXPECT_EQ(report.oldest_active_call_sequence, sequence);
|
|
EXPECT_EQ(report.oldest_active_call_thread_id, kWorkerThreadId);
|
|
EXPECT_EQ(report.oldest_active_call_elapsed_ns,
|
|
stalled_ticks - kFirstFrameTicksNs);
|
|
}
|
|
|
|
TEST(VulkanPresentProgressGateTest,
|
|
WorkerCallStartedAfterFrameRemainsSecondaryToRenderGap) {
|
|
VulkanPresentProgressGate gate;
|
|
ASSERT_TRUE(gate.Activate());
|
|
constexpr uint64_t kRenderThreadId = 6360;
|
|
constexpr uint64_t kWorkerThreadId = 6460;
|
|
gate.NotifyFramePresented(kFirstFrameTicksNs, 14, kRenderThreadId);
|
|
constexpr uint64_t kCallStartedNs = kFirstFrameTicksNs + 100;
|
|
const uint64_t sequence = gate.NotifyCallBegin(
|
|
"vkWaitSemaphores", kCallStartedNs, kWorkerThreadId);
|
|
ASSERT_NE(sequence, 0u);
|
|
|
|
VulkanPresentStallReport report;
|
|
ASSERT_TRUE(gate.Poll(
|
|
kCallStartedNs + VulkanPresentProgressGate::kStallThresholdNs, true,
|
|
&report));
|
|
EXPECT_EQ(report.stage, VulkanPresentStallStage::kBeforeHostPresent);
|
|
EXPECT_EQ(report.call_sequence, 0u);
|
|
EXPECT_EQ(report.thread_id, 0u);
|
|
EXPECT_STREQ(report.oldest_active_call_name, "vkWaitSemaphores");
|
|
EXPECT_EQ(report.oldest_active_call_sequence, sequence);
|
|
EXPECT_EQ(report.oldest_active_call_thread_id, kWorkerThreadId);
|
|
}
|
|
|
|
TEST(VulkanPresentProgressGateTest,
|
|
RenderCallStartedAfterFrameIsPrimaryStall) {
|
|
VulkanPresentProgressGate gate;
|
|
ASSERT_TRUE(gate.Activate());
|
|
constexpr uint64_t kRenderThreadId = 6560;
|
|
gate.NotifyFramePresented(kFirstFrameTicksNs, 15, kRenderThreadId);
|
|
constexpr uint64_t kCallStartedNs = kFirstFrameTicksNs + 100;
|
|
const uint64_t sequence = gate.NotifyCallBegin(
|
|
"vkResetCommandPool", kCallStartedNs, kRenderThreadId);
|
|
ASSERT_NE(sequence, 0u);
|
|
|
|
VulkanPresentStallReport report;
|
|
ASSERT_TRUE(gate.Poll(
|
|
kCallStartedNs + VulkanPresentProgressGate::kStallThresholdNs, true,
|
|
&report));
|
|
EXPECT_EQ(report.stage, VulkanPresentStallStage::kInsideVulkanCall);
|
|
EXPECT_STREQ(report.call_name, "vkResetCommandPool");
|
|
EXPECT_EQ(report.call_sequence, sequence);
|
|
EXPECT_EQ(report.thread_id, kRenderThreadId);
|
|
}
|
|
|
|
TEST(VulkanPresentProgressGateTest, ReportsEachNewBlockedCallInSameStall) {
|
|
VulkanPresentProgressGate gate;
|
|
ASSERT_TRUE(gate.Activate());
|
|
gate.NotifyFramePresented(kFirstFrameTicksNs, 14);
|
|
const uint64_t first_started_ns = kFirstFrameTicksNs + 100;
|
|
const uint64_t first_sequence =
|
|
gate.NotifyCallBegin("vkWaitForFences", first_started_ns, 7170);
|
|
ASSERT_NE(first_sequence, 0u);
|
|
|
|
VulkanPresentStallReport report;
|
|
ASSERT_TRUE(gate.Poll(
|
|
first_started_ns + VulkanPresentProgressGate::kStallThresholdNs, true,
|
|
&report));
|
|
EXPECT_EQ(report.call_sequence, first_sequence);
|
|
gate.NotifyCallEnd(first_sequence, 0);
|
|
EXPECT_FALSE(gate.Poll(
|
|
first_started_ns + VulkanPresentProgressGate::kStallThresholdNs + 1,
|
|
true, &report));
|
|
|
|
const uint64_t second_started_ns =
|
|
first_started_ns + VulkanPresentProgressGate::kStallThresholdNs + 100;
|
|
const uint64_t second_sequence =
|
|
gate.NotifyCallBegin("vkQueueWaitIdle", second_started_ns, 8180);
|
|
ASSERT_NE(second_sequence, 0u);
|
|
ASSERT_TRUE(gate.Poll(
|
|
second_started_ns + VulkanPresentProgressGate::kStallThresholdNs, true,
|
|
&report));
|
|
EXPECT_EQ(report.stage, VulkanPresentStallStage::kInsideVulkanCall);
|
|
EXPECT_EQ(report.call_sequence, second_sequence);
|
|
}
|
|
|
|
TEST(VulkanPresentProgressGateTest,
|
|
RecentHostPresentDoesNotHideExistingRenderGap) {
|
|
VulkanPresentProgressGate gate;
|
|
ASSERT_TRUE(gate.Activate());
|
|
gate.NotifyFramePresented(kFirstFrameTicksNs, 15);
|
|
const uint64_t host_started_ns =
|
|
kFirstFrameTicksNs + VulkanPresentProgressGate::kStallThresholdNs - 100;
|
|
gate.NotifyHostPresentBegin(host_started_ns);
|
|
|
|
VulkanPresentStallReport report;
|
|
ASSERT_TRUE(gate.Poll(
|
|
kFirstFrameTicksNs + VulkanPresentProgressGate::kStallThresholdNs, true,
|
|
&report));
|
|
EXPECT_EQ(report.stage, VulkanPresentStallStage::kBeforeHostPresent);
|
|
|
|
ASSERT_TRUE(gate.Poll(
|
|
host_started_ns + VulkanPresentProgressGate::kStallThresholdNs, true,
|
|
&report));
|
|
EXPECT_EQ(report.stage, VulkanPresentStallStage::kInsideHostPresent);
|
|
EXPECT_EQ(report.host_present_count, 1u);
|
|
}
|
|
|
|
TEST(VulkanPresentProgressGateTest, CompletedCallDoesNotMaskRenderGap) {
|
|
VulkanPresentProgressGate gate;
|
|
ASSERT_TRUE(gate.Activate());
|
|
gate.NotifyFramePresented(kFirstFrameTicksNs, 4);
|
|
const uint64_t sequence =
|
|
gate.NotifyCallBegin("vkQueueSubmit", kFirstFrameTicksNs + 100, 99);
|
|
ASSERT_NE(sequence, 0u);
|
|
gate.NotifyCallEnd(sequence, 0);
|
|
|
|
VulkanPresentStallReport report;
|
|
ASSERT_TRUE(gate.Poll(
|
|
kFirstFrameTicksNs + VulkanPresentProgressGate::kStallThresholdNs, true,
|
|
&report));
|
|
EXPECT_EQ(report.stage, VulkanPresentStallStage::kBeforeHostPresent);
|
|
EXPECT_EQ(report.call_name, nullptr);
|
|
EXPECT_STREQ(report.last_completed_call_name, "vkQueueSubmit");
|
|
EXPECT_EQ(report.last_completed_call_result, 0);
|
|
}
|
|
|
|
TEST(VulkanPresentProgressGateTest,
|
|
ReportsCoherentRenderThreadCompletionMetadata) {
|
|
VulkanPresentProgressGate gate;
|
|
ASSERT_TRUE(gate.Activate());
|
|
constexpr uint64_t kRenderThreadId = 9090;
|
|
gate.NotifyFramePresented(kFirstFrameTicksNs, 16, kRenderThreadId);
|
|
constexpr uint64_t kCallStartedNs = kFirstFrameTicksNs + 100;
|
|
constexpr uint64_t kCallCompletedNs = kCallStartedNs + 50;
|
|
constexpr int32_t kCallResult = -7;
|
|
const uint64_t sequence =
|
|
gate.NotifyCallBegin("vkResetFences", kCallStartedNs, kRenderThreadId);
|
|
ASSERT_NE(sequence, 0u);
|
|
gate.NotifyCallEnd(sequence, kCallResult, kCallCompletedNs, kRenderThreadId);
|
|
|
|
VulkanPresentStallReport report;
|
|
ASSERT_TRUE(gate.Poll(
|
|
kFirstFrameTicksNs + VulkanPresentProgressGate::kStallThresholdNs, true,
|
|
&report));
|
|
EXPECT_EQ(report.stage, VulkanPresentStallStage::kBeforeHostPresent);
|
|
EXPECT_EQ(report.last_present_thread_id, kRenderThreadId);
|
|
EXPECT_STREQ(report.last_completed_call_name, "vkResetFences");
|
|
EXPECT_EQ(report.last_completed_call_sequence, sequence);
|
|
EXPECT_EQ(report.last_completed_call_thread_id, kRenderThreadId);
|
|
EXPECT_EQ(report.last_completed_call_started_ns, kCallStartedNs);
|
|
EXPECT_EQ(report.last_completed_call_completed_ns, kCallCompletedNs);
|
|
EXPECT_EQ(report.last_completed_call_result, kCallResult);
|
|
}
|
|
|
|
TEST(VulkanPresentProgressGateTest,
|
|
WorkerCompletionDoesNotOverwriteRenderThreadRecord) {
|
|
VulkanPresentProgressGate gate;
|
|
ASSERT_TRUE(gate.Activate());
|
|
constexpr uint64_t kRenderThreadId = 9191;
|
|
constexpr uint64_t kWorkerThreadId = 9292;
|
|
gate.NotifyFramePresented(kFirstFrameTicksNs, 17, kRenderThreadId);
|
|
|
|
constexpr uint64_t kRenderCallStartedNs = kFirstFrameTicksNs + 100;
|
|
constexpr uint64_t kRenderCallCompletedNs = kRenderCallStartedNs + 50;
|
|
constexpr int32_t kRenderCallResult = -3;
|
|
const uint64_t render_sequence = gate.NotifyCallBegin(
|
|
"vkResetCommandPool", kRenderCallStartedNs, kRenderThreadId);
|
|
ASSERT_NE(render_sequence, 0u);
|
|
gate.NotifyCallEnd(render_sequence, kRenderCallResult,
|
|
kRenderCallCompletedNs, kRenderThreadId);
|
|
|
|
constexpr uint64_t kWorkerCallStartedNs = kRenderCallCompletedNs + 50;
|
|
constexpr uint64_t kWorkerCallCompletedNs = kWorkerCallStartedNs + 50;
|
|
const uint64_t worker_sequence = gate.NotifyCallBegin(
|
|
"vkWaitSemaphores", kWorkerCallStartedNs, kWorkerThreadId);
|
|
ASSERT_NE(worker_sequence, 0u);
|
|
gate.NotifyCallEnd(worker_sequence, 0, kWorkerCallCompletedNs,
|
|
kWorkerThreadId);
|
|
|
|
VulkanPresentStallReport report;
|
|
ASSERT_TRUE(gate.Poll(
|
|
kFirstFrameTicksNs + VulkanPresentProgressGate::kStallThresholdNs, true,
|
|
&report));
|
|
EXPECT_EQ(report.stage, VulkanPresentStallStage::kBeforeHostPresent);
|
|
EXPECT_EQ(report.last_present_thread_id, kRenderThreadId);
|
|
EXPECT_STREQ(report.last_completed_call_name, "vkResetCommandPool");
|
|
EXPECT_EQ(report.last_completed_call_sequence, render_sequence);
|
|
EXPECT_EQ(report.last_completed_call_thread_id, kRenderThreadId);
|
|
EXPECT_EQ(report.last_completed_call_started_ns, kRenderCallStartedNs);
|
|
EXPECT_EQ(report.last_completed_call_completed_ns,
|
|
kRenderCallCompletedNs);
|
|
EXPECT_EQ(report.last_completed_call_result, kRenderCallResult);
|
|
}
|
|
|
|
TEST(VulkanPresentProgressGateTest,
|
|
CompletedCallFromOldLifecycleIsNotReported) {
|
|
VulkanPresentProgressGate gate;
|
|
ASSERT_TRUE(gate.Activate());
|
|
constexpr uint64_t kRenderThreadId = 9393;
|
|
gate.NotifyFramePresented(kFirstFrameTicksNs, 18, kRenderThreadId);
|
|
const uint64_t sequence = gate.NotifyCallBegin(
|
|
"vkResetFences", kFirstFrameTicksNs + 100, kRenderThreadId);
|
|
ASSERT_NE(sequence, 0u);
|
|
gate.NotifyCallEnd(sequence, 0, kFirstFrameTicksNs + 150,
|
|
kRenderThreadId);
|
|
gate.Deactivate();
|
|
|
|
ASSERT_TRUE(gate.Activate());
|
|
constexpr uint64_t kNextFrameTicksNs = kFirstFrameTicksNs + 1000;
|
|
gate.NotifyFramePresented(kNextFrameTicksNs, 1, kRenderThreadId);
|
|
VulkanPresentStallReport report;
|
|
ASSERT_TRUE(gate.Poll(
|
|
kNextFrameTicksNs + VulkanPresentProgressGate::kStallThresholdNs, true,
|
|
&report));
|
|
EXPECT_EQ(report.stage, VulkanPresentStallStage::kBeforeHostPresent);
|
|
EXPECT_TRUE(report.last_completed_call_snapshot_coherent);
|
|
EXPECT_EQ(report.last_completed_call_name, nullptr);
|
|
EXPECT_EQ(report.last_completed_call_sequence, 0u);
|
|
}
|
|
|
|
TEST(VulkanPresentProgressGateTest, FailedHostPresentIsNotFrameProgress) {
|
|
VulkanPresentProgressGate gate;
|
|
ASSERT_TRUE(gate.Activate());
|
|
gate.NotifyFramePresented(kFirstFrameTicksNs, 5);
|
|
const uint64_t sequence =
|
|
gate.NotifyHostPresentBegin(kFirstFrameTicksNs + 100);
|
|
ASSERT_NE(sequence, 0u);
|
|
gate.NotifyHostPresentEnd(sequence);
|
|
|
|
VulkanPresentStallReport report;
|
|
ASSERT_TRUE(gate.Poll(
|
|
kFirstFrameTicksNs + VulkanPresentProgressGate::kStallThresholdNs, true,
|
|
&report));
|
|
EXPECT_EQ(report.stage, VulkanPresentStallStage::kBeforeHostPresent);
|
|
EXPECT_EQ(report.frame_count, 5u);
|
|
EXPECT_EQ(report.host_present_count, 1u);
|
|
}
|
|
|
|
TEST(VulkanPresentProgressGateTest, NewProgressClearsReportedStall) {
|
|
VulkanPresentProgressGate gate;
|
|
ASSERT_TRUE(gate.Activate());
|
|
gate.NotifyFramePresented(kFirstFrameTicksNs, 1);
|
|
|
|
VulkanPresentStallReport report;
|
|
ASSERT_TRUE(gate.Poll(
|
|
kFirstFrameTicksNs + VulkanPresentProgressGate::kStallThresholdNs, true,
|
|
&report));
|
|
|
|
constexpr uint64_t kNextHostCallTicksNs = 7000000000ULL;
|
|
const uint64_t sequence =
|
|
gate.NotifyHostPresentBegin(kNextHostCallTicksNs);
|
|
ASSERT_NE(sequence, 0u);
|
|
gate.NotifyHostPresentEnd(sequence);
|
|
gate.NotifyFramePresented(kNextHostCallTicksNs + 20, 2);
|
|
ASSERT_TRUE(gate.Poll(
|
|
kNextHostCallTicksNs + 20 + VulkanPresentProgressGate::kStallThresholdNs,
|
|
true, &report));
|
|
EXPECT_EQ(report.frame_count, 2u);
|
|
}
|
|
|
|
TEST(VulkanPresentProgressGateTest, SuspendedWindowDoesNotConsumeReport) {
|
|
VulkanPresentProgressGate gate;
|
|
ASSERT_TRUE(gate.Activate());
|
|
gate.NotifyFramePresented(kFirstFrameTicksNs, 1);
|
|
const uint64_t stalled_ticks =
|
|
kFirstFrameTicksNs + VulkanPresentProgressGate::kStallThresholdNs;
|
|
|
|
VulkanPresentStallReport report;
|
|
EXPECT_FALSE(gate.Poll(stalled_ticks, false, &report));
|
|
EXPECT_TRUE(gate.Poll(stalled_ticks, true, &report));
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace window
|
|
} // namespace mocktail
|