Vulkan'da GPU breadcrumb'ları: VK_AMD_buffer_marker ve VK_NV_device_diagnostic_checkpoints

vkQueueSubmit kilitlendiğinde veya vkGetFenceStatus hiç ateşlenmediğinde soru hangi komutun takıldığıdır. Shader printf yardım etmez — GPU oraya hiç ulaşmadı. Breadcrumb’lar farklı çözer: her command buffer çalışırken bilinen bir buffer’a marker yazar; hang’den sonra son yazılan marker GPU’nun tam olarak nerede durduğunu söyler. İki vendor uzantısı sağlar: VK_AMD_buffer_marker ve VK_NV_device_diagnostic_checkpoints.

VK_AMD_buffer_marker — pipeline noktasında değer yaz

marker.cpp
// hang'i atlatan host-visible buffer:
//   buf = VkBuffer + HOST_VISIBLE|COHERENT bellek, bir kez map'lenmiş

vkCmdWriteBufferMarkerAMD(cmd,
    vk::PipelineStageFlagBits::eAllCommands,  // ne zaman yazılacağı
    markerBuf, offset, /*marker*/ frameTag);
// → pipeline bu cmd buffer'da bu stage'e ulaştığında,
//   'frameTag' markerBuf'a iner — CPU'ya anında görünür

Draw/dispatch’ler arasına serpin; inen son marker = tamamlanan son stage. Hang’ler kendini ele verir.

VK_NV_device_diagnostic_checkpoints — otomatik checkpoint’ler

checkpoint.cpp
// komut kaydı sırasında — app-görünür yazım gerekmez:
vkCmdSetCheckpointNV(cmd, (const void*)myTag);   // tag = void* / int

// submit tarafında (veya timeout'tan sonra):
uint32_t n = 0;
dev.getQueueCheckpointDataNV(queue, &n, nullptr);
std::vector<vk::CheckpointDataNV> cps(n);
dev.getQueueCheckpointDataNV(queue, &n, cps.data());
// her entry: {stage, pCheckpointMarker} — queue'nun
// *her checkpoint'li submission için* son ulaştığı stage

getQueueCheckpointDataNV anahtar çağrıdır — GPU’nun geçtiği checkpoint’leri stage mask ile geri okur. pipelineStage‘i ayarladığınızla eşleşen son entry öldüğü yerdir.

Yine de çöktüğünde

crash.txt
breadcrumb'lı hang:     yazılan son marker = tamamlanan son stage —
                        hang *sonraki* komuttadır
crash → DEVICE_LOST:    kalıcı-map'li buffer'daki breadcrumb'lar bazı
                        sürücülerde device loss'u atlatır —
                        fault callback ateşlendikten sonra okuyun
ikisi:                  VK_EXT_device_fault (DEVICE_LOST yazısı) ile
                        birleştirip tam otopsi yapın

Pratik tarif

watchdog.cpp
// marker halkası, uçuşta olan her submission için bir:
struct Breadcrumb { uint64_t tag; uint64_t stage; };
// map'li buffer, kalıcı:
auto* crumbs = (Breadcrumb*)dev.mapMemory(mem, 0, size);

cmd.writeBufferMarkerAMD(eBottomOfPipe, buf,
                         offsetof(Breadcrumb,stage), myTag);
// … draw'lar …
cmd.writeBufferMarkerAMD(eBottomOfPipe, buf,
                         offsetof(Breadcrumb,tag),  myTag);
// sonra bir watchdog thread'inde:
while (true) {
    if (fenceTimedOut && crumbs[last].tag != expected)
        logHang(crumbs[last]);   // tamamlanan son stage = suçlu
}

Pratik kurallar

  • VK_AMD_buffer_marker yalnızca AMD; VK_NV_device_diagnostic_checkpoints yalnızca NVIDIA — iki kod yolu veya genel bir wrapper istersiniz.
  • Marker buffer HOST_VISIBLE+HOST_COHERENT olmalı ki GPU hang’deyken CPU okuyabilsin — DEVICE_LOCAL writeback işe yaramaz.
  • eBottomOfPipe/eAllCommands stage kullanın ki marker ancak önceki iş gerçekten bittiğinde flush olsun — erken bir stage ilerleme hakkında yalan söyler.
  • vkCmdSetCheckpointNV‘nin tag’i ham void*‘dir — tag → “N’inci submit edilen command buffer, draw i” eşleme tablosu tutun ki fault yerini çözebilesiniz.
  • Gerçek bir GPU crash’i (hang değil) için VK_EXT_device_fault + VK_NV_device_diagnostic_checkpoints kombinasyondur — fault adresi, breadcrumb’lar komutu verir.

Check out similar posts by category: Vulkan C++