Files
DroidDeck/docs/development/vram-budget.md
Kurt Himebauch 6a681bcbc2 docs: clarify DX12 budget consumers and physical limits (#2148)
* docs: clarify DX12 budget consumers and physical limits

* docs: record controlled Thor gameplay limits
2026-11-05 19:04:11 -05:00

5.5 KiB

Reported video memory budget

The Performance VRAM setting enables VK_LAYER_DROIDDECK_vram_cap for games and reports smaller device-local VK_EXT_memory_budget budgets. DXVK exposes these through DXGI's QueryVideoMemoryInfo, including to D3D12 games using DXVK's DXGI alongside vkd3d-proton. Games that consult this budget can choose smaller working sets. The driver still supplies real heap sizes, usage figures, memory types, and actual allocation results. DXVK also receives its existing dxgi.maxDeviceMemory setting, which separately reduces the adapter's advertised dedicated video memory. A lower driver budget remains lower; the layer never increases it.

This does not make vkd3d-proton automatically enforce the selected budget. In the upstream allocator inspected during this investigation, heapBudget is used for diagnostic reporting, while the DXVK adapter returns the Vulkan budget to applications. Seeing a smaller budget in a VKD3D log verifies reporting, not reduced allocation or eviction.

This is a budget hint, not a physical reservation or a GPU paging implementation. Games may exceed it. On UMA hardware, host-visible Vulkan allocations can share the same device-local heap as textures. Rejecting every allocation above a fixed total can therefore break required upload buffers and other allocations, rather than make a game reduce its texture pool. The layer does not intercept vkAllocateMemory or vkFreeMemory, and preserves the real heap size so individual allocations larger than the budget remain Vulkan-valid.

The layer activates only with DROIDDECK_VRAM_CAP=1 and a positive DROIDDECK_VRAM_CAP_MB. With the Performance setting on Auto, the game environment does not enable it. Explicit DXVK configuration remains available, while the Vulkan layer also covers D3D12 and games that replace their DXVK configuration.

Physical investigation

On an 8 GB Pocket FIT Elite with DD Turnip 0.4.0, Proton 11-12.1, and Caravan SandWitch build 25301828:

  • A native Vulkan probe reported a device-local heap of 5,650,776,064 bytes. All exposed memory types used the same device-local UMA heap. The initial implementation clamped both heap and budget to 2048 MiB; the revised layer preserves heap capacity and clamps only the budget.
  • The initial hard allocation cap caused the existing save to fail a required 603,979,776-byte D3D12 allocation. Android survived, but the game crashed. Discord testers also reported crashes after reaching the cap in Fallout 76.
  • In the initial test with allocation rejection disabled, vkd3d-proton logged the smaller 2048 MiB heap and budget. Caravan still exhausted system memory while loading the save. A reported budget alone does not solve this workload.
  • DX11 loaded the same save and supported movement around the station at approximately 60 FPS for more than five minutes, both with and without the reported budget layer. Graphics settings were unchanged. This establishes a renderer workaround, not proof that the layer solved Caravan's OOM.
  • The final release-signed APK, preserving real heap size and clamping only the budget to 2048 MiB, also passed more than five minutes of loaded-save DX11 movement. D3D12 with the same budget still exhausted system memory.
  • Launching D3D12 through droiddeck-proton-run --app without the Linux Steam client reached the loaded save and allowed movement, then Android killed the session for low memory. Removing the client footprint alone was insufficient.

A separate Windows DXGI query probe on a 12 GB AYN Thor with the same APK and Proton queried the adapter without allocating game resources. With the layer disabled, dedicated video memory was 8,858,370,048 bytes and the local budget was 5,656,018,944 bytes. Enabling only the layer at 2048 MiB preserved that dedicated-memory value and changed the local and UMA non-local budgets to 2,147,483,648 bytes. Adding the existing DXVK_CONFIG="dxgi.maxDeviceMemory = 2048" setting also lowered advertised dedicated memory to 2,147,483,648 bytes while retaining the 2048 MiB budgets. These probes verify the application-facing budget path; they are not 8 GB gameplay results.

On that Thor, subsequent D3D12 runs both with and without the 2048 MiB budget reached the existing save and supported more than five minutes of movement. Both used the Stability preset and VKD3D_CONFIG=log_memory_budget. The budgeted run ended with an Android low-memory kill during the shutdown window; the unbudgeted retry stopped cleanly. Earlier runs also encountered low-memory kills or a separate exception-stack startup failure. These observations do not establish a reduction in Caravan's memory use from the budget hint or a stable D3D12 fix.

Native regression coverage exercises core and KHR memory-property queries, chained budget structures, unchanged real usage above the budget, separate heap types, disabled behavior, device lifecycle dispatch, and successful driver allocations whose individual and combined sizes exceed the reported budget.

The Vulkan specification describes heapBudget as a guideline. Transparent movement between device-local and host-local memory requires driver and operating-system support for pageable device-local memory.