Example: VulkanExamples/p42_budget
シリーズ post 42(post 28:ケイパビリティクエリ、post:メモリタイプ)。
VkPhysicalDeviceMemoryProperties はヒープのサイズを教える——
箱に印刷された16GB。教えないのは:そのヒープのどれだけが
既に消えているか(他のアプリ、コンポジタ、自分の以前の
アロケーション)、そしてドライバがいくらまで与えてくれるか。
VK_EXT_memory_budget は1つのチェーンした構造体で両方の穴を
塞ぐ:
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]——ドライバが現在アロケートを許す量(ヒープ サイズ − ドライバ予約 − 他のプロセス)。heapUsage[i]——今実際にアロケートされている量。
テスト Radeon 上:
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
2つの教訓的な詳細:
- budget ≠ size:heap0 の 16GB は 15.1GB のバジェットを 示す——ドライバは ~1GB を自分用に取っておく(ページテーブル、 ファームウェア、他のクライアント)。heap2 はリサイズ可能 BAR ウィンドウ:256MB ヒープなのにバジェットは 54MB のみ、つまり 大半は恒久的に予約済み。
- usage はあなた以外も数える:共有ヒープ上の
heapUsageは システム全体——他のアプリが VRAM をアロケートするとここに 現れる。だからこそアプリはヒープサイズを信じる代わりに、 キャッシュを追い出す・増やすときにバジェットを再確認すべき。
チェック
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
やってはいけない使い方
- バジェットを約束として扱うな——クエリと
vkAllocateMemoryの間で縮みうる(他のアプリがメモリを掴んだ)。依然eOutOfDeviceMemoryをハンドルせよ;バジェットはポリシーの 入力であり予約ではない。 - バジェットを合計するな——ヒープは奇妙に重なる(BAR ヒープ は VRAM へのウィンドウ);フラグで正しいヒープを選べ。
- フレーム毎に再クエリするな——これはシステムコールに 近いクエリ;ドロー毎ではなく、アロケーション圧力または タイマーでポーリングせよ。
このシリーズのすべてのソースコードは CC0 1.0 Universal (CC0-1.0) の下でリリース——パブリックドメイン献身、帰属 表示不要。
この記事が役に立った場合は、TechOverflow での新しい記事の調査と公開を支援するため、「Buy Me a Coffee」でのご支援、または PayPal 経由でのご寄付をご検討ください