18-05-26 result

This commit is contained in:
Johanness
2026-05-18 01:26:21 +03:00
parent ea7e73d6a4
commit ad215f32bc
34 changed files with 1616 additions and 395 deletions
+368 -15
View File
@@ -45,17 +45,46 @@ struct PerfStats
uint64_t frames = 0;
uint64_t feedReadTicks = 0;
uint64_t uploadDecodeTicks = 0;
uint64_t stageCopyTicks = 0;
uint64_t uploadRecordTicks = 0;
uint64_t submitPresentTicks = 0;
uint64_t idleDelayTicks = 0;
uint64_t frameTicks = 0;
};
struct FramePerfStats
{
uint64_t eventTicks = 0;
uint64_t fenceWaitTicks = 0;
uint64_t feedReadTicks = 0;
uint64_t stageCopyTicks = 0;
uint64_t maxStageCopyTicks = 0;
uint64_t maxStageCopyBytes = 0;
uint32_t maxStageCopyFeed = 0;
uint32_t stageCopies = 0;
uint32_t v210StageCopies = 0;
uint64_t uploadRecordTicks = 0;
uint64_t layoutTicks = 0;
uint64_t imguiTicks = 0;
uint64_t drawRecordTicks = 0;
uint64_t acquireTicks = 0;
uint64_t submitPresentTicks = 0;
uint64_t idleDelayTicks = 0;
};
struct FeedPerfStats
{
uint64_t updates = 0;
uint64_t uploads = 0;
uint64_t deferredUploads = 0;
uint64_t repeats = 0;
uint64_t skippedGrains = 0;
uint64_t lastGrain = 0;
uint64_t lastUploadTicks = 0;
uint64_t uploadIntervalTicks = 0;
uint64_t minUploadIntervalTicks = UINT64_MAX;
uint64_t maxUploadIntervalTicks = 0;
uint64_t uploadIntervals = 0;
bool hasLastGrain = false;
};
@@ -721,6 +750,11 @@ int main(int argc, char* argv[])
std::vector<bool> v210FeedReady(feedCount);
std::vector<uint64_t> uploadedVersions(feedCount);
std::vector<bool> feedUploadNeeded(feedCount);
std::vector<const VideoFrame*> pendingFrames(feedCount);
std::vector<uint64_t> pendingVersions(feedCount);
std::vector<bool> pendingUploadNeeded(feedCount);
std::vector<double> feedUploadCredits(feedCount, 1.0);
uint64_t lastUploadPaceTicks = SDL_GetPerformanceCounter();
std::fill(
uploadedVersions.begin(),
@@ -1026,9 +1060,14 @@ int main(int argc, char* argv[])
const Uint64 frameStartTicks = SDL_GetTicks();
const uint64_t perfFrameStartTicks =
SDL_GetPerformanceCounter();
FramePerfStats framePerf;
uint64_t perfSectionStartTicks = 0;
SDL_Event event;
perfSectionStartTicks =
SDL_GetPerformanceCounter();
while (SDL_PollEvent(&event))
{
ImGui_ImplSDL3_ProcessEvent(&event);
@@ -1048,11 +1087,18 @@ int main(int argc, char* argv[])
if (event.key.key == SDLK_ESCAPE)
{
g_running = false;
}
}
break;
}
}
if (config.logPerf)
{
framePerf.eventTicks +=
SDL_GetPerformanceCounter() -
perfSectionStartTicks;
}
// ---- resize handling ----
if (framebufferResized)
@@ -1124,7 +1170,7 @@ int main(int argc, char* argv[])
// ---- frame timing ----
uint64_t perfSectionStartTicks =
perfSectionStartTicks =
SDL_GetPerformanceCounter();
vkWaitForFences(
@@ -1142,9 +1188,12 @@ int main(int argc, char* argv[])
if (config.logPerf)
{
perfStats.submitPresentTicks +=
const uint64_t elapsed =
SDL_GetPerformanceCounter() -
perfSectionStartTicks;
perfStats.submitPresentTicks += elapsed;
framePerf.fenceWaitTicks += elapsed;
framePerf.submitPresentTicks += elapsed;
}
++frameCounter;
@@ -1178,6 +1227,47 @@ int main(int argc, char* argv[])
feedUploadNeeded.end(),
false
);
std::fill(
pendingFrames.begin(),
pendingFrames.end(),
nullptr
);
std::fill(
pendingUploadNeeded.begin(),
pendingUploadNeeded.end(),
false
);
const uint64_t uploadPaceTicks =
SDL_GetPerformanceCounter();
const double uploadPaceDeltaSeconds =
static_cast<double>(
uploadPaceTicks - lastUploadPaceTicks) /
static_cast<double>(perfFrequency);
lastUploadPaceTicks = uploadPaceTicks;
if (config.paceUploads)
{
for (uint32_t i = 0; i < feedCount; ++i)
{
if (!feeds[i]->hasFrameRate())
{
continue;
}
const double rate =
std::min(
feeds[i]->frameRate(),
static_cast<double>(config.fpsCap)
);
feedUploadCredits[i] =
std::min(
2.0,
feedUploadCredits[i] +
rate * uploadPaceDeltaSeconds
);
}
}
for (uint32_t i = 0; i < feedCount; ++i)
{
@@ -1193,9 +1283,11 @@ int main(int argc, char* argv[])
if (config.logPerf)
{
perfStats.feedReadTicks +=
const uint64_t elapsed =
SDL_GetPerformanceCounter() -
perfSectionStartTicks;
perfStats.feedReadTicks += elapsed;
framePerf.feedReadTicks += elapsed;
if (uploadNeeded)
{
@@ -1231,10 +1323,55 @@ int main(int argc, char* argv[])
continue;
}
pendingFrames[i] = &frame;
pendingVersions[i] = version;
pendingUploadNeeded[i] = true;
}
const uint32_t maxV210Uploads =
config.maxV210UploadsPerFrame == 0
? feedCount
: config.maxV210UploadsPerFrame;
uint32_t v210UploadsThisFrame = 0;
const uint32_t uploadStart =
feedCount == 0 ? 0 : frameCounter % feedCount;
for (uint32_t offset = 0; offset < feedCount; ++offset)
{
const uint32_t i =
(uploadStart + offset) % feedCount;
if (!pendingUploadNeeded[i])
{
continue;
}
const bool isV210 = feeds[i]->hasV210();
if (config.paceUploads &&
isV210 &&
feeds[i]->hasFrameRate() &&
feedUploadCredits[i] < 1.0)
{
if (config.logPerf)
{
++feedPerfStats[i].deferredUploads;
}
continue;
}
if (isV210 && v210UploadsThisFrame >= maxV210Uploads)
{
if (config.logPerf)
{
++feedPerfStats[i].deferredUploads;
}
continue;
}
perfSectionStartTicks =
SDL_GetPerformanceCounter();
if (feeds[i]->hasV210())
if (isV210)
{
if (!v210FeedReady[i])
{
@@ -1284,7 +1421,7 @@ int main(int argc, char* argv[])
else
{
copyFrameToFeedTextureStaging(
frame,
*pendingFrames[i],
imageSize,
feedTextures[i]
);
@@ -1292,17 +1429,79 @@ int main(int argc, char* argv[])
if (config.logPerf)
{
perfStats.uploadDecodeTicks +=
const uint64_t elapsed =
SDL_GetPerformanceCounter() -
perfSectionStartTicks;
perfStats.stageCopyTicks += elapsed;
perfStats.uploadDecodeTicks += elapsed;
framePerf.stageCopyTicks += elapsed;
++framePerf.stageCopies;
if (isV210)
{
++framePerf.v210StageCopies;
}
if (elapsed > framePerf.maxStageCopyTicks)
{
framePerf.maxStageCopyTicks = elapsed;
framePerf.maxStageCopyFeed = i + 1;
framePerf.maxStageCopyBytes =
isV210
? static_cast<uint64_t>(
feeds[i]->v210Stride()) *
feeds[i]->v210Height()
: static_cast<uint64_t>(imageSize);
}
}
uploadedVersions[i] = version;
uploadedVersions[i] = pendingVersions[i];
if (isV210)
{
++v210UploadsThisFrame;
if (config.paceUploads &&
feeds[i]->hasFrameRate())
{
feedUploadCredits[i] =
std::max(
0.0,
feedUploadCredits[i] - 1.0
);
}
}
if (config.logPerf)
{
++feedPerfStats[i].uploads;
const uint64_t uploadTicks =
SDL_GetPerformanceCounter();
if (feedPerfStats[i].lastUploadTicks != 0)
{
const uint64_t interval =
uploadTicks -
feedPerfStats[i].lastUploadTicks;
feedPerfStats[i].uploadIntervalTicks +=
interval;
feedPerfStats[i].minUploadIntervalTicks =
std::min(
feedPerfStats[i].minUploadIntervalTicks,
interval
);
feedPerfStats[i].maxUploadIntervalTicks =
std::max(
feedPerfStats[i].maxUploadIntervalTicks,
interval
);
++feedPerfStats[i].uploadIntervals;
}
feedPerfStats[i].lastUploadTicks = uploadTicks;
}
feedUploadNeeded[i] = true;
}
// ---- update vertex UVs for aspect ratio ----
perfSectionStartTicks =
SDL_GetPerformanceCounter();
VkExtent2D swapExtent = swapchain.extent();
const float gapX =
2.0f * TILE_GAP_PIXELS /
@@ -1349,8 +1548,18 @@ int main(int argc, char* argv[])
static_cast<size_t>(vbSize)
);
if (config.logPerf)
{
framePerf.layoutTicks +=
SDL_GetPerformanceCounter() -
perfSectionStartTicks;
}
// ---- ImGui frame ----
perfSectionStartTicks =
SDL_GetPerformanceCounter();
ImGui_ImplVulkan_NewFrame();
ImGui_ImplSDL3_NewFrame();
ImGui::NewFrame();
@@ -1364,6 +1573,13 @@ int main(int argc, char* argv[])
ImGui::Render();
ImDrawData* imguiDrawData = ImGui::GetDrawData();
if (config.logPerf)
{
framePerf.imguiTicks +=
SDL_GetPerformanceCounter() -
perfSectionStartTicks;
}
// ---- record upload commands ----
perfSectionStartTicks =
@@ -1431,9 +1647,12 @@ int main(int argc, char* argv[])
if (config.logPerf)
{
perfStats.uploadDecodeTicks +=
const uint64_t elapsed =
SDL_GetPerformanceCounter() -
perfSectionStartTicks;
perfStats.uploadRecordTicks += elapsed;
perfStats.uploadDecodeTicks += elapsed;
framePerf.uploadRecordTicks += elapsed;
}
// ---- acquire swapchain image ----
@@ -1453,6 +1672,13 @@ int main(int argc, char* argv[])
&imageIndex
);
if (config.logPerf)
{
framePerf.acquireTicks +=
SDL_GetPerformanceCounter() -
perfSectionStartTicks;
}
if (acquireResult == VK_ERROR_OUT_OF_DATE_KHR)
{
std::cout
@@ -1471,14 +1697,27 @@ int main(int argc, char* argv[])
);
}
perfSectionStartTicks =
SDL_GetPerformanceCounter();
recordDrawCmdBuf(
drawCmdBufs[imageIndex],
imageIndex,
imguiDrawData
);
if (config.logPerf)
{
framePerf.drawRecordTicks +=
SDL_GetPerformanceCounter() -
perfSectionStartTicks;
}
// ---- submit ----
perfSectionStartTicks =
SDL_GetPerformanceCounter();
VkPipelineStageFlags waitStage =
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
@@ -1554,9 +1793,11 @@ int main(int argc, char* argv[])
if (config.logPerf)
{
perfStats.submitPresentTicks +=
const uint64_t elapsed =
SDL_GetPerformanceCounter() -
perfSectionStartTicks;
perfStats.submitPresentTicks += elapsed;
framePerf.submitPresentTicks += elapsed;
}
const Uint64 frameElapsedTicks =
@@ -1575,9 +1816,11 @@ int main(int argc, char* argv[])
if (config.logPerf)
{
perfStats.idleDelayTicks +=
const uint64_t elapsed =
SDL_GetPerformanceCounter() -
perfSectionStartTicks;
perfStats.idleDelayTicks += elapsed;
framePerf.idleDelayTicks += elapsed;
}
}
@@ -1586,7 +1829,76 @@ int main(int argc, char* argv[])
++perfStats.frames;
const uint64_t now = SDL_GetPerformanceCounter();
perfStats.frameTicks += now - perfFrameStartTicks;
const uint64_t currentFrameTicks =
now - perfFrameStartTicks;
perfStats.frameTicks += currentFrameTicks;
const double invMs =
1000.0 /
static_cast<double>(perfFrequency);
if (currentFrameTicks * invMs > 25.0)
{
const uint64_t accountedTicks =
framePerf.eventTicks +
framePerf.fenceWaitTicks +
framePerf.feedReadTicks +
framePerf.stageCopyTicks +
framePerf.uploadRecordTicks +
framePerf.layoutTicks +
framePerf.imguiTicks +
framePerf.drawRecordTicks +
framePerf.acquireTicks +
framePerf.submitPresentTicks +
framePerf.idleDelayTicks;
const uint64_t otherTicks =
currentFrameTicks > accountedTicks
? currentFrameTicks - accountedTicks
: 0;
std::cout
<< "SPIKE frame="
<< (currentFrameTicks * invMs)
<< "ms event="
<< (framePerf.eventTicks * invMs)
<< "ms fence="
<< (framePerf.fenceWaitTicks * invMs)
<< "ms feedRead="
<< (framePerf.feedReadTicks * invMs)
<< "ms stageCopy="
<< (framePerf.stageCopyTicks * invMs)
<< "ms stageCopies="
<< framePerf.stageCopies
<< " v210Copies="
<< framePerf.v210StageCopies
<< " maxCopy=f"
<< framePerf.maxStageCopyFeed
<< ":"
<< (framePerf.maxStageCopyTicks * invMs)
<< "ms/"
<< (static_cast<double>(
framePerf.maxStageCopyBytes) /
(1024.0 * 1024.0))
<< "MiB"
<< " uploadRecord="
<< (framePerf.uploadRecordTicks * invMs)
<< "ms layout="
<< (framePerf.layoutTicks * invMs)
<< "ms imgui="
<< (framePerf.imguiTicks * invMs)
<< "ms drawRecord="
<< (framePerf.drawRecordTicks * invMs)
<< "ms acquire="
<< (framePerf.acquireTicks * invMs)
<< "ms submitPresent="
<< (framePerf.submitPresentTicks * invMs)
<< "ms idleDelay="
<< (framePerf.idleDelayTicks * invMs)
<< "ms other="
<< (otherTicks * invMs)
<< "ms"
<< std::endl;
}
const uint64_t elapsedTicks = now - lastPerfLogTicks;
@@ -1595,9 +1907,6 @@ int main(int argc, char* argv[])
const double elapsedSeconds =
static_cast<double>(elapsedTicks) /
static_cast<double>(perfFrequency);
const double invMs =
1000.0 /
static_cast<double>(perfFrequency);
const double frames =
static_cast<double>(perfStats.frames);
@@ -1607,6 +1916,10 @@ int main(int argc, char* argv[])
<< (perfStats.feedReadTicks * invMs / frames)
<< "ms uploadDecode="
<< (perfStats.uploadDecodeTicks * invMs / frames)
<< "ms stageCopy="
<< (perfStats.stageCopyTicks * invMs / frames)
<< "ms uploadRecord="
<< (perfStats.uploadRecordTicks * invMs / frames)
<< "ms submitPresent="
<< (perfStats.submitPresentTicks * invMs / frames)
<< "ms idleDelay="
@@ -1625,6 +1938,8 @@ int main(int argc, char* argv[])
<< feedRuntimeStatusName(
feeds[i]->status())
<< ":upd=" << feedPerfStats[i].updates
<< ",upl=" << feedPerfStats[i].uploads
<< ",def=" << feedPerfStats[i].deferredUploads
<< ",rep=" << feedPerfStats[i].repeats;
if (feedPerfStats[i].hasLastGrain)
@@ -1638,6 +1953,44 @@ int main(int argc, char* argv[])
}
std::cout << std::endl;
std::cout << "JITTER";
for (uint32_t i = 0; i < feedCount; ++i)
{
std::cout << " f" << (i + 1)
<< ":upl=" << feedPerfStats[i].uploads;
if (feedPerfStats[i].uploadIntervals > 0)
{
const double avgMs =
feedPerfStats[i].uploadIntervalTicks *
invMs /
static_cast<double>(
feedPerfStats[i].uploadIntervals);
const double minMs =
feedPerfStats[i].minUploadIntervalTicks *
invMs;
const double maxMs =
feedPerfStats[i].maxUploadIntervalTicks *
invMs;
std::cout
<< ",avg=" << avgMs
<< "ms,min=" << minMs
<< "ms,max=" << maxMs
<< "ms";
}
if (feeds[i]->hasFrameRate() &&
feeds[i]->frameRate() > 0.0)
{
std::cout
<< ",exp="
<< (1000.0 / feeds[i]->frameRate())
<< "ms";
}
}
std::cout << std::endl;
ThreadCpuSamples currentThreadCpuSamples =
collectThreadCpuSamples();
printThreadCpuPerf(