mirror of
https://github.com/GPUOpen-LibrariesAndSDKs/D3D12MemoryAllocator.git
synced 2024-11-21 19:50:05 +00:00
- Added Allocation::GetResource. Allocation now remembers associated ID3D12Resource and keeps reference to it.
- Added Allocator::BuildStatsString, FreeStatsString for generation of a dump of internal library state, including list of all allocations and their parameters, in a JSON format. - Added Allocator::AllocateMemory to allocate a piece of heap without any associated resource. Useful for aliasing.
This commit is contained in:
parent
40a205aee1
commit
5855a7ffd1
5
src/.editorconfig
Normal file
5
src/.editorconfig
Normal file
@ -0,0 +1,5 @@
|
||||
root = true
|
||||
|
||||
[**.{cpp,h}]
|
||||
indent_style = space
|
||||
indent_size = 4
|
File diff suppressed because it is too large
Load Diff
@ -24,7 +24,7 @@
|
||||
|
||||
/** \mainpage D3D12 Memory Allocator
|
||||
|
||||
<b>Version 1.0.0-development</b> (2019-09-30)
|
||||
<b>Version 1.0.0-development</b> (2019-10-09)
|
||||
|
||||
Copyright (c) 2019 Advanced Micro Devices, Inc. All rights reserved. \n
|
||||
License: MIT
|
||||
@ -320,7 +320,11 @@ Features deliberately excluded from the scope of this library:
|
||||
|
||||
*/
|
||||
|
||||
#include <d3d12.h>
|
||||
// If using this library on a platform different than Windows PC, you should
|
||||
// include D3D12-compatible header before this library on your own.
|
||||
#ifdef _WIN32
|
||||
#include <d3d12.h>
|
||||
#endif
|
||||
|
||||
/// \cond INTERNAL
|
||||
|
||||
@ -341,7 +345,7 @@ namespace D3D12MA
|
||||
|
||||
/// \cond INTERNAL
|
||||
class AllocatorPimpl;
|
||||
class DeviceMemoryBlock;
|
||||
class NormalBlock;
|
||||
class BlockVector;
|
||||
/// \endcond
|
||||
|
||||
@ -412,6 +416,9 @@ Allocator::CreateResource.
|
||||
|
||||
The object remembers size and some other information.
|
||||
To retrieve this information, use methods of this class.
|
||||
|
||||
The object also remembers `ID3D12Resource` and "owns" a reference to it,
|
||||
so it calls `Release()` on the resource when destroyed.
|
||||
*/
|
||||
class Allocation
|
||||
{
|
||||
@ -435,6 +442,12 @@ public:
|
||||
*/
|
||||
UINT64 GetSize() const { return m_Size; }
|
||||
|
||||
/** \brief Returns D3D12 resource associated with this object.
|
||||
|
||||
Calling this method doesn't increment resource's reference counter.
|
||||
*/
|
||||
ID3D12Resource* GetResource() const { return m_Resource; }
|
||||
|
||||
/** \brief Returns memory heap that the resource is created in.
|
||||
|
||||
If the Allocation represents committed resource with implicit heap, returns NULL.
|
||||
@ -468,9 +481,11 @@ private:
|
||||
{
|
||||
TYPE_COMMITTED,
|
||||
TYPE_PLACED,
|
||||
TYPE_HEAP,
|
||||
TYPE_COUNT
|
||||
} m_Type;
|
||||
UINT64 m_Size;
|
||||
ID3D12Resource* m_Resource;
|
||||
wchar_t* m_Name;
|
||||
|
||||
union
|
||||
@ -483,15 +498,22 @@ private:
|
||||
struct
|
||||
{
|
||||
UINT64 offset;
|
||||
DeviceMemoryBlock* block;
|
||||
NormalBlock* block;
|
||||
} m_Placed;
|
||||
|
||||
struct
|
||||
{
|
||||
D3D12_HEAP_TYPE heapType;
|
||||
ID3D12Heap* heap;
|
||||
} m_Heap;
|
||||
};
|
||||
|
||||
Allocation();
|
||||
~Allocation();
|
||||
void InitCommitted(AllocatorPimpl* allocator, UINT64 size, D3D12_HEAP_TYPE heapType);
|
||||
void InitPlaced(AllocatorPimpl* allocator, UINT64 size, UINT64 offset, UINT64 alignment, DeviceMemoryBlock* block);
|
||||
DeviceMemoryBlock* GetBlock();
|
||||
void InitPlaced(AllocatorPimpl* allocator, UINT64 size, UINT64 offset, UINT64 alignment, NormalBlock* block);
|
||||
void InitHeap(AllocatorPimpl* allocator, UINT64 size, D3D12_HEAP_TYPE heapType, ID3D12Heap* heap);
|
||||
void SetResource(ID3D12Resource* resource);
|
||||
void FreeName();
|
||||
|
||||
D3D12MA_CLASS_NO_COPY(Allocation)
|
||||
@ -606,8 +628,22 @@ public:
|
||||
existing memory heap to the new resource, which is the main purpose of this
|
||||
whole library.
|
||||
|
||||
Two objects are created and returned: allocation and resource. You need to
|
||||
destroy them both.
|
||||
If `ppvResource` is null, you receive only `ppAllocation` object from this function.
|
||||
It holds pointer to `ID3D12Resource` that can be queried using function D3D12::Allocation::GetResource().
|
||||
Reference count of the resource object is 1.
|
||||
It is automatically destroyed when you destroy the allocation object.
|
||||
|
||||
If 'ppvResource` is not null, you receive pointer to the resource next to allocation object.
|
||||
Reference count of the resource object is then 2, so you need to manually `Release` it
|
||||
along with the allocation.
|
||||
|
||||
\param pAllocDesc Parameters of the allocation.
|
||||
\param pResourceDesc Description of created resource.
|
||||
\param InitialResourceState Initial resource state.
|
||||
\param pOptimizedClearValue Optional. Either null or optimized clear value.
|
||||
\param[out] ppAllocation Filled with pointer to new allocation object created.
|
||||
\param riidResource IID of a resource to be created. Must be `__uuidof(ID3D12Resource)`.
|
||||
\param[out] ppvResource Optional. If not null, filled with pointer to new resouce created.
|
||||
*/
|
||||
HRESULT CreateResource(
|
||||
const ALLOCATION_DESC* pAllocDesc,
|
||||
@ -618,10 +654,39 @@ public:
|
||||
REFIID riidResource,
|
||||
void** ppvResource);
|
||||
|
||||
/* \brief Allocates memory without creating any resource placed in it.
|
||||
|
||||
This function is similar to `ID3D12Device::CreateHeap`, but it may really assign
|
||||
part of a larger, existing heap to the allocation.
|
||||
|
||||
If ResourceHeapTier = 1, `heapFlags` must be one of these values, depending on type
|
||||
of resources you are going to create in this memory:
|
||||
`D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS`,
|
||||
`D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES`,
|
||||
`D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES`.
|
||||
If ResourceHeapTier = 2, `heapFlags` may be `D3D12_HEAP_FLAG_ALLOW_ALL_BUFFERS_AND_TEXTURES`.
|
||||
|
||||
`pAllocInfo->SizeInBytes` must be multiply of 64KB.
|
||||
`pAllocInfo->Alignment` must be one of the legal values as described in documentation of `D3D12_HEAP_DESC`.
|
||||
*/
|
||||
HRESULT AllocateMemory(
|
||||
const ALLOCATION_DESC* pAllocDesc,
|
||||
D3D12_HEAP_FLAGS heapFlags,
|
||||
const D3D12_RESOURCE_ALLOCATION_INFO* pAllocInfo,
|
||||
Allocation** ppAllocation);
|
||||
|
||||
/** \brief Retrieves statistics from the current state of the allocator.
|
||||
*/
|
||||
void CalculateStats(Stats* pStats);
|
||||
|
||||
/// Builds and returns statistics as a string in JSON format.
|
||||
/** @param[out] ppStatsString Must be freed using Allocator::FreeStatsString.
|
||||
*/
|
||||
void BuildStatsString(WCHAR** ppStatsString, BOOL DetailedMap);
|
||||
|
||||
/// Frees memory of a string returned from Allocator::BuildStatsString.
|
||||
void FreeStatsString(WCHAR* pStatsString);
|
||||
|
||||
private:
|
||||
friend HRESULT CreateAllocator(const ALLOCATOR_DESC*, Allocator**);
|
||||
template<typename T> friend void D3D12MA_DELETE(const ALLOCATION_CALLBACKS&, T*);
|
||||
|
@ -91,9 +91,9 @@ static bool ValidateData(const void* ptr, const UINT64 sizeInBytes, UINT seed)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void TestCommittedResources(const TestContext& ctx)
|
||||
static void TestCommittedResourcesAndJson(const TestContext& ctx)
|
||||
{
|
||||
wprintf(L"Test committed resources\n");
|
||||
wprintf(L"Test committed resources and JSON\n");
|
||||
|
||||
const UINT count = 4;
|
||||
const UINT64 bufSize = 32ull * 1024;
|
||||
@ -115,6 +115,8 @@ static void TestCommittedResources(const TestContext& ctx)
|
||||
|
||||
for(UINT i = 0; i < count; ++i)
|
||||
{
|
||||
const bool receiveExplicitResource = i < 2;
|
||||
|
||||
D3D12MA::Allocation* alloc = nullptr;
|
||||
CHECK_HR( ctx.allocator->CreateResource(
|
||||
&allocDesc,
|
||||
@ -122,8 +124,18 @@ static void TestCommittedResources(const TestContext& ctx)
|
||||
D3D12_RESOURCE_STATE_GENERIC_READ,
|
||||
NULL,
|
||||
&alloc,
|
||||
IID_PPV_ARGS(&resources[i].resource)) );
|
||||
__uuidof(ID3D12Resource),
|
||||
receiveExplicitResource ? (void**)&resources[i].resource : NULL));
|
||||
resources[i].allocation.reset(alloc);
|
||||
|
||||
if(receiveExplicitResource)
|
||||
{
|
||||
ID3D12Resource* res = resources[i].resource.p;
|
||||
CHECK_BOOL(res && res == resources[i].allocation->GetResource());
|
||||
const ULONG refCountAfterAdd = res->AddRef();
|
||||
CHECK_BOOL(refCountAfterAdd == 3);
|
||||
res->Release();
|
||||
}
|
||||
|
||||
// Make sure it has implicit heap.
|
||||
CHECK_BOOL( resources[i].allocation->GetHeap() == NULL && resources[i].allocation->GetOffset() == 0 );
|
||||
@ -144,6 +156,13 @@ static void TestCommittedResources(const TestContext& ctx)
|
||||
CHECK_BOOL(names[i] == NULL);
|
||||
}
|
||||
}
|
||||
|
||||
WCHAR* jsonString;
|
||||
ctx.allocator->BuildStatsString(&jsonString, TRUE);
|
||||
CHECK_BOOL(wcsstr(jsonString, L"\"Resource\\nFoo\\r\\nBar\"") != NULL);
|
||||
CHECK_BOOL(wcsstr(jsonString, L"\"Resource \\\"'&<>?#@!&-=_+[]{};:,.\\/\\\\\"") != NULL);
|
||||
CHECK_BOOL(wcsstr(jsonString, L"\"\"") != NULL);
|
||||
ctx.allocator->FreeStatsString(jsonString);
|
||||
}
|
||||
|
||||
static void TestPlacedResources(const TestContext& ctx)
|
||||
@ -501,7 +520,7 @@ static void TestMultithreading(const TestContext& ctx)
|
||||
resources.reserve(256);
|
||||
|
||||
// Create starting number of buffers.
|
||||
const UINT bufToCreateCount = 64;
|
||||
const UINT bufToCreateCount = 32;
|
||||
for(UINT bufIndex = 0; bufIndex < bufToCreateCount; ++bufIndex)
|
||||
{
|
||||
ResourceWithAllocation res = {};
|
||||
@ -613,7 +632,7 @@ static void TestMultithreading(const TestContext& ctx)
|
||||
|
||||
static void TestGroupBasics(const TestContext& ctx)
|
||||
{
|
||||
TestCommittedResources(ctx);
|
||||
TestCommittedResourcesAndJson(ctx);
|
||||
TestPlacedResources(ctx);
|
||||
TestMapping(ctx);
|
||||
TestStats(ctx);
|
||||
|
Loading…
Reference in New Issue
Block a user