As an added bonus, some things now have two memory addresses
There are two types of memory one can check for, local and non local.
- Local: This type of memory is local to the GPU and the fastest memory available for it to use.
- Non local: This is the system memory. In a Unified Memory Architecture (UMA) adapter this is zero.
To know how much memory the GPU can use call IDXGIAdapter3::QueryVideoMemoryInfo(). It is possible to tell DX12 the minimum amount of memory our application need to survive by calling IDXGIAdapter3::SetVideoMemoryReservation(). There is no guarantee we get it and memory availability might change at runtime. To get notified about changes call IDXGIAdapter3::RegisterVideoMemoryBudgetChangeNotificationEvent() and when notified call QueryVideoMemoryInfo again.
The manage memory the ID3D12Heap is used and things such as textures and buffers are stored in heaps. A heap is created by filling in a D3D12_HEAP_DESC and then call ID3D12Device::CreateHeap. Depending on how the memory will be used one can select what type of heap to create. There are three abstract heap types that try to be as adapter-neutral as possible. The final option is to create a custom heap and set the parameters directly.
This heap has the best bandwidth for the GPU but the CPU can not access it. The GPU can read and write the memory. This heap is filled in by putting the data into a upload heap first and then copy it to the default heap with the help of the GPU.
A heap for moving things from the CPU to the GPU. The GPU can read from this but is does not do so at optimal speed. For smaller things such as constant buffers it might be fine.
This is for the GPU to write and the CPU to read. The resources in a readback heap must be created and use the D3D12_RESOURCE_STATE_COPY_DEST.
Makes it possible to create a custom heap and select what memory it will use and it's access rules. What is possible depends on the hardware the game is running on. It is possible to query the settings used for the abstract heaps to use as a starting point by calling ID3D12Device::GetCustomHeapProperties().
For the GPU to use an object it need to be in physical memory that the GPU can access. The object is then said to be resident. Residency management is the fun part of making sure that all the objects the GPU needs is available in memory when it needs them. The GPU-accessible memory is made resident when a API object is created and evicted when the API object is destroyed. The main memory consumers that one need to care about is heaps the resources in them. The most reliable way to free memory is to destroy a heap. Creating heaps can be slow but can be run on a background thread.