Code Monkey home page Code Monkey logo

d3d12memoryallocator's People

Contributors

adam-sawicki-a avatar bmarques1995 avatar crud89 avatar danielkrupinski avatar debaetsd avatar demonese avatar fecf avatar germanaizek avatar kingofthebongo2008 avatar nathanvoglsam avatar pixelcatalyst avatar rayferric avatar rbertin-aso avatar ruslankutdusov avatar silveryard avatar turanszkij avatar zhaijialong avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

d3d12memoryallocator's Issues

UWP: ARM build issues

If you integrate the library in project building for UWP with ARM architecture there is json.WriteNumber ambiguity:

cmake . -G "Visual Studio 16 2019" -A ARM -Bbuild_uwp_arm -DCMAKE_SYSTEM_NAME:String=WindowsStore -DCMAKE_SYSTEM_VERSION:String="10.0"

Error below:

1>C:\projects\vgpu\src\lib\D3D12MemAlloc.cpp(7194,68): error C2668: 'D3D12MA::JsonWriter::WriteNumber': ambiguous call to overloaded function
1>C:\projects\vgpu\src\lib\D3D12MemAlloc.cpp(1505,18): message : could be 'void D3D12MA::JsonWriter::WriteNumber(UINT64)'
1>C:\projects\vgpu\src\lib\D3D12MemAlloc.cpp(1498,18): message : or       'void D3D12MA::JsonWriter::WriteNumber(UINT)'
1>C:\projects\vgpu\src\lib\D3D12MemAlloc.cpp(7194,68): message : while trying to match the argument list '(SIZE_T)'

Exposing D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE

Hi

In order to have the best CPU write performance, we should have D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE when creating the heap.
I may be missing things, but it doesn't look like to me this library allows its user to set this flag and it doesn't create heaps with this flag internally by default either.

It would be nice if this option could be exposed through the library interface or simply use D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE as the default Cpu page property since most game developers use it to pass data from CPU to GPU.

Thanks
Jiayin

FindAtOffset compile error with GDK

Building with GDK tools for console I'm getting a compile error with the latest release:

d3d12memalloc.cpp(3557): error C2440: 'return': cannot convert from 'D3D12MA::List<D3D12MA::Suballocation>::const_reverse_iterator' to 'D3D12MA::List<D3D12MA::Suballocation>::const_iterator'

My fix was to forward declare const_reverse_iterator right after the forward declaration of reverse_iterator on line 1564;

class const_reverse_iterator;

It seems as though "friend class const_reverse_iterator" automatically forward-declares the type for VS2017 but it's somehow ambiguous with the GDK toolchain so the conversion constructors aren't triggered automatically.

Sorry if this should be a PR instead -- it's a one-line fix.

ComPtr support

Is it possible to let the D3D12MA::Allocator inherit from IUnknown and provide implementations for AddRef (this won't conflict with the current use of the member method, AddRef), Release and QueryInterface to be used with Microsoft's intrusive ComPtr? This would be consistent with D3D12 types themselves and with 3th-party tools such as DirectXShaderCompiler which also mimic this former behavior.

32-bit compile error: ambiguous call to JsonWriter::WriteNumber with SIZE_T input.

D3D12MemoryAllocator\src\D3D12MemAlloc.cpp(7184,21): error C2668: 'D3D12MA::JsonWriter::WriteNumber': ambiguous call to overloaded function
D3D12MemoryAllocator\src\D3D12MemAlloc.cpp(1505,18): message : could be 'void D3D12MA::JsonWriter::WriteNumber(UINT64)'
D3D12MemoryAllocator\src\D3D12MemAlloc.cpp(1498,18): message : or       'void D3D12MA::JsonWriter::WriteNumber(UINT)'

coming from:

json.WriteNumber(m_AdapterDesc.DedicatedVideoMemory);
json.WriteNumber(m_AdapterDesc.DedicatedSystemMemory);
json.WriteNumber(m_AdapterDesc.SharedSystemMemory);

D3D12MA_DXGI_1_4 always 0 unless dxgi1_4.h included before

Hello,
after updating the allocator in our project from an older version, I've noticed, that ebf4f8de094c41b10f5b111fe88189f85d9ea8f0 introduced a new condition to when is the D3D12MA_DXGI_1_4 macro defined to 1.

#ifdef __IDXGIAdapter3_INTERFACE_DEFINED__
    #define D3D12MA_DXGI_1_4 1
#else
    #define D3D12MA_DXGI_1_4 0
#endif

Correct me if I'm wrong but since there are no includes before this block, unless someone either includes dxgi1_4.h before their D3D12MemAlloc.h or define the macro manually (which is not advised in my opinion) the D3D12MA_DXGI_1_4 will always be 0.

I understand the usage of the other ..._INTERFACE_DEFINED__ conditions since they are defined in the d3d12.h. However, even if we moved the block in question after the dxgi.h include it would not help since the dxgi headers are versioned. So to have the __IDXGIAdapter3_INTERFACE_DEFINED__ defined we would need to include dxgi1_4.h or greater which is actually predicated in the .cpp by D3D12MA_DXGI_1_4 being non-zero.

Is this a bug or did I misuderstand the intention/usage?

Questions about Defragmentation Thread Safety

Hello Adam !
Small question regarding defragmentation.

In the documentation it is written :

What it means in practice is that you shouldn't free any allocations from the defragmented pool since the moment a call to BeginPass begins.

One solution that you give is :

A solution to freeing allocations during defragmentation is to find such allocation on the list pass.pMoves[i] and set its operation to D3D12MA::DEFRAGMENTATION_MOVE_OPERATION_DESTROY instead of calling allocation->Release()

However, it is only possible to set the operation after having the pass moves (after the return of the call). Do I need to keep track of allocations that want to be released during computation time or won't it be an issue if releasing occurs ? Could it be simpler to just add a reference to allocations that ends up being part of a move and remove a reference at the end of the pass ?

Hope those questions are not stupid :)
Have a nice day !

GetResourceAllocation errors while using castable formats and CreateResource3

Hi ! Long time no see !

I'm encountering an issue while creating a resource with CreateResource3 and castable formats.

I'm creating a BC3_UNORM 2D texture with UAV allowed and it can cast to R32G32B32A32_UINT and BC3_UNORM_SRGB. CreatePlacedResource2 or CreateCommittedResource3 accepts this compressed UAV as it can cast to uncompressed format that is coherent.

The issue is that CreateResource3 will do a GetResourceAllocationInfo1 or GetResourceAllocationInfo2 that don't accept castable format, lead to D3D12 errors and return an allocation info with SizeInBytes == (uint64_t)-1. As you save this size and give it to RemoveAllocation, it leads to a failed assert.

To avoid this and errors in D3D12, it seems that it should use GetResourceAllocationInfo3 in ID3D12Device12 interface. I can't create a pull request from a private repo but this is my patch to fix the issue. It fixes for me but it is not perfect and I'm not sure it respects guideline when ID3D12Device12 is not supported ๐Ÿค”.
resourceAllocation3.patch

Have a nice day !
Robin

Hey

With the memory allocator there are some issues from the gpu based validator.

there is an uav which runs fine on the gpu, however i get warnings in the validator.

They do not happen on the cpu validator.
If i use only committed memory, there are no such errors.
I am looking where this may come from

D3D12 ERROR: GPU-BASED VALIDATION: Dispatch, Incompatible resource state: Resource: 0x000002BA10D56500:'Unnamed ID3D12Resource Object', Subresource Index: [0], Root descriptor type: UAV, Resource State: D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE(0x40) (Promoted from COMMON state), Shader Stage: COMPUTE, Root Parameter Index: [2], Dispatch Index: [21], Shader Code: <couldn't find file location in debug info>, Asm Instruction Range: [0xa-0xffffffff], Asm Operand Index: [0], Command List: 0x000002BA10951520:'CommandList 2, Allocator 0', SRV/UAV/CBV Descriptor Heap: 0x000002BA10693200:'StaticHeapDX12', Sampler Descriptor Heap: 0x000002BA10696300:'StaticHeapDX12', Pipeline State: 0x000002BA4D5C6A00:'TressFXSDFCollision.hlslCollideHairVerticesWithSdf_forward', [ EXECUTION ERROR #942: GPU_BASED_VALIDATION_INCOMPATIBLE_RESOURCE_STATE]

Crash on systems older than Windows 10 Build 20348

We upgraded D3D12MA and immediately started seeing an uptick in a crash in the wild. From what we can tell MemoryBlock::Init is blindly using GetDevice4() which may not be available in earlier versions of Windows 10 and code like this will GPF:

#ifdef __ID3D12Device4_INTERFACE_DEFINED__
    HRESULT hr = m_Allocator->GetDevice4()->CreateHeap1(&heapDesc, pProtectedSession, D3D12MA_IID_PPV_ARGS(&m_Heap));
#else
    D3D12MA_ASSERT(pProtectedSession == NULL);
    HRESULT hr = m_Allocator->GetDevice()->CreateHeap(&heapDesc, D3D12MA_IID_PPV_ARGS(&m_Heap));
#endif

C bindings for Direct3D 12 Memory Allocator

Hello there, would it be possible to create C bindings for this project? I might want to try contributing to it, but I sort of am not sure how you folks would want these to look like.

Would it go a similar way that Microsoft went about creating C bindings for Direct3D 12 API?

StrStrI identifier is undefined

StrStrI is undefined no matter what I do.

I've included it like this:

#include <shlwapi.h>
#inc....
#pragma comment (lib, "Shlwapi.lib")

Please help.

VS2015 compiles?

Hi.
I tried to use D3D12MemAlloc.h/cpp in our VS2015 project, and it had many compilation errors. Could we get VS2015 fix?

Index Buffer Creation fail

hello. when I run the program I'm getting this error: CommandQueue::ExecuteCommandLists ' Using IASetIndexBuffer on Command List Resource state (D3D12_RESOURCE_STATE_COPY_DEST) of resource (' Index Buffer Resource Heap') (is invalid for use as a index buffer. Expected State Bits (all): 0x2: D3D12_RESOURCE_STATE_INDEX_BUFFER, Actual State: 0x400: D3D12_RESOURCE_STATE_COPY_DEST, Missing State: 0x2: D3D12_RESOURCE_STATE_INDEX_BUFFER. '
even though I transit index buffer like this:

D3D12Backend::TransitBuffer(indexBuffer, D3D12_RESOURCE_STATE_COPY_DEST,
    D3D12_RESOURCE_STATE_INDEX_BUFFER,
    D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES);

void D3D12Backend::TransitBuffer(ComPtr<ID3D12Resource>& buffer,
    D3D12_RESOURCE_STATES  StateBefore,
    D3D12_RESOURCE_STATES  StateAfter ,
    UINT Subresource)
{
    D3D12_RESOURCE_BARRIER barrier = {};
    barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
    barrier.Transition.pResource = buffer.Get();
    barrier.Transition.StateBefore = StateBefore;
    barrier.Transition.StateAfter = StateAfter;
    barrier.Transition.Subresource = Subresource;
    g_pd3dCommandList->ResourceBarrier(1, &barrier);
}

this is index buffer code: https://gist.github.com/benanil/c700bd6686ba14e7fdd1b3fcbea2dfd5

I also get these warnings

D3D12 WARNING: ID3D12CommandList::IASetIndexBuffer: pDesc->BufferLocation 0x0000000303010000 belongs to a Heap (0x000001C32BCCE9D0:'Unnamed ID3D12Heap Object') however there are no Placed Resources fully containing the GPU Virtual Address range [0x0000000303010000, 0x000000030301000b].  This may be OK since the heap memory can still be accessed from within shaders.  However there may be no way to express resource barriers or perform any other operations requiring a Resource interface.  The developer probably did not intend to make use of this behavior. [ EXECUTION WARNING #923: HEAP_ADDRESS_RANGE_HAS_NO_RESOURCE]
D3D12 WARNING: ID3D12CommandList::IASetIndexBuffer: Resource 0x000001C32BCEE9B0:'HS Index Buffer Resource Heap' and 0 other resources only cover a portion of the GPU Virtual Address range [0x0000000303010000, 0x000000030301000b] on a Heap (0x000001C32BCCE9D0:'Unnamed ID3D12Heap Object').  This may be OK as long as all of these resources are in the same state however developer probably did not intend to make use of this behavior. [ STATE_CREATION WARNING #926: HEAP_ADDRESS_RANGE_INTERSECTS_MULTIPLE_BUFFERS]

Stats inside ASSERT conditional

When trying this code out I got a warning: warning C4706: assignment within conditional expression
it looks like if the assert isn't defined, the assignment will not be made. Is this intentional?

D3D12MA_ASSERT(outStats.Total.Stats.BlockCount =

Also please excuse me if this is not the right way to ask questions like this, I'm not used to the GitHub environment

AlignUp SizeInBytes for buffer memory

AlignUp<UINT64>(inOutResourceDesc.Width, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT), // SizeInBytes

If you are using the same heap for buffers and textures, it would be possible for a "small" texture with 4kb alignment to be placed in that memory space after the buffer, if the size is not aligned up. Is there any other reason you align up the size when you allocate memory for a buffer?

Or is the intention to always use separate heaps for buffers and textures?

D3D12 Memory Alloc Question

Hi, I am doing d3d12 programing. it's a few people do the similar work and it's very difficult to find someone to communication.
I am try to create a texture, my code like this:
`
D3D12_HEAP_PROPERTIES HeapPro;
BuildTextureHeapPro(HeapPro);
D3D12_RESOURCE_DESC TextureDesc;
BuildTextureDesc(TextureDesc);
TextureDesc.Alignment = 65536;

D3D12_RESOURCE_ALLOCATION_INFO Info;
Info = Device->GetResourceAllocationInfo(0, 1, &TextureDesc);
mTextureLen = (int)Info.SizeInBytes;

`
It works ok in most times.
But when the texture width is 1108 and the height is 1440, B8G8R8A8 format, Info.SizeInBytes return a wrong size, which return 6619136. and 1108 * 1440 * 4 = 6382080. I try another way, for example, i try "Device->GetCopyableFootprints(&TextureDesc, 0, 1, 0, &Layouts, nullptr, &RowSizeInBytes, &RequiredSize);", and RequiredSize is 6635344, and it is not the right value. I think the right value is 6635520. Because the row pitch is 4608 and the right value is 4608 * 1440 = 6635520.
what is the problem? i google for days and can't find the solution.
please help, thankyou!

Comptr Issues.

Hi, I'm currently trying to implement this library with com smart pointers, but I've run into a problem.

When I use Microsoft::WRL::ComPtrD3D12MA::Allocator allocator, I get the following compiler warning.

C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0\winrt\wrl/client.h(235,1): error C2440: '=': cannot convert from 'void' to 'unsigned long' [C:\Users\username\source\repos\D3D12\build\D3D12.vcxproj]
[build] C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0\winrt\wrl/client.h(235,32): message : Expressions of type void cannot be converted to other types [C:\Users\username\source\repos\D3D12\build\D3D12.vcxproj]
[build] C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0\winrt\wrl/client.h(228): message : while compiling class template member function 'unsigned long Microsoft::WRL::ComPtrD3D12MA::Allocator::InternalRelease(void) noexcept' [C:\Users\username\source\repos\D3D12\build\D3D12.vcxproj]
[build] C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0\winrt\wrl/client.h(290): message : see reference to function template instantiation 'unsigned long Microsoft::WRL::ComPtrD3D12MA::Allocator::InternalRelease(void) noexcept' being compiled [C:\Users\username\source\repos\D3D12\build\D3D12.vcxproj]
[build] C:\Users\username\source\repos\D3D12\src\DXWindow.hpp(73): message : see reference to class template instantiation 'Microsoft::WRL::ComPtrD3D12MA::Allocator' being compiled [C:\Users\username\source\repos\D3D12\build\D3D12.vcxproj]

However if I use CComPtrD3D12MA::Allocator allocator everything works fine.

The gpuopen docs says this library should work with WRL pointers.

I don't know if I should be mixing both types of smart pointer as my other com objects are using WRL.

Any help is appreciated, thanks.

4 test failures when using WARP device

Hello,
I was trying out D3D12MA when using the WARP device and I noticed that 4 tests are failing in that case.
Specifically: TestPlacedResources, TestCustomPools, TestDevice4 and TestDevice8.

Repro steps

  • Change this check to != 0 to select the WARP device:

if ((desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) == 0)

  • Run the tests again

Errors list

I get the following failures (each seen after commenting out the previously failing test and re-running the tests):

Test placed resources
Assertion failed: 0 && "C:\Users\Sergio\Documents\GitHub\D3D12MemoryAllocator\src\Tests.cpp" "(" "455" "): !( " "resources[i].allocation->GetHeap() != NULL" " )", file C:\Users\Sergio\Documents\GitHub\D3D12MemoryAllocator\src\Tests.cpp, line 455

Test custom pools
Assertion failed: 0 && "C:\Users\Sergio\Documents\GitHub\D3D12MemoryAllocator\src\Tests.cpp" "(" "683" "): FAILED( " "hr" " )", file C:\Users\Sergio\Documents\GitHub\D3D12MemoryAllocator\src\Tests.cpp, line 683

Test ID3D12Device4
Assertion failed: 0 && "C:\Users\Sergio\Documents\GitHub\D3D12MemoryAllocator\src\Tests.cpp" "(" "1348" "): FAILED( " "dev4->CreateProtectedResourceSession(&sessionDesc, IID_PPV_ARGS(&session))" " )", file C:\Users\Sergio\Documents\GitHub\D3D12MemoryAllocator\src\Tests.cpp, line 1348

Test ID3D12Device8
Assertion failed: 0 && "C:\Users\Sergio\Documents\GitHub\D3D12MemoryAllocator\src\Tests.cpp" "(" "1412" "): !( " "alloc1->GetHeap()!= NULL" " )", file C:\Users\Sergio\Documents\GitHub\D3D12MemoryAllocator\src\Tests.cpp, line 1412

Fix for TestDevice4

Not sure about the failures in the other tests, but I could investigate and fix the one in this one.
Turns out the WARP device doesn't support ID3D12Device4::CreateProtectedResourceSession, so the call to this method at the start of the test just causes ERROR_INVALID_PARAMETER to be returned. The fix is to just do something like:

D3D12_FEATURE_DATA_PROTECTED_RESOURCE_SESSION_SUPPORT support;
CHECK_HR(ctx.device->CheckFeatureSupport(
    D3D12_FEATURE::D3D12_FEATURE_PROTECTED_RESOURCE_SESSION_SUPPORT,
    &support,
    sizeof(D3D12_FEATURE_DATA_PROTECTED_RESOURCE_SESSION_SUPPORT)));

if (support.Support == D3D12_PROTECTED_RESOURCE_SESSION_SUPPORT_FLAGS::D3D12_PROTECTED_RESOURCE_SESSION_SUPPORT_FLAG_NONE)
{
    wprintf(L"Skipping ID3D12Device4\n");
    return;
}

Hope this helps! ๐Ÿ˜„

D3D12MA_DEBUG_GLOBAL_MUTEX causes double lock on Release

Defining D3D12MA_DEBUG_GLOBAL_MUTEX causes double locking of static debug std::mutex when releasing resources.

See IUnknownImpl::Release():

ULONG STDMETHODCALLTYPE IUnknownImpl::Release()
{
    D3D12MA_DEBUG_GLOBAL_MUTEX_LOCK

    const uint32_t newRefCount = --m_RefCount;
    if(newRefCount == 0)
        ReleaseThis();
    return newRefCount;
}

When m_RefCount == 0, ReleaseThis(), tries to acquire debug lock again:

void Allocator::ReleaseThis()
{
    D3D12MA_DEBUG_GLOBAL_MUTEX_LOCK
    ...
}

Resulting in std::system_exception being thrown.

Support usage from C?

DX12 (like most Microsoft COM API) is available in C. However, this memory allocator is not.

Would it be possible to expose a C interface for the allocator?

Update vcpkg port

The latest vcpkg port is on 10f148cef0dfd34ae1a9373b9396beb1581c992a, which seems to be a bit over two years old:

// D3D12MemAlloc.h

<b>Version 2.0.0-development</b> (2021-03-11)

Release build v1.0.0+vs2017 problem

There seems to be a bug in the release build that prevents me from compiling the allocator.
In particular on line 596 m_Allocator is referenced but not declared anywhere I can find.

596: Free(m_Allocator.m_pCallbacks, m_pArray)

The issue seems to be fixed on the master branch as I can compile without issues there, I thought I'd open an issue to let you know though. Thanks for the work!

Offset is not correctly written when exporting to json

Hi !

After diving into a json detailed allocation map, I found a lot of offset that had the same value.

It looks like it is a simple switch of arguments :

The definition of PrintDetailedMap_Allocation is this one :
void BlockMetadata::PrintDetailedMap_Allocation(JsonWriter& json, UINT64 offset, UINT64 size, void* privateData) const

but it is called like that
PrintDetailedMap_Allocation(json, block->size, block->offset, block->PrivateData()); in BlockMetadata_TLSF::WriteAllocationInfoToJson (D3D12MemAlloc.cpp:5606).

If it is not this simple thing, I don't understand why nearly all my allocations have the same offset as my size. If it is, it could have be a PR but I wasn't sure.

Is D3D12MA::Allocator::BeginDefragmentation() Work Correctly ?

Our in-house engine use D3D12MA as D3D12 backend's native memory allocator, and I found that placed memory fragments get more and more with game running. By read document, I found there is a interface called D3D12MA::Allocator::BeginDefragmentation can help heap allocation defragment. But after transplanted code from official sample, I just got some overlapped placed resources in heaps, like this in NSight Graphics:

image

Our resources' copy, create, access and destroy can happened on multi-thread, and resources' lifecycle is managed by intelligent pointers, but I have checked if a defragment action scheduled, any of resources' operation will blocked by mutex, and old resources' ref count will be set to 0 after defragment action.

So I got puzzled, I can not find any meaningful code on web except official sample, is D3D12MA really support defragment ? Could you have some more complex sample which can shared with us ?

XBOX support

Is it possible to use this library to port game\engine DX12 renderer from Windows to consoles (XBOX ONE S/X, XBOX SERIES S/X) ? Or we need to do some adjustments?

Question about ALLOCATION_FLAG_WITHIN_BUDGET flag

Hi there, does setting the ALLOCATION_FLAG_WITHIN_BUDGET flag enforce using only gpu/device memory or does it also include system memory that is shared for gpu? In other words, how can we specify the followings?

  1. "only use dedicated gpu memory"
  2. "use system memory if running out of device memory"
  3. "use disk if running out of system and gpu memory"

TestStats and TestID3D12Device4 failing (master, e56c26d)

Hello,
I noticed that a couple of tests are currently failing, in particular TestStats and TestID3D12Device4.
This happens both when running the pre-built executable, as well as when manually building and running the sample.

I'm getting these two errors (the second is after commenting out the first and re-running the tests):

Test stats
Assertion failed: 0 && "C:\Users\Sergio\Documents\GitHub\D3D12MemoryAllocator\src\Tests.cpp" "(" "924" "): !( " "endStats.Total.AllocationCount == begStats.Total.AllocationCount + count" " )", file C:\Users\Sergio\Documents\GitHub\D3D12MemoryAllocator\src\Tests.cpp, line 924

Test ID3D12Device4
Assertion failed: 0 && "C:\Users\Sergio\Documents\GitHub\D3D12MemoryAllocator\src\Tests.cpp" "(" "1372" "): FAILED( " "ctx.allocator->AllocateMemory1(&allocDesc, &heapAllocInfo, session, &alloc)" " )", file C:\Users\Sergio\Documents\GitHub\D3D12MemoryAllocator\src\Tests.cpp, line 1372

System info:

  • Windows 10 Pro, x64 (build 19041.782)
  • GTX 1080 (driver 456.71)

Hope this helps, keep up the good work! ๐Ÿ™Œ

Add support for custom heaps (explicit D3D12_HEAP_PROPERTIES)

Overview

Let me start by saying that D3D12MA is a great project and it's super easy to integrate, which is awesome ๐Ÿ˜„

There's one big limitation currently in the way D3D12MA can be used, which is that there is no support for custom heaps. Even when using Allocator::CreatePool to create a custom pool, the POOL_DESC.HeapType specifically mentions in the documentation not to use the CUSTOM heap type, and there is also no way to pass other heap properties for the pool. In general, it would be necessary for POOL_DESC to allow callers to pass a D3D12_HEAP_PROPERTIES value directly (eg. replacing that single HeapType field), so that consumers would have full control on the target heap used for allocations when using that pool.

This would enable a number of scenarios not possible today when using D3D12MA, such as:

  • Properly supporting UMA architectures (with a custom heap that's CPU visible)
  • Using a custom DEFAULT heap that's also CPU visible (using POOL_L0 and PAGE_ACCESS_WRITE_BACK)
  • Using a custom READBACK heap for transfer buffers that can be both read to and written to by the GPU
  • Etc.

Proposed solution

The simplest solution I can think of would be to just change this field in POOL_DESC:

 struct POOL_DESC
 {
-    D3D12_HEAP_TYPE HeapType;
+    D3D12_HEAP_PROPERTIES HeapProperties;
 };

That HeapProperties would then be passed internally just like HeapType is today, and then MemoryBlock::Init would use that HeapProperties value to setup the D3D12_HEAP_DESC value before calling ID3D12Device::CreateHeap, instead of just setting the heap type like it does today. As in, minor changes would need to be done here:

HRESULT MemoryBlock::Init()
{
D3D12MA_ASSERT(m_Heap == NULL && m_Size > 0);
D3D12_HEAP_DESC heapDesc = {};
heapDesc.SizeInBytes = m_Size;
heapDesc.Properties.Type = m_HeapType;
heapDesc.Alignment = HeapFlagsToAlignment(m_HeapFlags);
heapDesc.Flags = m_HeapFlags;
HRESULT hr = m_Allocator->GetDevice()->CreateHeap(&heapDesc, __uuidof(*m_Heap), (void**)&m_Heap);

This would give consumers of the library much greater flexibility, and it'd make the ability to create custom allocation pools much more worthwhile, as there could be way more customization done on the allocation parameters used by them.

Sporadic issues when copying between 3D textures with D3D12MA + WARP device

Hi there! ๐Ÿ‘‹
I've stumbled upon a weird issue while writing unit tests for my library ComputeSharp, which uses a 1:1 C# port of D3D12MA, and I'm investigating it to try to narrow down the root cause. I thought I'd also open an issue here for tracking as it seems to be related to D3D12MA (I've verified I cannot repro it if I just allocate my resources with ID3D12Device::CreateCommittedResource) in some way.

I don't yet have a full minimal repro, but here's the general idea:

  • This issue only happens when using a WARP device.
  • This issue also only happens when using D3D12MA and a custom pool (here) for UMA devices.
  • This issue only happens when working with 3D textures and copying data between them.
  • I can only reproduce the issue when the test in question is running after another one with different parameters. If I run it on its own, it passes fine. This makes me think it might be somewhat related to how D3D12MA is reusing allocations.
  • I can repro this on 2 different machines with Windows 11. I've had another dev run the tests on his Windows 10 machine and they all passed. Another dev on another Windows 10 machine instead has even more tests failing for whatever reason.

The repro steps I have so far:

  • Create a WARP device with D3D_FEATURE_LEVEL_11_0
  • Create a copy command queue, fence, etc. (the usual setup)
  • Create a D3D12MA allocator, and a pool with these parameters:
D3D12MA_POOL_DESC poolDesc = default;
poolDesc.HeapProperties.CreationNodeMask = 1;
poolDesc.HeapProperties.VisibleNodeMask = 1;
poolDesc.HeapProperties.Type = D3D12_HEAP_TYPE_CUSTOM;
poolDesc.HeapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_WRITE_BACK;
poolDesc.HeapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_L0;
  • Create a 3D texture with DXGI_FORMAT_R32_FLOAT format, D3D12_RESOURCE_FLAG_NONE flags, D3D12_RESOURCE_STATE_COMMON state, D3D12_HEAP_TYPE_DEFAULT heap, D3D12MA_ALLOCATION_FLAG_NONE D3D12MA flags, with the UMA pool.
  • Fill this texture with sample data, by creating an upload buffer with the allocator (D3D12_HEAP_TYPE_UPLOAD, D3D12_RESOURCE_FLAG_NONE, D3D12_RESOURCE_STATE_GENERIC_READ), using the right byte size depending on the copyable footprint retrieved from the previously allocated 3D texture. Map this resource, write the sample data to it, then create a copy command list and use ID3D12GraphicsCommandList::CopyTextureRegion to copy this data to the actual texture.
  • Create another 3D texture, leave this uninitialized (ie. use D3D12MA_ALLOCATION_FLAG_COMMITTED to force zeroing).
  • Copy a given volume from the first 3D texture to this new texture (ID3D12GraphicsCommandList::CopyTextureRegion).
  • Copy the entire second 3D texture back to be able to verify its contents after the previous copy. That is, allocate a readback buffer just like the upload buffer before, call ID3D12GraphicsCommandList::CopyTextureRegion to it, then map it and copy its contents somewhere you can easily read from (or alternatively just map the buffer and then read directly from there).

Now, running these 2 tests one after the other causes the second one to fail:

  1. First test (passing โœ…):
    • Source texture size: (512, 512, 3)
    • Destination texture size: (512, 512, 3)
    • Source copy offsets: (0, 0, 0)
    • Destination copy offsets: (0, 0, 1)
    • Copy volume size: (512, 512, 2)
  2. Second test (failing โŒ):
    • Source texture size: (512, 512, 3)
    • Destination texture size: (512, 512, 4)
    • Source copy offsets: (0, 0, 1)
    • Destination copy offsets: (0, 0, 2)
    • Copy volume size: (512, 512, 2)

By "test failing", I mean that when verifying the data read back from the second texture (the destination one), I get this:

  • The depth level 0 is correctly all zeroed โœ…
  • The depth level 1 is not zeroed. It seems to still have the data from the previous test run, where items were copied at destination dpeth level 1 in the second texture. This time instead the destination depth level is 2, so depth level 1 should just all be 0. We're explicitly passing D3D12MA_ALLOCATION_FLAG_COMMITTED for the destination texture, so it should always be a new allocation with no previous data in it. โŒ
  • Depth levels 2 and 3 are correctly holding the data copied from the source texture โœ…

Just a random thought, but if D3D12MA is in fact accidentlaly not using a committed allocation here and reusing a previous one, it might explain why the behavior is so inconsistent across different OS versions and machines, as the exact way previous allocations are reused and cleared by the OS/driver is undefined? Anyway this is as detailed I could be for this, let me know if there's anything else I can do! I can also try to actually come up with a minimal repro if it helps (though that'd be in C#).

Thanks! ๐Ÿ˜„

Question about residency management.

Hello,
How do you recommend using this library with residency management.
Microsoft has an example about this.
Do you have any recommendations about this?
Thank you

Regarding D3D12_HEAP_FLAG_CREATE_NOT_ZEROED

Hi Adam ! Hope everything is ok !

I wanted to know if something was a feature or more of a bug.

I have a resource that is created with the allocator. By default, this resource (because it can be created without the allocator) is using the D3D12_HEAP_FLAGS : D3D12_HEAP_FLAG_CREATE_NOT_ZEROED. Because of this extra flag, the function CalcDefaultPoolIndex considers that the resource should not be created in a default pool, return -1 and the resource will be created as committed.

Is it the correct behaviour or should it be created as placed (since a placed resource will never be zeroed) ?

Question about support for deferring block frees

Hi, I'm attempting to replicate an allocation scheme used on non-PC platforms for transient resources visible to the GPU only which relies on aliasing the same memory across the frame. This relies on being able to "free" (from the application's POV) the resource memory as soon as it is no longer needed, even if midway through recording a command list, and then allocate new placed resources on top of the same memory so that within a frame GPU memory can be reused via aliasing.

It seems like using a D3D12MA::Pool object almost supports this since I could make one for these transient allocations and then use AllocateMemory to suballocate the heaps it manages. However, the problem is that releasing the D3D12MA::Allocator will immediately free the underlying ID3D12Heap if that block has now become empty even though the frames using that memory are still in flight. I could avoid this by holding onto the Allocation object until I'm sure the GPU is is finished with the last frame using that memory, although that would prevent any aliasing and frames N, N+1, N+2 would then each have their own copy instead of reusing the same memory, which is undesirable.

Is there some existing mechanism to prevent the underlying heaps from being actually freed when the pool shrinks for some N frames as observed via Allocator::SetCurrentFrameIndex()? I see POOL_DESC::MinBlockCount, which keeps empty blocks around, but I don't have a specific minimum size. Ideally the pool would resize dynamically, but the empty blocks would stick around for N frames after they were last used via a cooldown, where N is the number of frames my application has in flight at a given time. It would also be valid for them to be reused to allocate new resources, similar to reuse within a frame since my application ensures work using the memory doesn't overlap, which is why it seems like the existing behavior is so close to what I'm trying to do.

Am I missing something here? Maybe there is a non-obvious D3D12 behavior that makes this kind of setup impossible? :)

Thanks!

EDIT: I just realized after writing this that if it was possible to dynamically change MinBlockCount on a Pool I could call Pool::GetStatistics() each frame then set the MinBlockCount to the N-frame max of Statistics::BlockCount which would essentially do this behavior

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.