BREAKING CHANGE: Made all public classes COM-compatible - inheriting from IUnknown, reference counting

This commit is contained in:
Adam Sawicki 2021-07-26 21:18:52 +02:00
parent 0f44bf40bf
commit 7642634a62
4 changed files with 155 additions and 183 deletions

View File

@ -31,7 +31,6 @@
#include <combaseapi.h> #include <combaseapi.h>
#include <mutex> #include <mutex>
#include <atomic>
#include <algorithm> #include <algorithm>
#include <utility> #include <utility>
#include <cstdlib> #include <cstdlib>
@ -239,17 +238,6 @@ static inline void D3D12MA_SWAP(T& a, T& b)
#define D3D12MA_RW_MUTEX RWMutex #define D3D12MA_RW_MUTEX RWMutex
#endif #endif
/*
If providing your own implementation, you need to implement a subset of std::atomic.
*/
#ifndef D3D12MA_ATOMIC_UINT32
#define D3D12MA_ATOMIC_UINT32 std::atomic<UINT>
#endif
#ifndef D3D12MA_ATOMIC_UINT64
#define D3D12MA_ATOMIC_UINT64 std::atomic<UINT64>
#endif
/* /*
Returns true if given number is a power of two. Returns true if given number is a power of two.
T must be unsigned integer number or signed integer but always nonnegative. T must be unsigned integer number or signed integer but always nonnegative.
@ -2846,6 +2834,7 @@ struct CommittedAllocationParameters
class AllocatorPimpl class AllocatorPimpl
{ {
public: public:
std::atomic_uint32_t m_RefCount = 1;
CurrentBudgetData m_Budget; CurrentBudgetData m_Budget;
AllocatorPimpl(const ALLOCATION_CALLBACKS& allocationCallbacks, const ALLOCATOR_DESC& desc); AllocatorPimpl(const ALLOCATION_CALLBACKS& allocationCallbacks, const ALLOCATOR_DESC& desc);
@ -4473,7 +4462,7 @@ void PoolPimpl::FreeName()
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Public class Pool implementation // Public class Pool implementation
void Pool::Release() void Pool::ReleaseThis()
{ {
if(this == NULL) if(this == NULL)
{ {
@ -5862,6 +5851,38 @@ void AllocatorPimpl::WriteBudgetToJson(JsonWriter& json, const Budget& budget)
json.EndObject(); json.EndObject();
} }
////////////////////////////////////////////////////////////////////////////////
// Public but internal class IUnknownImpl implementation
HRESULT STDMETHODCALLTYPE IUnknownImpl::QueryInterface(REFIID riid, _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject)
{
if(ppvObject == NULL)
return E_POINTER;
if(riid == IID_IUnknown)
{
++m_RefCount;
*ppvObject = this;
return S_OK;
}
*ppvObject = NULL;
return E_NOINTERFACE;
}
ULONG STDMETHODCALLTYPE IUnknownImpl::AddRef()
{
return ++m_RefCount;
}
ULONG STDMETHODCALLTYPE IUnknownImpl::Release()
{
D3D12MA_DEBUG_GLOBAL_MUTEX_LOCK
const uint32_t newRefCount = --m_RefCount;
if(newRefCount == 0)
ReleaseThis();
return newRefCount;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Public class Allocation implementation // Public class Allocation implementation
@ -5893,7 +5914,7 @@ void Allocation::PackedData::SetTextureLayout(D3D12_TEXTURE_LAYOUT textureLayout
m_TextureLayout = u; m_TextureLayout = u;
} }
void Allocation::Release() void Allocation::ReleaseThis()
{ {
if(this == NULL) if(this == NULL)
{ {
@ -6063,7 +6084,7 @@ Allocator::~Allocator()
D3D12MA_DELETE(m_Pimpl->GetAllocs(), m_Pimpl); D3D12MA_DELETE(m_Pimpl->GetAllocs(), m_Pimpl);
} }
void Allocator::Release() void Allocator::ReleaseThis()
{ {
D3D12MA_DEBUG_GLOBAL_MUTEX_LOCK D3D12MA_DEBUG_GLOBAL_MUTEX_LOCK
@ -6072,8 +6093,6 @@ void Allocator::Release()
D3D12MA_DELETE(allocationCallbacksCopy, this); D3D12MA_DELETE(allocationCallbacksCopy, this);
} }
const D3D12_FEATURE_DATA_D3D12_OPTIONS& Allocator::GetD3D12Options() const const D3D12_FEATURE_DATA_D3D12_OPTIONS& Allocator::GetD3D12Options() const
{ {
return m_Pimpl->GetD3D12Options(); return m_Pimpl->GetD3D12Options();
@ -6325,7 +6344,7 @@ VirtualBlock::~VirtualBlock()
D3D12MA_DELETE(m_Pimpl->m_AllocationCallbacks, m_Pimpl); D3D12MA_DELETE(m_Pimpl->m_AllocationCallbacks, m_Pimpl);
} }
void VirtualBlock::Release() void VirtualBlock::ReleaseThis()
{ {
D3D12MA_DEBUG_GLOBAL_MUTEX_LOCK D3D12MA_DEBUG_GLOBAL_MUTEX_LOCK

View File

@ -728,6 +728,36 @@ may get their alignment 4K and their size a multiply of 4K instead of 64K.
// To be used with MAKE_HRESULT to define custom error codes. // To be used with MAKE_HRESULT to define custom error codes.
#define FACILITY_D3D12MA 3542 #define FACILITY_D3D12MA 3542
/*
If providing your own implementation, you need to implement a subset of std::atomic.
*/
#if !defined(D3D12MA_ATOMIC_UINT32) || !defined(D3D12MA_ATOMIC_UINT64)
#include <atomic>
#endif
#ifndef D3D12MA_ATOMIC_UINT32
#define D3D12MA_ATOMIC_UINT32 std::atomic<UINT>
#endif
#ifndef D3D12MA_ATOMIC_UINT64
#define D3D12MA_ATOMIC_UINT64 std::atomic<UINT64>
#endif
namespace D3D12MA
{
class IUnknownImpl : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, _COM_Outptr_ void __RPC_FAR *__RPC_FAR *ppvObject);
virtual ULONG STDMETHODCALLTYPE AddRef();
virtual ULONG STDMETHODCALLTYPE Release();
protected:
virtual void ReleaseThis() { delete this; }
private:
D3D12MA_ATOMIC_UINT32 m_RefCount = 1;
};
} // namespace D3D12MA
/// \endcond /// \endcond
namespace D3D12MA namespace D3D12MA
@ -847,16 +877,9 @@ To retrieve this information, use methods of this class.
The object also remembers `ID3D12Resource` and "owns" a reference to it, The object also remembers `ID3D12Resource` and "owns" a reference to it,
so it calls `%Release()` on the resource when destroyed. so it calls `%Release()` on the resource when destroyed.
*/ */
class Allocation class Allocation : public IUnknownImpl
{ {
public: public:
/** \brief Deletes this object.
This function must be used instead of destructor, which is private.
There is no reference counting involved.
*/
void Release();
/** \brief Returns offset in bytes from the start of memory heap. /** \brief Returns offset in bytes from the start of memory heap.
You usually don't need to use this offset. If you create a buffer or a texture together with the allocation using function You usually don't need to use this offset. If you create a buffer or a texture together with the allocation using function
@ -925,6 +948,9 @@ public:
*/ */
BOOL WasZeroInitialized() const { return m_PackedData.WasZeroInitialized(); } BOOL WasZeroInitialized() const { return m_PackedData.WasZeroInitialized(); }
protected:
virtual void ReleaseThis();
private: private:
friend class AllocatorPimpl; friend class AllocatorPimpl;
friend class BlockVector; friend class BlockVector;
@ -1066,16 +1092,9 @@ pools - creating resources in default pool is sufficient.
To create custom pool, fill D3D12MA::POOL_DESC and call D3D12MA::Allocator::CreatePool. To create custom pool, fill D3D12MA::POOL_DESC and call D3D12MA::Allocator::CreatePool.
*/ */
class Pool class Pool : public IUnknownImpl
{ {
public: public:
/** \brief Deletes pool object, frees D3D12 heaps (memory blocks) managed by it. Allocations and resources must already be released!
It doesn't delete allocations and resources created in this pool. They must be all
released before calling this function!
*/
void Release();
/** \brief Returns copy of parameters of the pool. /** \brief Returns copy of parameters of the pool.
These are the same parameters as passed to D3D12MA::Allocator::CreatePool. These are the same parameters as passed to D3D12MA::Allocator::CreatePool.
@ -1103,6 +1122,9 @@ public:
*/ */
LPCWSTR GetName() const; LPCWSTR GetName() const;
protected:
virtual void ReleaseThis();
private: private:
friend class Allocator; friend class Allocator;
friend class AllocatorPimpl; friend class AllocatorPimpl;
@ -1258,16 +1280,9 @@ Call method Allocator::Release to destroy it.
It is recommended to create just one object of this type per `ID3D12Device` object, It is recommended to create just one object of this type per `ID3D12Device` object,
right after Direct3D 12 is initialized and keep it alive until before Direct3D device is destroyed. right after Direct3D 12 is initialized and keep it alive until before Direct3D device is destroyed.
*/ */
class Allocator class Allocator : public IUnknownImpl
{ {
public: public:
/** \brief Deletes this object.
This function must be used instead of destructor, which is private.
There is no reference counting involved.
*/
void Release();
/// Returns cached options retrieved from D3D12 device. /// Returns cached options retrieved from D3D12 device.
const D3D12_FEATURE_DATA_D3D12_OPTIONS& GetD3D12Options() const; const D3D12_FEATURE_DATA_D3D12_OPTIONS& GetD3D12Options() const;
/** \brief Returns true if `D3D12_FEATURE_DATA_ARCHITECTURE1::UMA` was found to be true. /** \brief Returns true if `D3D12_FEATURE_DATA_ARCHITECTURE1::UMA` was found to be true.
@ -1469,6 +1484,9 @@ public:
/// Frees memory of a string returned from Allocator::BuildStatsString. /// Frees memory of a string returned from Allocator::BuildStatsString.
void FreeStatsString(WCHAR* pStatsString) const; void FreeStatsString(WCHAR* pStatsString) const;
protected:
virtual void ReleaseThis();
private: private:
friend HRESULT CreateAllocator(const ALLOCATOR_DESC*, Allocator**); friend HRESULT CreateAllocator(const ALLOCATOR_DESC*, Allocator**);
template<typename T> friend void D3D12MA_DELETE(const ALLOCATION_CALLBACKS&, T*); template<typename T> friend void D3D12MA_DELETE(const ALLOCATION_CALLBACKS&, T*);
@ -1540,16 +1558,11 @@ sub-allocation regions inside a single GPU buffer.
To create this object, fill in D3D12MA::VIRTUAL_BLOCK_DESC and call CreateVirtualBlock(). To create this object, fill in D3D12MA::VIRTUAL_BLOCK_DESC and call CreateVirtualBlock().
To destroy it, call its method VirtualBlock::Release(). To destroy it, call its method VirtualBlock::Release().
You need to free all the allocations within this block or call Clear() before destroying it.
*/ */
class VirtualBlock class VirtualBlock : public IUnknownImpl
{ {
public: public:
/** \brief Destroys this object and frees it from memory.
You need to free all the allocations within this block or call Clear() before destroying it.
*/
void Release();
/** \brief Returns true if the block is empty - contains 0 allocations. /** \brief Returns true if the block is empty - contains 0 allocations.
*/ */
BOOL IsEmpty() const; BOOL IsEmpty() const;
@ -1585,6 +1598,9 @@ public:
/** \brief Frees memory of a string returned from VirtualBlock::BuildStatsString. /** \brief Frees memory of a string returned from VirtualBlock::BuildStatsString.
*/ */
void FreeStatsString(WCHAR* pStatsString) const; void FreeStatsString(WCHAR* pStatsString) const;
protected:
virtual void ReleaseThis();
private: private:
friend HRESULT CreateVirtualBlock(const VIRTUAL_BLOCK_DESC*, VirtualBlock**); friend HRESULT CreateVirtualBlock(const VIRTUAL_BLOCK_DESC*, VirtualBlock**);

View File

@ -90,7 +90,7 @@ static float g_TimeDelta;
static DXGIUsage* g_DXGIUsage; static DXGIUsage* g_DXGIUsage;
static ComPtr<ID3D12Device> g_Device; static ComPtr<ID3D12Device> g_Device;
static D3D12MA::Allocator* g_Allocator; static ComPtr<D3D12MA::Allocator> g_Allocator;
static ComPtr<IDXGISwapChain3> g_SwapChain; // swapchain used to switch between render targets static ComPtr<IDXGISwapChain3> g_SwapChain; // swapchain used to switch between render targets
static ComPtr<ID3D12CommandQueue> g_CommandQueue; // container for command lists static ComPtr<ID3D12CommandQueue> g_CommandQueue; // container for command lists
@ -1575,7 +1575,7 @@ void Cleanup() // release com ojects and clean up memory
g_Fences[i].Reset(); g_Fences[i].Reset();
} }
g_Allocator->Release(); g_Allocator = nullptr; g_Allocator.Reset();
if(ENABLE_CPU_ALLOCATION_CALLBACKS) if(ENABLE_CPU_ALLOCATION_CALLBACKS)
{ {
assert(g_CpuAllocationCount.load() == 0); assert(g_CpuAllocationCount.load() == 0);
@ -1592,7 +1592,7 @@ static void ExecuteTests()
TestContext ctx = {}; TestContext ctx = {};
ctx.allocationCallbacks = &g_AllocationCallbacks; ctx.allocationCallbacks = &g_AllocationCallbacks;
ctx.device = g_Device.Get(); ctx.device = g_Device.Get();
ctx.allocator = g_Allocator; ctx.allocator = g_Allocator.Get();
ctx.allocatorFlags = g_AllocatorFlags; ctx.allocatorFlags = g_AllocatorFlags;
Test(ctx); Test(ctx);
} }

View File

@ -29,33 +29,17 @@ extern void EndCommandList(ID3D12GraphicsCommandList* cmdList);
static constexpr UINT64 MEGABYTE = 1024 * 1024; static constexpr UINT64 MEGABYTE = 1024 * 1024;
template<typename T>
struct D3d12maObjDeleter
{
void operator()(T* obj) const
{
if(obj)
{
obj->Release();
}
}
};
typedef std::unique_ptr<D3D12MA::Allocation, D3d12maObjDeleter<D3D12MA::Allocation>> AllocationUniquePtr;
typedef std::unique_ptr<D3D12MA::Pool, D3d12maObjDeleter<D3D12MA::Pool>> PoolUniquePtr;
typedef std::unique_ptr<D3D12MA::VirtualBlock, D3d12maObjDeleter<D3D12MA::VirtualBlock>> VirtualBlockUniquePtr;
struct ResourceWithAllocation struct ResourceWithAllocation
{ {
ComPtr<ID3D12Resource> resource; ComPtr<ID3D12Resource> resource;
AllocationUniquePtr allocation; ComPtr<D3D12MA::Allocation> allocation;
UINT64 size = UINT64_MAX; UINT64 size = UINT64_MAX;
UINT dataSeed = 0; UINT dataSeed = 0;
void Reset() void Reset()
{ {
resource.Reset(); resource.Reset();
allocation.reset(); allocation.Reset();
size = UINT64_MAX; size = UINT64_MAX;
dataSeed = 0; dataSeed = 0;
} }
@ -139,14 +123,12 @@ static void TestVirtualBlocks(const TestContext& ctx)
// # Create block 16 MB // # Create block 16 MB
VirtualBlockUniquePtr block; ComPtr<D3D12MA::VirtualBlock> block;
VirtualBlock* blockPtr = nullptr;
VIRTUAL_BLOCK_DESC blockDesc = {}; VIRTUAL_BLOCK_DESC blockDesc = {};
blockDesc.pAllocationCallbacks = ctx.allocationCallbacks; blockDesc.pAllocationCallbacks = ctx.allocationCallbacks;
blockDesc.Size = blockSize; blockDesc.Size = blockSize;
CHECK_HR( CreateVirtualBlock(&blockDesc, &blockPtr) ); CHECK_HR( CreateVirtualBlock(&blockDesc, &block) );
CHECK_BOOL( blockPtr ); CHECK_BOOL( block );
block.reset(blockPtr);
// # Allocate 8 MB // # Allocate 8 MB
@ -322,16 +304,14 @@ static void TestCommittedResourcesAndJson(const TestContext& ctx)
{ {
const bool receiveExplicitResource = i < 2; const bool receiveExplicitResource = i < 2;
D3D12MA::Allocation* alloc = nullptr;
CHECK_HR( ctx.allocator->CreateResource( CHECK_HR( ctx.allocator->CreateResource(
&allocDesc, &allocDesc,
&resourceDesc, &resourceDesc,
D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_DEST,
NULL, NULL,
&alloc, &resources[i].allocation,
__uuidof(ID3D12Resource), __uuidof(ID3D12Resource),
receiveExplicitResource ? (void**)&resources[i].resource : NULL)); receiveExplicitResource ? (void**)&resources[i].resource : NULL));
resources[i].allocation.reset(alloc);
if(receiveExplicitResource) if(receiveExplicitResource)
{ {
@ -385,10 +365,8 @@ static void TestCustomHeapFlags(const TestContext& ctx)
resAllocInfo.SizeInBytes = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; resAllocInfo.SizeInBytes = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
resAllocInfo.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; resAllocInfo.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
D3D12MA::Allocation* alloc = nullptr;
CHECK_HR( ctx.allocator->AllocateMemory(&allocDesc, &resAllocInfo, &alloc) );
ResourceWithAllocation res; ResourceWithAllocation res;
res.allocation.reset(alloc); CHECK_HR( ctx.allocator->AllocateMemory(&allocDesc, &resAllocInfo, &res.allocation) );
// Must be created as separate allocation. // Must be created as separate allocation.
CHECK_BOOL( res.allocation->GetOffset() == 0 ); CHECK_BOOL( res.allocation->GetOffset() == 0 );
@ -414,15 +392,13 @@ static void TestCustomHeapFlags(const TestContext& ctx)
allocDesc.ExtraHeapFlags = D3D12_HEAP_FLAG_SHARED | D3D12_HEAP_FLAG_SHARED_CROSS_ADAPTER; // Extra flags. allocDesc.ExtraHeapFlags = D3D12_HEAP_FLAG_SHARED | D3D12_HEAP_FLAG_SHARED_CROSS_ADAPTER; // Extra flags.
ResourceWithAllocation res; ResourceWithAllocation res;
D3D12MA::Allocation* alloc = nullptr;
CHECK_HR( ctx.allocator->CreateResource( CHECK_HR( ctx.allocator->CreateResource(
&allocDesc, &allocDesc,
&resourceDesc, &resourceDesc,
D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COMMON,
NULL, NULL,
&alloc, &res.allocation,
IID_PPV_ARGS(&res.resource)) ); IID_PPV_ARGS(&res.resource)) );
res.allocation.reset(alloc);
// Must be created as committed. // Must be created as committed.
CHECK_BOOL( res.allocation->GetHeap() == NULL ); CHECK_BOOL( res.allocation->GetHeap() == NULL );
@ -445,7 +421,6 @@ static void TestPlacedResources(const TestContext& ctx)
D3D12_RESOURCE_DESC resourceDesc; D3D12_RESOURCE_DESC resourceDesc;
FillResourceDescForBuffer(resourceDesc, bufSize); FillResourceDescForBuffer(resourceDesc, bufSize);
D3D12MA::Allocation* alloc = nullptr;
for(UINT i = 0; i < count; ++i) for(UINT i = 0; i < count; ++i)
{ {
CHECK_HR( ctx.allocator->CreateResource( CHECK_HR( ctx.allocator->CreateResource(
@ -453,9 +428,8 @@ static void TestPlacedResources(const TestContext& ctx)
&resourceDesc, &resourceDesc,
D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_GENERIC_READ,
NULL, NULL,
&alloc, &resources[i].allocation,
IID_PPV_ARGS(&resources[i].resource)) ); IID_PPV_ARGS(&resources[i].resource)) );
resources[i].allocation.reset(alloc);
// Make sure it doesn't have implicit heap. // Make sure it doesn't have implicit heap.
if(!alwaysCommitted) if(!alwaysCommitted)
@ -505,10 +479,9 @@ static void TestPlacedResources(const TestContext& ctx)
&resourceDesc, &resourceDesc,
D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_DEST,
NULL, NULL,
&alloc, &textureRes.allocation,
IID_PPV_ARGS(&textureRes.resource)) ); IID_PPV_ARGS(&textureRes.resource)) );
textureRes.allocation.reset(alloc);
// Additionally create an MSAA render target to see if no error occurs due to bad handling of Resource Tier. // Additionally create an MSAA render target to see if no error occurs due to bad handling of Resource Tier.
resourceDesc = {}; resourceDesc = {};
resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
@ -528,9 +501,8 @@ static void TestPlacedResources(const TestContext& ctx)
&resourceDesc, &resourceDesc,
D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_RENDER_TARGET,
NULL, NULL,
&alloc, &renderTargetRes.allocation,
IID_PPV_ARGS(&renderTargetRes.resource)) ); IID_PPV_ARGS(&renderTargetRes.resource)) );
renderTargetRes.allocation.reset(alloc);
} }
static void TestOtherComInterface(const TestContext& ctx) static void TestOtherComInterface(const TestContext& ctx)
@ -549,7 +521,7 @@ static void TestOtherComInterface(const TestContext& ctx)
allocDesc.Flags = D3D12MA::ALLOCATION_FLAG_COMMITTED; allocDesc.Flags = D3D12MA::ALLOCATION_FLAG_COMMITTED;
} }
D3D12MA::Allocation* alloc = nullptr; ComPtr<D3D12MA::Allocation> alloc;
ComPtr<ID3D12Pageable> pageable; ComPtr<ID3D12Pageable> pageable;
CHECK_HR(ctx.allocator->CreateResource( CHECK_HR(ctx.allocator->CreateResource(
&allocDesc, &allocDesc,
@ -563,8 +535,6 @@ static void TestOtherComInterface(const TestContext& ctx)
ComPtr<ID3D12Device> device; ComPtr<ID3D12Device> device;
CHECK_HR(pageable->GetDevice(IID_PPV_ARGS(&device))); CHECK_HR(pageable->GetDevice(IID_PPV_ARGS(&device)));
CHECK_BOOL(device.Get() == ctx.device); CHECK_BOOL(device.Get() == ctx.device);
alloc->Release();
} }
} }
@ -586,11 +556,8 @@ static void TestCustomPools(const TestContext& ctx)
poolDesc.MinBlockCount = 1; poolDesc.MinBlockCount = 1;
poolDesc.MaxBlockCount = 2; poolDesc.MaxBlockCount = 2;
D3D12MA::Pool* poolPtr; ComPtr<D3D12MA::Pool> pool;
CHECK_HR( ctx.allocator->CreatePool(&poolDesc, &poolPtr) ); CHECK_HR( ctx.allocator->CreatePool(&poolDesc, &pool) );
PoolUniquePtr pool{poolPtr};
D3D12MA::Allocation* allocPtr;
// # Validate stats for empty pool // # Validate stats for empty pool
@ -610,7 +577,7 @@ static void TestCustomPools(const TestContext& ctx)
// # Create buffers 2x 5 MB // # Create buffers 2x 5 MB
D3D12MA::ALLOCATION_DESC allocDesc = {}; D3D12MA::ALLOCATION_DESC allocDesc = {};
allocDesc.CustomPool = pool.get(); allocDesc.CustomPool = pool.Get();
allocDesc.ExtraHeapFlags = (D3D12_HEAP_FLAGS)0xCDCDCDCD; // Should be ignored. allocDesc.ExtraHeapFlags = (D3D12_HEAP_FLAGS)0xCDCDCDCD; // Should be ignored.
allocDesc.HeapType = (D3D12_HEAP_TYPE)0xCDCDCDCD; // Should be ignored. allocDesc.HeapType = (D3D12_HEAP_TYPE)0xCDCDCDCD; // Should be ignored.
@ -618,15 +585,14 @@ static void TestCustomPools(const TestContext& ctx)
D3D12_RESOURCE_DESC resDesc; D3D12_RESOURCE_DESC resDesc;
FillResourceDescForBuffer(resDesc, BUFFER_SIZE); FillResourceDescForBuffer(resDesc, BUFFER_SIZE);
AllocationUniquePtr allocs[4]; ComPtr<D3D12MA::Allocation> allocs[4];
for(uint32_t i = 0; i < 2; ++i) for(uint32_t i = 0; i < 2; ++i)
{ {
CHECK_HR( ctx.allocator->CreateResource(&allocDesc, &resDesc, CHECK_HR( ctx.allocator->CreateResource(&allocDesc, &resDesc,
D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_GENERIC_READ,
NULL, // pOptimizedClearValue NULL, // pOptimizedClearValue
&allocPtr, &allocs[i],
__uuidof(ID3D12Resource), NULL) ); // riidResource, ppvResource __uuidof(ID3D12Resource), NULL) ); // riidResource, ppvResource
allocs[i].reset(allocPtr);
} }
// # Validate pool stats now // # Validate pool stats now
@ -654,10 +620,11 @@ static void TestCustomPools(const TestContext& ctx)
allocDesc.Flags = i == 0 ? allocDesc.Flags = i == 0 ?
D3D12MA::ALLOCATION_FLAG_NEVER_ALLOCATE: D3D12MA::ALLOCATION_FLAG_NEVER_ALLOCATE:
D3D12MA::ALLOCATION_FLAG_COMMITTED; D3D12MA::ALLOCATION_FLAG_COMMITTED;
ComPtr<D3D12MA::Allocation> alloc;
const HRESULT hr = ctx.allocator->CreateResource(&allocDesc, &resDesc, const HRESULT hr = ctx.allocator->CreateResource(&allocDesc, &resDesc,
D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_GENERIC_READ,
NULL, // pOptimizedClearValue NULL, // pOptimizedClearValue
&allocPtr, &alloc,
__uuidof(ID3D12Resource), NULL); // riidResource, ppvResource __uuidof(ID3D12Resource), NULL); // riidResource, ppvResource
CHECK_BOOL( FAILED(hr) ); CHECK_BOOL( FAILED(hr) );
} }
@ -667,15 +634,16 @@ static void TestCustomPools(const TestContext& ctx)
allocDesc.Flags = D3D12MA::ALLOCATION_FLAG_NONE; allocDesc.Flags = D3D12MA::ALLOCATION_FLAG_NONE;
for(uint32_t i = 2; i < 5; ++i) for(uint32_t i = 2; i < 5; ++i)
{ {
ComPtr<D3D12MA::Allocation> alloc;
HRESULT hr = ctx.allocator->CreateResource(&allocDesc, &resDesc, HRESULT hr = ctx.allocator->CreateResource(&allocDesc, &resDesc,
D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_GENERIC_READ,
NULL, // pOptimizedClearValue NULL, // pOptimizedClearValue
&allocPtr, &alloc,
__uuidof(ID3D12Resource), NULL); // riidResource, ppvResource __uuidof(ID3D12Resource), NULL); // riidResource, ppvResource
if(i < 4) if(i < 4)
{ {
CHECK_HR( hr ); CHECK_HR( hr );
allocs[i].reset(allocPtr); allocs[i] = std::move(alloc);
} }
else else
{ {
@ -691,19 +659,18 @@ static void TestCustomPools(const TestContext& ctx)
// # Make room, AllocateMemory, CreateAliasingResource // # Make room, AllocateMemory, CreateAliasingResource
allocs[3].reset(); allocs[3].Reset();
allocs[0].reset(); allocs[0].Reset();
D3D12_RESOURCE_ALLOCATION_INFO resAllocInfo = {}; D3D12_RESOURCE_ALLOCATION_INFO resAllocInfo = {};
resAllocInfo.SizeInBytes = 5 * MEGABYTE; resAllocInfo.SizeInBytes = 5 * MEGABYTE;
resAllocInfo.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; resAllocInfo.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
CHECK_HR( ctx.allocator->AllocateMemory(&allocDesc, &resAllocInfo, &allocPtr) ); CHECK_HR( ctx.allocator->AllocateMemory(&allocDesc, &resAllocInfo, &allocs[0]) );
allocs[0].reset(allocPtr);
resDesc.Width = 1 * MEGABYTE; resDesc.Width = 1 * MEGABYTE;
ComPtr<ID3D12Resource> res; ComPtr<ID3D12Resource> res;
CHECK_HR( ctx.allocator->CreateAliasingResource(allocs[0].get(), CHECK_HR( ctx.allocator->CreateAliasingResource(allocs[0].Get(),
0, // AllocationLocalOffset 0, // AllocationLocalOffset
&resDesc, &resDesc,
D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_GENERIC_READ,
@ -724,27 +691,24 @@ static void TestCustomPool_MinAllocationAlignment(const TestContext& ctx)
poolDesc.HeapFlags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS; poolDesc.HeapFlags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS;
poolDesc.MinAllocationAlignment = MIN_ALIGNMENT; poolDesc.MinAllocationAlignment = MIN_ALIGNMENT;
D3D12MA::Pool* poolPtr; ComPtr<D3D12MA::Pool> pool;
CHECK_HR( ctx.allocator->CreatePool(&poolDesc, &poolPtr) ); CHECK_HR( ctx.allocator->CreatePool(&poolDesc, &pool) );
PoolUniquePtr pool{poolPtr};
D3D12MA::Allocation* allocPtr;
D3D12MA::ALLOCATION_DESC allocDesc = {}; D3D12MA::ALLOCATION_DESC allocDesc = {};
allocDesc.CustomPool = pool.get(); allocDesc.CustomPool = pool.Get();
D3D12_RESOURCE_DESC resDesc; D3D12_RESOURCE_DESC resDesc;
FillResourceDescForBuffer(resDesc, BUFFER_SIZE); FillResourceDescForBuffer(resDesc, BUFFER_SIZE);
AllocationUniquePtr allocs[BUFFER_COUNT]; ComPtr<D3D12MA::Allocation> allocs[BUFFER_COUNT];
for(size_t i = 0; i < BUFFER_COUNT; ++i) for(size_t i = 0; i < BUFFER_COUNT; ++i)
{ {
CHECK_HR( ctx.allocator->CreateResource(&allocDesc, &resDesc, CHECK_HR( ctx.allocator->CreateResource(&allocDesc, &resDesc,
D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_GENERIC_READ,
NULL, // pOptimizedClearValue NULL, // pOptimizedClearValue
&allocPtr, &allocs[i],
IID_NULL, NULL) ); // riidResource, ppvResource IID_NULL, NULL) ); // riidResource, ppvResource
allocs[i].reset(allocPtr); CHECK_BOOL(allocs[i]->GetOffset() % MIN_ALIGNMENT == 0);
CHECK_BOOL(allocPtr->GetOffset() % MIN_ALIGNMENT == 0);
} }
} }
@ -762,25 +726,23 @@ static HRESULT TestCustomHeap(const TestContext& ctx, const D3D12_HEAP_PROPERTIE
const UINT64 BUFFER_SIZE = 1 * MEGABYTE; const UINT64 BUFFER_SIZE = 1 * MEGABYTE;
D3D12MA::Pool* poolPtr; ComPtr<D3D12MA::Pool> pool;
HRESULT hr = ctx.allocator->CreatePool(&poolDesc, &poolPtr); HRESULT hr = ctx.allocator->CreatePool(&poolDesc, &pool);
PoolUniquePtr pool{poolPtr};
if(SUCCEEDED(hr)) if(SUCCEEDED(hr))
{ {
D3D12MA::ALLOCATION_DESC allocDesc = {}; D3D12MA::ALLOCATION_DESC allocDesc = {};
allocDesc.CustomPool = pool.get(); allocDesc.CustomPool = pool.Get();
D3D12_RESOURCE_DESC resDesc; D3D12_RESOURCE_DESC resDesc;
FillResourceDescForBuffer(resDesc, BUFFER_SIZE); FillResourceDescForBuffer(resDesc, BUFFER_SIZE);
// Pool already allocated a block. We don't expect CreatePlacedResource to fail. // Pool already allocated a block. We don't expect CreatePlacedResource to fail.
D3D12MA::Allocation* allocPtr; ComPtr<D3D12MA::Allocation> alloc;
CHECK_HR( ctx.allocator->CreateResource(&allocDesc, &resDesc, CHECK_HR( ctx.allocator->CreateResource(&allocDesc, &resDesc,
D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_DEST,
NULL, // pOptimizedClearValue NULL, // pOptimizedClearValue
&allocPtr, &alloc,
__uuidof(ID3D12Resource), NULL) ); // riidResource, ppvResource __uuidof(ID3D12Resource), NULL) ); // riidResource, ppvResource
AllocationUniquePtr alloc{allocPtr};
D3D12MA::Stats globalStatsCurr = {}; D3D12MA::Stats globalStatsCurr = {};
ctx.allocator->CalculateStats(&globalStatsCurr); ctx.allocator->CalculateStats(&globalStatsCurr);
@ -840,11 +802,10 @@ static void TestStandardCustomCommittedPlaced(const TestContext& ctx)
poolDesc.HeapProperties.Type = heapType; poolDesc.HeapProperties.Type = heapType;
poolDesc.HeapFlags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS; poolDesc.HeapFlags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS;
D3D12MA::Pool* poolPtr; ComPtr<D3D12MA::Pool> pool;
CHECK_HR(ctx.allocator->CreatePool(&poolDesc, &poolPtr)); CHECK_HR(ctx.allocator->CreatePool(&poolDesc, &pool));
PoolUniquePtr pool{poolPtr};
std::vector<AllocationUniquePtr> allocations; std::vector<ComPtr<D3D12MA::Allocation>> allocations;
D3D12MA::Stats statsBeg = {}; D3D12MA::Stats statsBeg = {};
D3D12MA::StatInfo poolStatInfoBeg = {}; D3D12MA::StatInfo poolStatInfoBeg = {};
@ -867,7 +828,7 @@ static void TestStandardCustomCommittedPlaced(const TestContext& ctx)
D3D12MA::ALLOCATION_DESC allocDesc = {}; D3D12MA::ALLOCATION_DESC allocDesc = {};
if(useCustomPool) if(useCustomPool)
{ {
allocDesc.CustomPool = pool.get(); allocDesc.CustomPool = pool.Get();
allocDesc.HeapType = (D3D12_HEAP_TYPE)0xCDCDCDCD; // Should be ignored. allocDesc.HeapType = (D3D12_HEAP_TYPE)0xCDCDCDCD; // Should be ignored.
allocDesc.ExtraHeapFlags = (D3D12_HEAP_FLAGS)0xCDCDCDCD; // Should be ignored. allocDesc.ExtraHeapFlags = (D3D12_HEAP_FLAGS)0xCDCDCDCD; // Should be ignored.
} }
@ -878,7 +839,7 @@ static void TestStandardCustomCommittedPlaced(const TestContext& ctx)
if(neverAllocate) if(neverAllocate)
allocDesc.Flags |= D3D12MA::ALLOCATION_FLAG_NEVER_ALLOCATE; allocDesc.Flags |= D3D12MA::ALLOCATION_FLAG_NEVER_ALLOCATE;
D3D12MA::Allocation* allocPtr = NULL; ComPtr<D3D12MA::Allocation> allocPtr = NULL;
HRESULT hr = ctx.allocator->CreateResource(&allocDesc, &resDesc, HRESULT hr = ctx.allocator->CreateResource(&allocDesc, &resDesc,
D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COMMON,
NULL, // pOptimizedClearValue NULL, // pOptimizedClearValue
@ -886,7 +847,7 @@ static void TestStandardCustomCommittedPlaced(const TestContext& ctx)
CHECK_BOOL(SUCCEEDED(hr) == (allocPtr != NULL)); CHECK_BOOL(SUCCEEDED(hr) == (allocPtr != NULL));
if(allocPtr) if(allocPtr)
{ {
allocations.push_back(AllocationUniquePtr{allocPtr}); allocations.push_back(allocPtr);
if(useCustomPool) if(useCustomPool)
++poolAllocCount; ++poolAllocCount;
} }
@ -956,13 +917,13 @@ static void TestAliasingMemory(const TestContext& ctx)
allocDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT; allocDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT;
allocDesc.ExtraHeapFlags = D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES; allocDesc.ExtraHeapFlags = D3D12_HEAP_FLAG_ALLOW_ONLY_RT_DS_TEXTURES;
D3D12MA::Allocation* alloc = NULL; ComPtr<D3D12MA::Allocation> alloc;
CHECK_HR( ctx.allocator->AllocateMemory(&allocDesc, &finalAllocInfo, &alloc) ); CHECK_HR( ctx.allocator->AllocateMemory(&allocDesc, &finalAllocInfo, &alloc) );
CHECK_BOOL(alloc != NULL && alloc->GetHeap() != NULL); CHECK_BOOL(alloc != NULL && alloc->GetHeap() != NULL);
ID3D12Resource* res1 = NULL; ComPtr<ID3D12Resource> res1;
CHECK_HR( ctx.allocator->CreateAliasingResource( CHECK_HR( ctx.allocator->CreateAliasingResource(
alloc, alloc.Get(),
0, // AllocationLocalOffset 0, // AllocationLocalOffset
&resDesc1, &resDesc1,
D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COMMON,
@ -970,9 +931,9 @@ static void TestAliasingMemory(const TestContext& ctx)
IID_PPV_ARGS(&res1)) ); IID_PPV_ARGS(&res1)) );
CHECK_BOOL(res1 != NULL); CHECK_BOOL(res1 != NULL);
ID3D12Resource* res2 = NULL; ComPtr<ID3D12Resource> res2;
CHECK_HR( ctx.allocator->CreateAliasingResource( CHECK_HR( ctx.allocator->CreateAliasingResource(
alloc, alloc.Get(),
0, // AllocationLocalOffset 0, // AllocationLocalOffset
&resDesc2, &resDesc2,
D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COMMON,
@ -981,10 +942,6 @@ static void TestAliasingMemory(const TestContext& ctx)
CHECK_BOOL(res2 != NULL); CHECK_BOOL(res2 != NULL);
// You can use res1 and res2, but not at the same time! // You can use res1 and res2, but not at the same time!
res2->Release();
res1->Release();
alloc->Release();
} }
static void TestMapping(const TestContext& ctx) static void TestMapping(const TestContext& ctx)
@ -1003,15 +960,13 @@ static void TestMapping(const TestContext& ctx)
for(UINT i = 0; i < count; ++i) for(UINT i = 0; i < count; ++i)
{ {
D3D12MA::Allocation* alloc = nullptr;
CHECK_HR( ctx.allocator->CreateResource( CHECK_HR( ctx.allocator->CreateResource(
&allocDesc, &allocDesc,
&resourceDesc, &resourceDesc,
D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_GENERIC_READ,
NULL, NULL,
&alloc, &resources[i].allocation,
IID_PPV_ARGS(&resources[i].resource)) ); IID_PPV_ARGS(&resources[i].resource)) );
resources[i].allocation.reset(alloc);
void* mappedPtr = NULL; void* mappedPtr = NULL;
CHECK_HR( resources[i].resource->Map(0, &EMPTY_RANGE, &mappedPtr) ); CHECK_HR( resources[i].resource->Map(0, &EMPTY_RANGE, &mappedPtr) );
@ -1082,15 +1037,13 @@ static void TestStats(const TestContext& ctx)
{ {
if(i == count / 2) if(i == count / 2)
allocDesc.Flags |= D3D12MA::ALLOCATION_FLAG_COMMITTED; allocDesc.Flags |= D3D12MA::ALLOCATION_FLAG_COMMITTED;
D3D12MA::Allocation* alloc = nullptr;
CHECK_HR( ctx.allocator->CreateResource( CHECK_HR( ctx.allocator->CreateResource(
&allocDesc, &allocDesc,
&resourceDesc, &resourceDesc,
D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_GENERIC_READ,
NULL, NULL,
&alloc, &resources[i].allocation,
IID_PPV_ARGS(&resources[i].resource)) ); IID_PPV_ARGS(&resources[i].resource)) );
resources[i].allocation.reset(alloc);
} }
D3D12MA::Stats endStats = {}; D3D12MA::Stats endStats = {};
@ -1153,33 +1106,29 @@ static void TestTransfer(const TestContext& ctx)
// Create 3 sets of resources. // Create 3 sets of resources.
for(UINT i = 0; i < count; ++i) for(UINT i = 0; i < count; ++i)
{ {
D3D12MA::Allocation* alloc = nullptr;
CHECK_HR( ctx.allocator->CreateResource( CHECK_HR( ctx.allocator->CreateResource(
&allocDescUpload, &allocDescUpload,
&resourceDesc, &resourceDesc,
D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_GENERIC_READ,
NULL, NULL,
&alloc, &resourcesUpload[i].allocation,
IID_PPV_ARGS(&resourcesUpload[i].resource)) ); IID_PPV_ARGS(&resourcesUpload[i].resource)) );
resourcesUpload[i].allocation.reset(alloc);
CHECK_HR( ctx.allocator->CreateResource( CHECK_HR( ctx.allocator->CreateResource(
&allocDescDefault, &allocDescDefault,
&resourceDesc, &resourceDesc,
D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_DEST,
NULL, NULL,
&alloc, &resourcesDefault[i].allocation,
IID_PPV_ARGS(&resourcesDefault[i].resource)) ); IID_PPV_ARGS(&resourcesDefault[i].resource)) );
resourcesDefault[i].allocation.reset(alloc);
CHECK_HR( ctx.allocator->CreateResource( CHECK_HR( ctx.allocator->CreateResource(
&allocDescReadback, &allocDescReadback,
&resourceDesc, &resourceDesc,
D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_DEST,
NULL, NULL,
&alloc, &resourcesReadback[i].allocation,
IID_PPV_ARGS(&resourcesReadback[i].resource)) ); IID_PPV_ARGS(&resourcesReadback[i].resource)) );
resourcesReadback[i].allocation.reset(alloc);
} }
// Map and fill data in UPLOAD. // Map and fill data in UPLOAD.
@ -1241,7 +1190,6 @@ static void TestZeroInitialized(const TestContext& ctx)
wprintf(L"Test zero initialized\n"); wprintf(L"Test zero initialized\n");
const UINT64 bufSize = 128ull * 1024; const UINT64 bufSize = 128ull * 1024;
D3D12MA::Allocation* alloc = nullptr;
D3D12_RESOURCE_DESC resourceDesc; D3D12_RESOURCE_DESC resourceDesc;
FillResourceDescForBuffer(resourceDesc, bufSize); FillResourceDescForBuffer(resourceDesc, bufSize);
@ -1257,9 +1205,8 @@ static void TestZeroInitialized(const TestContext& ctx)
&resourceDesc, &resourceDesc,
D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_GENERIC_READ,
NULL, NULL,
&alloc, &bufUpload.allocation,
IID_PPV_ARGS(&bufUpload.resource)) ); IID_PPV_ARGS(&bufUpload.resource)) );
bufUpload.allocation.reset(alloc);
{ {
void* mappedPtr = nullptr; void* mappedPtr = nullptr;
@ -1279,9 +1226,8 @@ static void TestZeroInitialized(const TestContext& ctx)
&resourceDesc, &resourceDesc,
D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_COPY_DEST,
NULL, NULL,
&alloc, &bufReadback.allocation,
IID_PPV_ARGS(&bufReadback.resource)) ); IID_PPV_ARGS(&bufReadback.resource)) );
bufReadback.allocation.reset(alloc);
auto CheckBufferData = [&](const ResourceWithAllocation& buf) auto CheckBufferData = [&](const ResourceWithAllocation& buf)
{ {
@ -1323,9 +1269,8 @@ static void TestZeroInitialized(const TestContext& ctx)
&resourceDesc, &resourceDesc,
D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_COPY_SOURCE,
NULL, NULL,
&alloc, &bufDefault.allocation,
IID_PPV_ARGS(&bufDefault.resource)) ); IID_PPV_ARGS(&bufDefault.resource)) );
bufDefault.allocation.reset(alloc);
wprintf(L" Committed: "); wprintf(L" Committed: ");
CheckBufferData(bufDefault); CheckBufferData(bufDefault);
@ -1347,9 +1292,8 @@ static void TestZeroInitialized(const TestContext& ctx)
&resourceDesc, &resourceDesc,
D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_COPY_SOURCE,
NULL, NULL,
&alloc, &bufDefault.allocation,
IID_PPV_ARGS(&bufDefault.resource)) ); IID_PPV_ARGS(&bufDefault.resource)) );
bufDefault.allocation.reset(alloc);
// 2. Check it // 2. Check it
@ -1413,15 +1357,13 @@ static void TestMultithreading(const TestContext& ctx)
D3D12_RESOURCE_DESC resourceDesc; D3D12_RESOURCE_DESC resourceDesc;
FillResourceDescForBuffer(resourceDesc, res.size); FillResourceDescForBuffer(resourceDesc, res.size);
D3D12MA::Allocation* alloc = nullptr;
CHECK_HR( ctx.allocator->CreateResource( CHECK_HR( ctx.allocator->CreateResource(
&allocDesc, &allocDesc,
&resourceDesc, &resourceDesc,
D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_GENERIC_READ,
NULL, NULL,
&alloc, &res.allocation,
IID_PPV_ARGS(&res.resource)) ); IID_PPV_ARGS(&res.resource)) );
res.allocation.reset(alloc);
void* mappedPtr = nullptr; void* mappedPtr = nullptr;
CHECK_HR( res.resource->Map(0, &EMPTY_RANGE, &mappedPtr) ); CHECK_HR( res.resource->Map(0, &EMPTY_RANGE, &mappedPtr) );
@ -1458,15 +1400,13 @@ static void TestMultithreading(const TestContext& ctx)
D3D12_RESOURCE_DESC resourceDesc; D3D12_RESOURCE_DESC resourceDesc;
FillResourceDescForBuffer(resourceDesc, res.size); FillResourceDescForBuffer(resourceDesc, res.size);
D3D12MA::Allocation* alloc = nullptr;
CHECK_HR( ctx.allocator->CreateResource( CHECK_HR( ctx.allocator->CreateResource(
&allocDesc, &allocDesc,
&resourceDesc, &resourceDesc,
D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_GENERIC_READ,
NULL, NULL,
&alloc, &res.allocation,
IID_PPV_ARGS(&res.resource)) ); IID_PPV_ARGS(&res.resource)) );
res.allocation.reset(alloc);
void* mappedPtr = nullptr; void* mappedPtr = nullptr;
CHECK_HR( res.resource->Map(0, NULL, &mappedPtr) ); CHECK_HR( res.resource->Map(0, NULL, &mappedPtr) );
@ -1556,12 +1496,11 @@ static void TestDevice4(const TestContext& ctx)
D3D12MA::ALLOCATION_DESC allocDesc = {}; D3D12MA::ALLOCATION_DESC allocDesc = {};
allocDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT; allocDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT;
D3D12MA::Allocation* alloc = nullptr; ComPtr<D3D12MA::Allocation> bufAlloc;
ComPtr<ID3D12Resource> bufRes; ComPtr<ID3D12Resource> bufRes;
CHECK_HR(ctx.allocator->CreateResource1(&allocDesc, &resourceDesc, CHECK_HR(ctx.allocator->CreateResource1(&allocDesc, &resourceDesc,
D3D12_RESOURCE_STATE_COMMON, NULL, D3D12_RESOURCE_STATE_COMMON, NULL,
session.Get(), &alloc, IID_PPV_ARGS(&bufRes))); session.Get(), &bufAlloc, IID_PPV_ARGS(&bufRes)));
AllocationUniquePtr bufAllocPtr{alloc};
// Create a heap // Create a heap
// Temporarily commented out as it caues BSOD on RTX2080Ti driver 461.40. // Temporarily commented out as it caues BSOD on RTX2080Ti driver 461.40.
@ -1592,25 +1531,23 @@ static void TestDevice8(const TestContext& ctx)
allocDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT; allocDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT;
allocDesc.Flags = D3D12MA::ALLOCATION_FLAG_COMMITTED; allocDesc.Flags = D3D12MA::ALLOCATION_FLAG_COMMITTED;
D3D12MA::Allocation* alloc0 = nullptr; ComPtr<D3D12MA::Allocation> allocPtr0;
ComPtr<ID3D12Resource> res0; ComPtr<ID3D12Resource> res0;
CHECK_HR(ctx.allocator->CreateResource2(&allocDesc, &resourceDesc, CHECK_HR(ctx.allocator->CreateResource2(&allocDesc, &resourceDesc,
D3D12_RESOURCE_STATE_COMMON, NULL, NULL, D3D12_RESOURCE_STATE_COMMON, NULL, NULL,
&alloc0, IID_PPV_ARGS(&res0))); &allocPtr0, IID_PPV_ARGS(&res0)));
AllocationUniquePtr allocPtr0{alloc0}; CHECK_BOOL(allocPtr0->GetHeap() == NULL);
CHECK_BOOL(alloc0->GetHeap() == NULL);
// Create a placed buffer // Create a placed buffer
allocDesc.Flags &= ~D3D12MA::ALLOCATION_FLAG_COMMITTED; allocDesc.Flags &= ~D3D12MA::ALLOCATION_FLAG_COMMITTED;
D3D12MA::Allocation* alloc1 = nullptr; ComPtr<D3D12MA::Allocation> allocPtr1;
ComPtr<ID3D12Resource> res1; ComPtr<ID3D12Resource> res1;
CHECK_HR(ctx.allocator->CreateResource2(&allocDesc, &resourceDesc, CHECK_HR(ctx.allocator->CreateResource2(&allocDesc, &resourceDesc,
D3D12_RESOURCE_STATE_COMMON, NULL, NULL, D3D12_RESOURCE_STATE_COMMON, NULL, NULL,
&alloc1, IID_PPV_ARGS(&res1))); &allocPtr1, IID_PPV_ARGS(&res1)));
AllocationUniquePtr allocPtr1{alloc1}; CHECK_BOOL(allocPtr1->GetHeap()!= NULL);
CHECK_BOOL(alloc1->GetHeap()!= NULL);
} }
static void TestGroupVirtual(const TestContext& ctx) static void TestGroupVirtual(const TestContext& ctx)