Vulkan'da VK_KHR_calibrated_timestamps ile GPU ve CPU saatlerini senkronize etme

vkCmdWriteTimestamp size cihaz saat alanında bir sayı verir. clock_gettime(CLOCK_MONOTONIC) CPU zamanı verir. Bunları naifçe karşılaştırmak anlamsızdır — cihaz saati kayabilir, farklı hızda çalışabilir veya bağlantısız olabilir. VK_KHR_calibrated_timestamps (önceden VK_EXT_calibrated_timestamps) sürücüden esasen aynı anda iki saati ister, böylece çevirebilirsiniz.

Neden

why.txt
GPU timestamp:  "frame done at device_t=98237462"  ← bilinmeyen epoch
CPU timestamp:  "at 14:03:22.417123"               ← CLOCK_MONOTONIC
kalibre edilmiş çift: (device_t, monotonic_t) birlikte yakalandı → korele et

Olmadan: sadece GPU↔GPU veya CPU↔CPU fark alabilirsiniz, asla çapraz değil.

Alanları keşfetme

domains.cpp
uint32_t n = 0;
phys.getCalibrateableTimeDomainsKHR(&n, nullptr);
std::vector<vk::TimeDomainKHR> doms(n);
phys.getCalibrateableTimeDomainsKHR(&n, doms.data());
// eDevice            — vkCmdWriteTimestamp'ın alanı
// eClockMonotonic    — Linux CLOCK_MONOTONIC
// eClockMonotonicRaw — uyumamış monotonic
// eQueryPerformanceCounter — Windows QPC
// ePresentStageLocalExt / eSwapchainLocalExt — present_timing alanları

Kalibre örneği alma

calibrate.cpp
vk::CalibratedTimestampInfoKHR infos[] = {
    {vk::TimeDomainKHR::eDevice},
    {vk::TimeDomainKHR::eClockMonotonic},
};
uint64_t ts[2];  uint64_t maxDev;
dev.getCalibratedTimestampsKHR(2, infos, ts, &maxDev);

// ts[0] = şimdiki cihaz saati, ts[1] = şimdiki CLOCK_MONOTONIC,
// ikisi de "sürücünün yapabildiği kadar yakın" yakalanır.
// maxDev = iki okuma arasındaki en kötü durum skew'i (ns).

Artık gelecekteki her vkCmdWriteTimestamp sonucu T duvar saatine eşlenir: wall ≈ ts[1] + (T - ts[0]) — çağrılar arasında cihaz saatinin ölçülebilir kaymadığını varsayarak (her frame’de taze çift alın).

Üçgeni tamamlama

VK_EXT_present_timing‘in VkPresentStageTimeEXT.time‘ı swapchain-yerel bir alan (eSwapchainLocalExt) kullanır — timeDomainId‘ye eşlemesini vkGetSwapchainTimeDomainPropertiesEXT ile sorgular, sonra o alanı da kalibre edersiniz:

loop.txt
submit ──► vkCmdWriteTimestamp      ──►  eDevice alanı
        └► vkGetPastPresentationTiming ─► eSwapchainLocalExt
        └► wp_presentation / CLOCK_MONOTONIC
üçünde de vkGetCalibratedTimestampsKHR → tek zaman çizelgesi, gerçek gecikme

Pratik kurallar

  • Present-timing’e korele ediyorsanız frame başına taze kalibre çifti alın — saniyeler içindeki saat kayması görünür.
  • maxDeviation hata çubuğunuzdur — ölçüm doğruluğu ihtiyacınızdan büyükse, o sürücüde korelasyon güvenilmezdir.
  • eDevice ve eClockMonotonic minimal faydalı çifttir; VK_EXT_present_timing ile birleştirirken eSwapchainLocalExt ekleyin.
  • Tüm cihazlar tüm alanları açmaz — varsaymayın, sorgulayın.
  • Saf “GPU ne kadar sürdü” için eDevice‘da kalın — kalibrasyon sadece CPU/ekran saatlerine geçerken gerekli.

Check out similar posts by category: Vulkan C++