Library / SDK
GPUOpen-LibrariesAndSDKs/D3D12MemoryAllocator avatar
GPUOpen-LibrariesAndSDKs/D3D12MemoryAllocator

D3D12MemoryAllocator turns committed resources into placed resources for you

Easy to integrate memory allocation library for Direct3D 12

1,045 stars122 forksC++MIT

At a glance

What is it?
D3D12MemoryAllocator is a C++ library in a single pair of H and CPP files that manages Direct3D 12 memory heaps and creates resources as placed resources inside them, the equivalent of Vulkan Memory Allocator for D3D12. It fits a graphics engine team tired of hand-managing heap types and placements, and it does not fit a project that needs to work on non-Windows platforms or that already has a working allocation path.
Who is it for?
D3D12MemoryAllocator fits a team writing a Direct3D 12 renderer that has outgrown committed resource creation and wants heap budgeting, placed resources and a defragmentation pass without writing an allocator, and it does not fit a project with a Vulkan or OpenGL backend, since it is D3D12-specific.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 11 days ago.
What is it written in?
Mainly C++, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem is that explicit APIs make you manage heap blocks yourself

D3D12MemoryAllocator exists because memory allocation and resource creation in new, explicit graphics APIs such as Vulkan and Direct3D 12 is difficult compared with older graphics APIs like Direct3D 11 or OpenGL. The reason is a design change in how the driver expects you to work: it is recommended to allocate bigger blocks of memory and assign parts of them to resources.

That recommendation is the whole problem. With Direct3D 11, the API handles block placement for you. With D3D12, you are expected to create heaps, manage the free space inside them, satisfy each resource's size and alignment requirements, and respect the device's heap tier, which determines whether certain classes of resources are allowed to share a heap. Every engine that takes that instruction seriously ends up writing an allocator.

The README makes the lineage explicit. Vulkan Memory Allocator is the library that implements this functionality for Vulkan, it has been available since 2017, and it is used in many software projects including some AAA game studios. This is the equivalent library for D3D12, from the same GPUOpen organisation.

The value proposition is therefore not new. It is that you do not have to write the piece you were going to have to write anyway, and that you get a maintained one with the edge cases already handled.

CreateResource replaces CreateCommittedResource and does three things at once

The interface is deliberately close to D3D12's own. The library offers Allocator::CreateResource, similar to the standard ID3D12Device::CreateCommittedResource, and it internally does three things: it allocates and keeps track of bigger memory heaps with the used and unused ranges inside them, it finds the best matching unused range to create a new resource there as a placed resource, and it automatically respects the size and alignment requirements for created resources. It also handles the resource heap tier automatically, whether it is D3D12_RESOURCE_HEAP_TIER_1, which requires keeping certain classes of resources separate, or D3D12_RESOURCE_HEAP_TIER_2, which allows keeping them all together.

The example shows the whole call. You fill in a D3D12_RESOURCE_DESC and an ALLOCATION_DESC with a heap type, then call allocator->CreateResource with the initial resource state, and it returns the resource and an Allocation object:

cpp
D3D12_RESOURCE_DESC resourceDesc = {};
resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
resourceDesc.Alignment = 0;
resourceDesc.Width = 1024;
resourceDesc.Height = 1024;
resourceDesc.DepthOrArraySize = 1;
resourceDesc.MipLevels = 1;
resourceDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
resourceDesc.SampleDesc.Count = 1;
resourceDesc.SampleDesc.Quality = 0;
resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
resourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;

D3D12MA::ALLOCATION_DESC allocDesc = {};
allocDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT;

D3D12Resource* resource;
D3D12MA::Allocation* allocation;
HRESULT hr = allocator->CreateResource(
    &allocDesc, &resourceDesc,
    D3D12_RESOURCE_STATE_COPY_DEST, NULL,
    &allocation, IID_PPV_ARGS(&resource));

The README spells out what that one call does: an ID3D12Heap memory block is allocated if needed, an unused region of that block is reserved for the allocation, and an ID3D12Resource is created as a placed resource bound to that region. The Allocation object represents the memory assigned to the texture and can be queried for parameters like offset and size.

That offset is the number you actually wanted from the start. It is what you need to put a texture in a bindless or ray tracing acceleration structure, and it is exactly what CreateCommittedResource never gave you.

A virtual allocator that never touches GPU memory

The virtual allocator is the feature that reaches beyond a Direct3D 12 memory manager, and it is the one most likely to be useful outside a renderer.

The virtual allocator exposes the core allocation algorithm to be used without allocating real GPU memory, so you can allocate your own stuff, for example sub-allocating pieces of one large buffer. The same code that finds the best matching free range in a D3D12 heap can then be pointed at a plain CPU buffer, a network packet pool, or an arena of your own.

The reason it works is that the algorithm is separated from the D3D12 specifics. The allocator's job is to answer a question about geometry: given a set of size and alignment requirements, where in this address space should the next block go, and what is left over. The virtual mode answers exactly that question over a virtual range and hands you offsets, with no heap, no resource and no device involved.

That makes it usable as a general-purpose sub-allocator, and it is the sort of thing that is hard to write correctly. Fragmentation handling, alignment rounding and best-fit search all live in one place, tested by the same test suite that exercises the D3D12 path.

Debugging tools: JSON dumps, statistics and a visualiser

Memory bugs in a renderer are notoriously hard to diagnose, because what you want to know is not what the D3D12 debug layer reports but where the gaps are in your own allocator's address space. The library answers that with three separate facilities.

The JSON dump gives you a string in JSON format with a detailed map of the internal state, including the list of allocations, their string names, and the gaps between them. The visualiser in tools/GpuMemDumpVis turns that JSON into a picture, so a heap layout becomes something you can look at rather than something you have to imagine from a list.

Statistics are a separate API. You can obtain brief or detailed statistics about the amount of memory used and unused, the number of allocated heaps and the number of allocations, both globally and per memory heap type. Current memory usage and budget as reported by the system can also be queried, which is the hook you want for a frame-time budget or a crash dump triage.

Debug annotations tie the two together. You can associate a custom void* pPrivateData and a debug LPCWSTR pName with each allocation. The pName is what shows up in the JSON dump and in the visualiser, so a named allocation is a diagnosable one, and the private data pointer lets you attach your own context to an allocation without a side table.

Custom pools, a linear allocator and defragmentation

Three features handle the cases where a general purpose heap allocator is the wrong tool.

Custom memory pools let you create a pool with desired parameters, for example a fixed or limited maximum size, custom D3D12_HEAP_PROPERTIES and D3D12_HEAP_FLAGS, and allocate memory out of it. This is how you reserve a fixed budget for a streaming system or an upload ring, and it keeps that memory out of the shared pool where a general allocation could fragment it.

The linear allocator is a pool with a linear algorithm, used for much faster allocations and deallocations in free-at-once, stack, double stack or ring buffer fashion. A ring buffer allocation pattern, where the oldest block is recycled as the newest arrives, is the natural fit for per-frame upload buffers, and a linear allocator turns that from a search problem into pointer arithmetic.

Defragmentation lets the library move data around to free some memory blocks and make your allocations better compacted. This is the feature with the most caveats in practice, since moving data means copying it, and for a texture or a buffer that means a GPU-side copy and a transition of the resource state. The library is offering the operation; deciding when it is worth the copy is the engine's job.

Resource aliasing support, overlap, is a related capability: two allocations can share the same memory as long as their lifetimes do not overlap, which is how a large render target pool avoids holding several full-resolution targets at once.

Two files, no dependencies, HRESULT error handling

The prerequisites are unusually strict for a library of this kind, and they are what makes it easy to drop into an existing engine.

It is a self-contained C++ library in a single pair of H and CPP files, with no external dependencies other than the standard C and C++ library and the Windows SDK. Some features of C++14 are used, and STL containers, C++ exceptions and RTTI are not used. That last point matters in a graphics engine: the renderer usually has its own memory system, its own container types and its own crash handling, and a library that drags in the STL and throws exceptions across your ABI boundary is a nuisance.

The interface is object-oriented in a convention similar to D3D12, error handling is implemented by returning HRESULT error codes in the same way as D3D12, and the interface is documented using Doxygen-style comments. The generated online documentation is browsable and is produced from the comments in include/D3D12MemAlloc.h.

The library is designed to be used in multithreaded code, which is a hard requirement rather than a nice-to-have in a renderer where the render thread, the streaming thread and the loading thread all allocate.

Configuration happens through the optional members of the ALLOCATOR_DESC structure, where you can provide a custom CPU memory allocator and other parameters. Customization and integration with custom engines is done by predefining appropriate macros to provide your own implementation of external facilities used by the library, like assert, mutex and atomic. That is the integration point for an engine that wants its own allocator for the CPU-side bookkeeping memory, its own mutex type, and its own assertion handling.

Where D3D12MemoryAllocator is the wrong tool

The first limitation is platform and API. This is a Direct3D 12 library, which means Windows and the Microsoft graphics stack. A renderer that also targets Vulkan needs a different allocator, or the Vulkan Memory Allocator the README names as its sibling, and if you support both you are maintaining two allocators with two sets of behaviour. The project is explicit that it is the D3D12 equivalent, not a cross-API abstraction.

The second is that the library does not eliminate the allocation problem, it relocates it. You still decide your heap types, your budget per heap and your upload strategy. It handles placement, alignment and tier rules. It does not decide that your render target pool should be reserved rather than shared, and it will not tell you that a frame is about to allocate 40 megabytes of transient resources.

The third is the defragmentation and aliasing cost, mentioned above. Both features are opt-in and both have a real price at runtime. A team that enables them without measuring will get a slower frame in exchange for a tidier address space, and a team that assumed a memory allocator would never need to think about GPU copies was wrong.

The fourth is the alternative that already exists: the Direct3D 12 API has its own ID3D12Device::CreateCommittedResource. A small engine with a handful of resources does not need an allocator at all, and adopting one is work with a maintenance tail. The library earns its place in an engine with many transient resources, a large number of distinct allocations, and a real need to see where the memory went.

One more practical note. The release ships a precompiled binary for the D3D12Sample application that contains the test suite, compiled with Visual Studio 2022, so it needs MSVCP140.dll, VCRUNTIME140.dll and VCRUNTIME140_1.dll, and the README points at the Microsoft Visual C++ Redistributable X64 version if the launch fails.

Editorial conclusion

D3D12MemoryAllocator fits a team writing a Direct3D 12 renderer that has outgrown committed resource creation and wants heap budgeting, placed resources and a defragmentation pass without writing an allocator, and it does not fit a project with a Vulkan or OpenGL backend, since it is D3D12-specific. Before integrating, confirm you are on the release line you expect, since the versions are v3.2.0 from 2026-06-04 and v3.1.0 from 2026-02-24, and read NOTICES.txt, because parts of the code come from Vulkan Memory Allocator and the DirectX-Graphics-Samples, both under MIT.

Frequently asked questions

What does D3D12MemoryAllocator do?

It manages Direct3D 12 memory heaps and creates resources as placed resources inside them. The call Allocator::CreateResource, similar to ID3D12Device::CreateCommittedResource, allocates a heap if needed, reserves an unused region in it and creates the resource bound to that region, returning an Allocation object you can query for offset and size.

What are the dependencies for D3D12MemoryAllocator?

It is a self-contained C++ library in a single pair of H and CPP files, with no external dependencies other than the standard C and C++ library and the Windows SDK. Some C++14 features are used, and STL containers, C++ exceptions and RTTI are not.

Can D3D12MemoryAllocator be used without a GPU?

Yes, through the virtual allocator, an API that exposes the core allocation algorithm to be used without allocating real GPU memory, so you can sub-allocate pieces of one large buffer with your own allocator.

How do I visualise memory usage with D3D12MemoryAllocator?

The library can produce a JSON dump with a detailed map of internal state, including allocations, their names and the gaps between them, and the tool in tools/GpuMemDumpVis converts that dump into a picture. Statistics are also available, globally and per memory heap type.

What licence is D3D12MemoryAllocator released under?

The library is MIT licensed, with the text in LICENSE.txt. Parts of the code come from the Vulkan Memory Allocator by AMD and the DirectX-Graphics-Samples by Microsoft, both MIT licensed, and NOTICES.txt covers the third party software.

Official sources

  1. GPUOpen-LibrariesAndSDKs/D3D12MemoryAllocator on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/gpuopen-librariesandsdks-d3d12memoryallocator.svg)](https://hysenlabs.com/projects/gpuopen-librariesandsdks-d3d12memoryallocator)

Was this useful?