Bir DMA-Buf import ettiniz (external_memory_dma_buf yazısı) — ancak
decoder onu kendi queue’sunda, yabancı bir sürücüde yazdı. Vulkan’ın
bellek modeli şöyle der: yazmalar, sahipliği transfer etmediğiniz
sürece yalnızca yazan queue family’ye görünürdür.
VK_EXT_queue_family_foreign, sentinel family indeksi
VK_QUEUE_FAMILY_FOREIGN_EXT‘i — “en son kim dokunduysa” queue’su —
ve buffer’ı kendi queue family’nize taşımak için semaphore/barrier
mekaniğini verir.
Sorun
decoder queue'su DMA-Buf'a yazar → grafik queue'nuz örnekler
↑ Vulkan'ın bellek modelinde farklı
bir "queue family" —
yazmaların görünür olması garanti değilTransfer olmadan örnekleme UB’dir — çoğu zaman şans eseri çalışır, bazen bayat veri döndürür.
Transfer
// decoder tarafı (kavramsal — exporter bir semaphore sinyaller
// veya bittiğini bilirsiniz):
// DMA-Buf, VK_QUEUE_FAMILY_FOREIGN_EXT'e "ait"tir
// sizin queue'nuz — bir release/acquire çifti veya iki alanlı barrier:
vk::ImageMemoryBarrier imb{};
imb.srcQueueFamilyIndex = VK_QUEUE_FAMILY_FOREIGN_EXT; // önce: foreign
imb.dstQueueFamilyIndex = myGraphicsFamily; // şimdi: benim
imb.image = importedImg;
imb.oldLayout = vk::ImageLayout::eGeneral;
imb.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
// srcAccess = foreign tarafın yaptığı — genelde senkronu taşıyan
// bir semaphore wait üzerinden eMemoryWrite
cmd.pipelineBarrier(eTopOfPipe, eFragmentShader, {}, {}, {}, {imb});srcQueueFamilyIndex = VK_QUEUE_FAMILY_FOREIGN_EXT işin püf noktasıdır:
“hangi family’nin yazdığını bilmiyorum — al gitsin” der. Exporter’ın
tamamlanmasını taşıyan bir semaphore wait ile eşleştiğinde yazma artık
görünürdür.
Semaphore yolu
// decoder sinyaller; siz wait + acquire edersiniz:
vk::SubmitInfo si{};
si.waitSemaphoreCount = 1;
si.pWaitSemaphores = &decoderSem; // VA-API/V4L2 fence'inden
si.pWaitDstStageMask = &fragmentStage;
// … yukarıdaki barrier aynı cmd buffer'a girer …
queue.submit(si);Pratikte VAAPI/V4L2, VkSemaphore‘a dönüşen bir sync fd üzerinden
tamamlanma sinyaller — vkGetSemaphoreFdKHR/vkImportSemaphoreFdKHR
ile içeri alınır.
Uçtan uca akış
FFmpeg decode bitti → AVDRMFrameDescriptor plane'lerin fd'lerini taşır
→ DMA-Buf yoluyla VkImage olarak import et
→ barrier: FOREIGN_EXT → grafik queue'su, eGeneral → eShaderReadOnly
→ grid shader'da örnekle
→ kare emekliliğinde: geri ver (dst=FOREIGN_EXT) veya VkImage'i
doğrudan düşür — DMA-Buf decoder'ın havuzuna dönerPratik kurallar
VK_QUEUE_FAMILY_FOREIGN_EXTbir sözde family‘dir —queueFamilyProperties‘te asla görünmez; yalnızcasrcQueueFamilyIndex/dstQueueFamilyIndexalanlarına girer.- Barrier tek başına sıralama taşımaz — semaphore wait ile eşleştirin ki okumanız başlamadan önce foreign yazma tamamlanmış olsun.
- Bitince release edin:
dst=FOREIGN_EXTbarrier’ı buffer’ı geri verir — yalnızca DMA-Buf yeniden kullanılmayıp yok ediliyorsa atlayın. - Sürücü ve donanımın gerçekten aynı queue family’yi paylaştığı aynı cihaz import’larında barrier no-op’tur — ancak spec yine de bildirimi gerektirir.
- Atlarsanız belirti aralıklı bayat karelerdir — klasik “ilk kare yeşil, sonraki kareler iyi” video-import bug’ı.