VK_EXT_swapchain_maintenance1 açıklaması: present fence'leri, ölçekleme modları, ertelenmiş imha

Orijinal swapchain API’sinde er geç karşılaşacağınız üç boşluk vardı: present motorunun bir frame’le işinin ne zaman bittiğini bilemezdiniz (sadece render’ın bittiğini bilirdiniz), swapchain’i yeniden oluşturmadan present modunu veya ölçeklemeyi değiştiremezdiniz ve bir swapchain’i yok etmek, presentasyon motoru hâlâ okurken image’larını da yok ederdi. VK_EXT_swapchain_maintenance1 (artık VK_KHR_swapchain_maintenance1 olarak da core-aliased) tek bir uzantıyla dört deliği de yamıyor.

Dört özellik

features.txt
1. present fence'leri    — vkQueuePresentKHR bir VkFence'i sinyalleyebilir
2. present-başına modlar — yeniden oluşturmadan FIFO↔MAILBOX geçişi
3. present ölçekleme     — kompozitör/GPU image'ı pencere boyutuna ölçekler
4. ertelenmiş imha       — vkReleaseSwapchainImagesEXT, vkDestroySwapchainKHR
   sonrası bile image'ları presenter için canlı tut

Özelliği açın + yüzey-başına desteği sorgulayın:

feature.cpp
vk::PhysicalDeviceSwapchainMaintenance1FeaturesEXT feat{};
feat.swapchainMaintenance1 = VK_TRUE;
// vkCreateDevice'a zincirle

// Yüzey başına: hangi ölçekleme/yerçekimi/mod-uyumluluğunu destekler?
vk::SurfacePresentScalingCapabilitiesEXT scaleCaps{};
vk::SurfacePresentModeCompatibilityEXT   modeCompat{};
vk::SurfaceCapabilities2KHR caps2{};
caps2.pNext = &scaleCaps;  scaleCaps.pNext = &modeCompat;
dev.getSurfaceCapabilities2KHR(
    vk::PhysicalDeviceSurfaceInfo2KHR{surf}, &caps2);
// scaleCaps.supportedPresentScaling — eOneToOne/eAspectRatioStretched/eStretched
// scaleCaps.supportedPresentGravityX/Y — eMin/eCentered/eMax
// modeCompat.presentModeCount/pPresentModes — arasında geçiş yapabileceğiniz modlar

1. Present fence’leri — frame’in gerçekten gittiğini bilin

fence.cpp
vk::SwapchainPresentFenceInfoEXT fences{};
fences.swapchainCount = 1;
fences.pFences        = &presentFence;      // swapchain başına bir tane

vk::PresentInfoKHR pi{};
pi.pNext = &fences;
// … waitSemaphores, swapchain, imageIndex …
queue.presentKHR(pi);

dev.waitForFences(presentFence, VK_TRUE, UINT64_MAX);
// artık presentasyon motoru image'la işini bitirdi —
// host'taki ilişkili frame-başına verileri güvenle yeniden kullanabilirsiniz.

Render fence’inde vkWaitForFences‘ten farkı: render fence render bittiğinde sinyaller; present fence presentasyon motoru image’ı bıraktığında sinyaller — fark, VK_EXT_present_timing‘in ölçtüğü gizli present-kuyruğu gecikmesidir.

2. Present-başına mod geçişi

modes.cpp
// Oluştururken: kullanabileceğiniz TÜM modları bildirin
vk::SwapchainPresentModesCreateInfoEXT pm{};
pm.presentModeCount = 2;
vk::PresentModeKHR modes[] = {eMailbox, eFifo};
pm.pPresentModes = modes;
sci.pNext = ±   // VkSwapchainCreateInfoKHR'ye zincirle

// Present anında — yeniden oluşturma yok, OUT_OF_DATE yok:
vk::SwapchainPresentModeInfoEXT mi{};
mi.swapchainCount = 1;
mi.pPresentModes  = &vk::PresentModeKHR::eMailbox;
pi.pNext = &mi;    // (present-fence bilgisiyle birlikte zincirleyin)

“Aktifken düşük-gecikme, boştayken güç-tasarruflu FIFO” için yararlı — frame başına geçiş, takılma yok.

3. Present ölçekleme — presenter’ın sizin için yeniden boyutlandırmasına izin verin

scaling.cpp
vk::SwapchainPresentScalingCreateInfoEXT sc{};
sc.scalingBehavior = vk::PresentScalingFlagBitsEXT::eAspectRatioStretched;
sc.presentGravityX = vk::PresentGravityFlagBitsEXT::eCentered;
sc.presentGravityY = vk::PresentGravityFlagBitsEXT::eCentered;
sci.pNext = ≻   // VkSwapchainCreateInfoKHR'ye zincirle

// Artık 1280x720 swapchain 1920x1080 pencereye sunabilir —
// display motoru yükseltir+ortalar, sıfır shader maliyeti.

Bir video duvarı için şu anlama gelir: akış çözünürlüğünde render edin, display motorunun germesine izin verin — yeniden boyutlandırmada UI yeniden-düzenleme geçişi gerekmez.

4. Ertelenmiş image imhası

release.cpp
// Eski: vkDestroySwapchainKHR, presenter hâlâ
// tutarken bile image'ları anında öldürürdü → dikkatli idle-beklemeler gerektirirdi.
// Yeni: SİZİN referanslarınızı bırakın ama present bitene kadar image'ların yaşamasına izin verin:
vk::ReleaseSwapchainImagesInfoEXT rel{};
rel.swapchain     = swapchain;
rel.imageIndexCount = 3;
rel.pImageIndices   = indices;
dev.releaseSwapchainImagesEXT(rel);
// swapchain nesnesi hâlâ var; image'lar presenter bitince serbest.

Pratik kurallar

  • swapchainMaintenance1 VK_KHR_swapchain cihaz-uzantısı bölgesindedir — VkPhysicalDeviceSwapchainMaintenance1FeaturesEXT kontrol edin.
  • Present fence’leri sadece swapchain başına uçuştaki en eski present’te ateşlenir — present-tarafı temizlik için “frame N kaynaklarına dokunmadan önce wait-idle"ın yerini alır.
  • Present-mod uyumluluğu önceden bildirilmeli — SwapchainPresentModesCreateInfoEXT‘te olmayan bir moda geçiş yapılamaz.
  • Ölçekleme sadece imageExtent ile pencere boyutu arasındaki uyumsuzluğu kapsar — gerçek surface extent değişikliklerinde vkAcquireNextImageKHR yeniden boyutlandırmasının yerini almaz.

Check out similar posts by category: Vulkan C++