Skip to content

GraphicsMemory

Chuck Walbourn edited this page Mar 1, 2018 · 42 revisions

This class is used to manage video memory allocations.

Header

#include <GraphicsMemory.h>

Initialization

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.

Present

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());

Usage

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);

Garbage collection

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()

Threading model

Allocation of memory resources is fully asynchronous, but should be sync'd once-per-frame to ensure the proper Commit semantics.

Remark

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.

AllocateConstant will always use an alignment of D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT.

Further reading

Memory Management in Direct3D 12

For Use

  • Universal Windows Platform apps
  • Windows desktop apps
  • Windows 11
  • Windows 10
  • Xbox One
  • Xbox Series X|S

Architecture

  • x86
  • x64
  • ARM64

For Development

  • Visual Studio 2022
  • Visual Studio 2019 (16.11)
  • clang/LLVM v12 - v18
  • MinGW 12.2, 13.2
  • CMake 3.20

Related Projects

DirectX Tool Kit for DirectX 11

DirectXMesh

DirectXTex

DirectXMath

Tools

Test Suite

Model Viewer

Content Exporter

DxCapsViewer

See also

DirectX Landing Page

Clone this wiki locally