VRAM: suballocate textures from shared blocks (~0.9 GB of 64 KiB page padding); bonus: group spatially related textures #411
Labels
No labels
amd
avatars
bug
builder
cannot-reproduce
crash
epic
feature
from-viewer
gl-removal
known-limitation
monitoring
parity
perf
platform
priority
critical
priority
high
priority
low
priority
medium
provenance
rendering
rt
status
in-progress
status
testing
status
up-next
triage
ui
upstream
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Blocks
Reference
sky_line/Slipstream#411
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Part of #405. Follow-up from #407.
Problem
Every texture gets its own
vkAllocateMemory, and the driver rounds every allocation up to its page granularity: 64 KiB on NVIDIA (measured by the #407 probe on an RTX 5090 / 615.71; the tracker now measures it at device creation). Most SL textures are small: floor-size and low-mip images, UI and icons. So in a busy region:~956 MB of VRAM is padding, more than double the actual texture bytes (374 MB). About 10,000 of the ~14,000 texture allocations are tiny (floor size), and each wastes ~60 KB. Measured on the probe:
Huge allocation counts also hurt on drivers with a low
maxMemoryAllocationCount. Some report 4096; NVIDIA has no practical limit. The bug report now shows the limit when there is one.Goal
Suballocate textures (and other small images/buffers) out of large shared device-memory blocks instead of one allocation each. That recovers most of the padding (~0.9 GB here) and cuts the allocation count ~3×.
Design notes
bufferImageGranularityand the alignment fromvkGetImageMemoryRequirements), grouped by memory type, with a suballocator: size classes / buddy, or TLSF-style for mixed sizes. VMA's algorithms are a reference, but we own the allocator (no new dependency unless decided).VkMemoryDedicatedRequirements/prefersDedicatedAllocation).slack, notpad, and keeppadmeaning driver rounding of the blocks themselves (≈ 0).texture pressuresteps still show real savings.Bonus: pack related textures together
When placing textures in blocks, prefer putting spatially related or co-used textures in the same block (and near each other) when they fit:
Possible benefits:
Measure, don't assume: the GPU win is hardware-dependent and may be small. Compare frame time and TLB-related counters (Nsight / RGP) for a busy scene with grouped vs ungrouped placement before committing to the grouping logic. The padding fix alone is the main goal.
Done when
Decided plan (owner, 2026-10-05)
Allocator: VMA
Use AMD's Vulkan Memory Allocator (VMA): a single header (
vk_mem_alloc.h), MIT license, vendored. It replaces a hand-rolled TLSF and defrag, and gives us:VK_EXT_memory_budgetintegration;The #407 tracker stays. VMA's device-memory callbacks report every block it allocates or frees, so driver-level accounting keeps working, and per-category texture bytes come from suballocations.
Measured on the RTX 5090 (615.71)
vkGetImageMemoryRequirements, full mip chains, optimal tiling, sampled + transfer-dst + mutable format. Alignment is 1 KiB for every case;bufferImageGranularityis 1 KiB. The 64 KiB is only the driver's per-vkAllocateMemoryrounding, so suballocation recovers almost all of it.Size classes, by the image's memory-requirement size
The 64 KiB threshold comes from the granularity the tracker measures at device creation (#407), not a constant, so drivers with a smaller rounding unit shift the small class automatically. AMD and Intel numbers come from bug reports.
Expected (busy region at 4K):
Phasing
Unload hitches
With one allocation per texture, unloading a region or a ladder texture step issues thousands of
vkFreeMemorycalls at once. Those are slow driver calls and a likely contributor to unload hitches. With suballocation, freeing a texture is a cheap free-list operation;vkFreeMemoryonly happens when a whole block empties. Measure the hitch before and after with the existing hitch counters.Done: texture pools (slab + medium classes + TLSF fallback) are live, with #587's size classes and now #614's compaction reclaiming stranded space. Closing.