-
Notifications
You must be signed in to change notification settings - Fork 434
GraphicsMemory
This class is used to manage video memory allocations.
#include <GraphicsMemory.h>
The graphics memory helper is a singleton. It needs explicit initialization because it requires the device.
std::unique_ptr<GraphicsMemory> graphicsMemory;
graphicsMemory = std::make_unique<GraphicsMemory>(device);
For exception safety, it is recommended you make use of the C++ RAII pattern and use a std::unique_ptr
.
The graphics memory helper manages memory allocation for 'in-flight' data shared between the CPU and GPU. After each frame is rendered, the application needs to call Present
and then Commit to let the manager know that a frame's worth of video memory has been sent to the GPU. This allows the manager to check to see if a previous frame's data is complete and can be released.
swapChain->Present(...);
graphicsMemory->Commit(m_deviceResources->GetCommandQueue());
Most use of GraphicsMemory
is internal to the library, but it can be used directly for allocating video memory via Allocate and AllocateConstant.
The GraphicsResource
class is a smart-pointer with std::unique_ptr
semantics that manages the GPU address, CPU address, and fencing for a particular memory allocation. The SharedGraphicsResource
class is a similar smart-pointer with std::shared_ptr
semantics that's typically used for shared 'static' vertex buffers / index buffers.
Here is an example of using GraphicsMemory
to allocate and render with a constant buffer:
__declspec(align(16)) struct ConstantBufferParams
{
XMVECTOR lightDir;
};
static_assert((sizeof(ConstantBufferParams) % 16) == 0, "CB size not padded correctly");
...
ConstantBufferParams cbData;
XMStoreFloat3(&cbData.lightDir, lightDir);
GraphicsResource myCB = graphicsMemory->AllocateConstant(cbData);
...
commandList->SetComputeRootConstantBufferView(ROOT_SIGNATURE_CB_INDEX, myCB.GpuAddress());
Note that for constant buffers in particular, you generally allocate one buffer per frame since they change and you need to maintain several in flight depending on the number of render targets in your swap chain.
Here is an example of allocating and rendering with a vertex buffer:
GraphicsResource vertexBuffer;
...
vertexBuffer = graphicsMemory->Allocate(sizeof(Vertex) * c_number_of_verts);
memcpy(vertexBuffer.Memory(), s_vertices, sizeof(Vertex) * c_number_of_verts);
...
D3D12_VERTEX_BUFFER_VIEW vbv;
vbv.BufferLocation = vertexBuffer.GpuAddress();
vbv.StrideInBytes = sizeof(Vertex);
vbv.SizeInBytes = static_cast<UINT>(vertexBuffer.Size());
commandList->IASetVertexBuffers(0, 1, &vbv);
Allocated buffers have a lifetime determined by a GraphicsResource
smart-pointer referencing it, or a reference count managed by one or more SharedGraphicsResource
smart-pointers. You can clear a reference by either assigning a different value to the same smart-pointer, or call Reset.
Generally memory is reclaimed on subsequent calls to Commit
(i.e. once per frame), but an application can explicitly call GarbageCollect as well to force a cleanup (typically switching between game levels). If you idle the GPU, the maximum amount of memory will be reclaimed.
m_deviceResources->WaitForGpu();
graphicsMemory->GarbageCollect();
Since GraphicsMemory is a singleton, you can make use of the static method Get if desired:
GraphicsMemory::Get().GarbageCollect()
Allocation of memory resources is fully asynchronous, but should be sync'd once-per-frame to ensure the proper Commit
semantics.
The Allocate method takes an alignment optional parameter that defaults to 16-byte (paragraph) alignment. Graphics memory allocations should always use 4-byte (DWORD) alignment or greater.
All content and source code for this package are subject to the terms of the MIT License.
This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.
- Universal Windows Platform apps
- Windows desktop apps
- Windows 11
- Windows 10
- Xbox One
- Xbox Series X|S
- x86
- x64
- ARM64
- Visual Studio 2022
- Visual Studio 2019 (16.11)
- clang/LLVM v12 - v18
- MinGW 12.2, 13.2
- CMake 3.20