Example: VulkanExamples/p42_budget
Serideki post 42 (post 28: capability sorguları, post: bellek tipleri).
VkPhysicalDeviceMemoryProperties size heap boyutlarını söyler —
kutunun üstünde yazan 16GB. Söylemediği: o heap’in ne kadarının zaten
gittiği (diğer uygulamalar, compositor, kendi önceki
allocation’larınız) veya driver’ın size ne kadar vermeye istekli
olduğu. VK_EXT_memory_budget tek bir zincirlenmiş struct ile iki
boşluğu da kapatır:
main.cpp (excerpt)
vk::PhysicalDeviceMemoryBudgetPropertiesEXT budget{};
vk::PhysicalDeviceMemoryProperties2 mp{};
mp.pNext = &budget;
phys.getMemoryProperties2(&mp);
for (uint32_t i = 0; i < mp.memoryProperties.memoryHeapCount; ++i)
printf("heap%u size=%lluMB usage=%lluMB budget=%lluMB\n", i,
(unsigned long long)(mp.memoryProperties
.memoryHeaps[i].size >> 20),
(unsigned long long)(budget.heapUsage[i] >> 20),
(unsigned long long)(budget.heapBudget[i] >> 20));heapBudget[i]— driver’ın şu an allocate etmenize izin verdiği (heap boyutu − driver rezervasyonları − diğer süreçler).heapUsage[i]— şu an gerçekten allocate edilmiş olan.
Test Radeon’unda:
example.sh
--- before allocations ---
heap0 size=16128MB usage=0MB budget=15124MB flags=0x1 # VRAM
heap1 size=15540MB usage=0MB budget=15339MB flags=0x0 # GTT/host
heap2 size=256MB usage=0MB budget=54MB flags=0x1 # BAR carve-out
--- after 3x256MB device-local ---
heap0 size=16128MB usage=768MB budget=15124MB flags=0x1
İki öğretici ayrıntı:
- budget ≠ size: heap0’ın 16GB’ı 15.1GB bütçe gösterir — driver ~1GB’ı kendine ayırır (page table’lar, firmware, diğer istemciler). heap2 resizable-BAR penceresidir: 256MB heap ama yalnızca 54MB bütçe, yani çoğu kalıcı olarak rezerve.
- usage sizden fazlasını sayar:
heapUsagepaylaşılan heap’lerde sistem çapındadır — VRAM allocate eden başka bir uygulama burada görünür; bir uygulamanın heap boyutuna güvenmek yerine cache tahliye ederken veya büyütürken bütçeyi yeniden kontrol etmesi gerekmesinin tam nedeni budur.
Kontrol
check.py
# SPDX-License-Identifier: CC0-1.0
import re, subprocess
o = subprocess.run(["./app"], check=True, capture_output=True,
text=True).stdout
def parse(text):
return {i: (int(u), int(b)) for i, u, b in re.findall(
r"heap(\d+) size=\d+MB usage=(\d+)MB budget=(\d+)MB "
r"flags=0x1", text)}
before, _, after = o.partition("--- after 3x256MB device-local ---")
heaps_b = parse(before)
heaps_a = parse(after)
assert heaps_b and heaps_a, o
grew = [i for i in heaps_a
if heaps_a[i][0] - heaps_b.get(i, (0, 0))[0] >= 700]
assert grew, f"no heap grew by ~768MB: {o}"
print("OK: heap budget/usage reported, device-local usage +768MB")example.sh
$ python3 check.py
OK: heap budget/usage reported, device-local usage +768MB
Nasıl KULLANILMAMALI
- Bütçeyi söz olarak görmeyin — sorgu ile
vkAllocateMemoryınız arasında küçülebilir (başka bir uygulama belleği kaptı). Yine deeOutOfDeviceMemory‘yi ele alın; bütçe bir politika girdisidir, rezervasyon değil. - Bütçeleri toplamayın — heap’ler garip şekillerde çakışır (BAR heap’i VRAM’e bir penceredir); flag’leriyle doğru heap’i seçin.
- Her frame’de yeniden sorgulamayın — bu syscall’e yakın bir sorgudur; draw başına değil, allocation baskısında veya bir zamanlayıcıda poll edin.
Bu serideki tüm kaynak kod CC0 1.0 Universal (CC0-1.0) altında yayımlanmıştır — kamu malı tahsisi, atıf gerekmez.
If this post helped you, please consider buying me a coffee or donating via PayPal to support research & publishing of new posts on TechOverflow