Added Allocator::CreateResource1, AllocateMemory1
diff --git a/src/D3D12MemAlloc.cpp b/src/D3D12MemAlloc.cpp
index d5ad4b0..a7ab321 100644
--- a/src/D3D12MemAlloc.cpp
+++ b/src/D3D12MemAlloc.cpp
@@ -2462,6 +2462,9 @@
     ~AllocatorPimpl();

 

     ID3D12Device* GetDevice() const { return m_Device; }

+#ifdef __ID3D12Device4_INTERFACE_DEFINED__

+    ID3D12Device4* GetDevice4() const { return m_Device4; }

+#endif

     // Shortcut for "Allocation Callbacks", because this function is called so often.

     const ALLOCATION_CALLBACKS& GetAllocs() const { return m_AllocationCallbacks; }

     const D3D12_FEATURE_DATA_D3D12_OPTIONS& GetD3D12Options() const { return m_D3D12Options; }

@@ -2479,11 +2482,31 @@
         REFIID riidResource,

         void** ppvResource);

 

+#ifdef __ID3D12Device4_INTERFACE_DEFINED__

+    HRESULT CreateResource1(

+        const ALLOCATION_DESC* pAllocDesc,

+        const D3D12_RESOURCE_DESC* pResourceDesc,

+        D3D12_RESOURCE_STATES InitialResourceState,

+        const D3D12_CLEAR_VALUE *pOptimizedClearValue,

+        ID3D12ProtectedResourceSession *pProtectedSession,

+        Allocation** ppAllocation,

+        REFIID riidResource,

+        void** ppvResource);

+#endif // #ifdef __ID3D12Device4_INTERFACE_DEFINED__

+

     HRESULT AllocateMemory(

         const ALLOCATION_DESC* pAllocDesc,

         const D3D12_RESOURCE_ALLOCATION_INFO* pAllocInfo,

         Allocation** ppAllocation);

 

+#ifdef __ID3D12Device4_INTERFACE_DEFINED__

+    HRESULT AllocateMemory1(

+        const ALLOCATION_DESC* pAllocDesc,

+        const D3D12_RESOURCE_ALLOCATION_INFO* pAllocInfo,

+        ID3D12ProtectedResourceSession *pProtectedSession,

+        Allocation** ppAllocation);

+#endif // #ifdef __ID3D12Device4_INTERFACE_DEFINED__

+

     HRESULT CreateAliasingResource(

         Allocation* pAllocation,

         UINT64 AllocationLocalOffset,

@@ -2534,9 +2557,12 @@
     const bool m_UseMutex;

     const bool m_AlwaysCommitted;

     ID3D12Device* m_Device; // AddRef

+#ifdef __ID3D12Device4_INTERFACE_DEFINED__

+    ID3D12Device4* m_Device4 = NULL; // AddRef, optional

+#endif

     IDXGIAdapter* m_Adapter; // AddRef

 #if D3D12MA_DXGI_1_4

-    IDXGIAdapter3* m_Adapter3; // AddRef, optional

+    IDXGIAdapter3* m_Adapter3 = NULL; // AddRef, optional

 #endif

     UINT64 m_PreferredBlockSize;

     ALLOCATION_CALLBACKS m_AllocationCallbacks;

@@ -2573,6 +2599,19 @@
         REFIID riidResource,

         void** ppvResource);

 

+#ifdef __ID3D12Device4_INTERFACE_DEFINED__

+    HRESULT AllocateCommittedResource1(

+        const ALLOCATION_DESC* pAllocDesc,

+        const D3D12_RESOURCE_DESC* pResourceDesc,

+        const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo,

+        D3D12_RESOURCE_STATES InitialResourceState,

+        const D3D12_CLEAR_VALUE *pOptimizedClearValue,

+        ID3D12ProtectedResourceSession *pProtectedSession,

+        Allocation** ppAllocation,

+        REFIID riidResource,

+        void** ppvResource);

+#endif // #ifdef __ID3D12Device4_INTERFACE_DEFINED__

+

     // Allocates and registers new heap without any resources placed in it, as dedicated allocation.

     // Creates and returns Allocation object.

     HRESULT AllocateHeap(

@@ -2580,6 +2619,14 @@
         const D3D12_RESOURCE_ALLOCATION_INFO& allocInfo,

         Allocation** ppAllocation);

 

+#ifdef __ID3D12Device4_INTERFACE_DEFINED__

+    HRESULT AllocateHeap1(

+        const ALLOCATION_DESC* pAllocDesc,

+        const D3D12_RESOURCE_ALLOCATION_INFO& allocInfo,

+        ID3D12ProtectedResourceSession *pProtectedSession,

+        Allocation** ppAllocation);

+#endif // #ifdef __ID3D12Device4_INTERFACE_DEFINED__

+

     /*

     If SupportsResourceHeapTier2():

         0: D3D12_HEAP_TYPE_DEFAULT

@@ -4061,9 +4108,6 @@
     m_AlwaysCommitted((desc.Flags & ALLOCATOR_FLAG_ALWAYS_COMMITTED) != 0),

     m_Device(desc.pDevice),

     m_Adapter(desc.pAdapter),

-#if D3D12MA_DXGI_1_4

-    m_Adapter3(NULL),

-#endif

     m_PreferredBlockSize(desc.PreferredBlockSize != 0 ? desc.PreferredBlockSize : D3D12MA_DEFAULT_BLOCK_SIZE),

     m_AllocationCallbacks(allocationCallbacks),

     m_CurrentFrameIndex(0),

@@ -4099,6 +4143,10 @@
     desc.pAdapter->QueryInterface<IDXGIAdapter3>(&m_Adapter3);

 #endif

 

+#ifdef __ID3D12Device4_INTERFACE_DEFINED__

+    m_Device->QueryInterface<ID3D12Device4>(&m_Device4);

+#endif

+

     HRESULT hr = m_Adapter->GetDesc(&m_AdapterDesc);

     if(FAILED(hr))

     {

@@ -4141,6 +4189,9 @@
 

 AllocatorPimpl::~AllocatorPimpl()

 {

+#ifdef __ID3D12Device4_INTERFACE_DEFINED__

+    SAFE_RELEASE(m_Device4);

+#endif

 #if D3D12MA_DXGI_1_4

     SAFE_RELEASE(m_Adapter3);

 #endif

@@ -4314,6 +4365,55 @@
     }

 }

 

+#ifdef __ID3D12Device4_INTERFACE_DEFINED__

+HRESULT AllocatorPimpl::CreateResource1(

+    const ALLOCATION_DESC* pAllocDesc,

+    const D3D12_RESOURCE_DESC* pResourceDesc,

+    D3D12_RESOURCE_STATES InitialResourceState,

+    const D3D12_CLEAR_VALUE *pOptimizedClearValue,

+    ID3D12ProtectedResourceSession *pProtectedSession,

+    Allocation** ppAllocation,

+    REFIID riidResource,

+    void** ppvResource)

+{

+    // Fall back to old implementation

+    if(pProtectedSession == NULL)

+    {

+        return CreateResource(pAllocDesc, pResourceDesc, InitialResourceState, pOptimizedClearValue, ppAllocation, riidResource, ppvResource);

+    }

+

+    *ppAllocation = NULL;

+    if(ppvResource)

+    {

+        *ppvResource = NULL;

+    }

+

+    // In current implementation it must always be allocated as committed.

+    if(pAllocDesc->CustomPool != NULL ||

+        (pAllocDesc->Flags & ALLOCATION_FLAG_NEVER_ALLOCATE) != 0)

+    {

+        return E_INVALIDARG;

+    }

+

+    D3D12_RESOURCE_DESC finalResourceDesc = *pResourceDesc;

+    D3D12_RESOURCE_ALLOCATION_INFO resAllocInfo = GetResourceAllocationInfo(finalResourceDesc);

+    resAllocInfo.Alignment = D3D12MA_MAX<UINT64>(resAllocInfo.Alignment, D3D12MA_DEBUG_ALIGNMENT);

+    D3D12MA_ASSERT(IsPow2(resAllocInfo.Alignment));

+    D3D12MA_ASSERT(resAllocInfo.SizeInBytes > 0);

+

+    return AllocateCommittedResource1(

+        pAllocDesc,

+        &finalResourceDesc,

+        resAllocInfo,

+        InitialResourceState,

+        pOptimizedClearValue,

+        pProtectedSession,

+        ppAllocation,

+        riidResource,

+        ppvResource);

+}

+#endif // #ifdef __ID3D12Device4_INTERFACE_DEFINED__

+

 HRESULT AllocatorPimpl::AllocateMemory(

     const ALLOCATION_DESC* pAllocDesc,

     const D3D12_RESOURCE_ALLOCATION_INFO* pAllocInfo,

@@ -4384,6 +4484,37 @@
     }

 }

 

+#ifdef __ID3D12Device4_INTERFACE_DEFINED__

+HRESULT AllocatorPimpl::AllocateMemory1(

+    const ALLOCATION_DESC* pAllocDesc,

+    const D3D12_RESOURCE_ALLOCATION_INFO* pAllocInfo,

+    ID3D12ProtectedResourceSession *pProtectedSession,

+    Allocation** ppAllocation)

+{

+    // Fall back to old implementation

+    if(pProtectedSession == NULL)

+    {

+        return AllocateMemory(pAllocDesc, pAllocInfo, ppAllocation);

+    }

+

+    *ppAllocation = NULL;

+

+    // In current implementation it must always be allocated as separate CreateHeap1.

+    if(pAllocDesc->CustomPool != NULL ||

+        (pAllocDesc->Flags & ALLOCATION_FLAG_NEVER_ALLOCATE) != 0)

+    {

+        return E_INVALIDARG;

+    }

+

+    if(!IsHeapTypeValid(pAllocDesc->HeapType))

+    {

+        return E_INVALIDARG;

+    }

+

+    return AllocateHeap1(pAllocDesc, *pAllocInfo, pProtectedSession, ppAllocation);

+}

+#endif // #ifdef __ID3D12Device4_INTERFACE_DEFINED__

+

 HRESULT AllocatorPimpl::CreateAliasingResource(

     Allocation* pAllocation,

     UINT64 AllocationLocalOffset,

@@ -4557,6 +4688,77 @@
     return hr;

 }

 

+#ifdef __ID3D12Device4_INTERFACE_DEFINED__

+HRESULT AllocatorPimpl::AllocateCommittedResource1(

+    const ALLOCATION_DESC* pAllocDesc,

+    const D3D12_RESOURCE_DESC* pResourceDesc,

+    const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo,

+    D3D12_RESOURCE_STATES InitialResourceState,

+    const D3D12_CLEAR_VALUE *pOptimizedClearValue,

+    ID3D12ProtectedResourceSession *pProtectedSession,

+    Allocation** ppAllocation,

+    REFIID riidResource,

+    void** ppvResource)

+{

+    if(m_Device4 == NULL)

+    {

+        return E_NOINTERFACE;

+    }

+

+    if((pAllocDesc->Flags & ALLOCATION_FLAG_NEVER_ALLOCATE) != 0)

+    {

+        return E_OUTOFMEMORY;

+    }

+

+    if((pAllocDesc->Flags & ALLOCATION_FLAG_WITHIN_BUDGET) != 0)

+    {

+        Budget budget = {};

+        GetBudgetForHeapType(budget, pAllocDesc->HeapType);

+        if(budget.UsageBytes + resAllocInfo.SizeInBytes > budget.BudgetBytes)

+        {

+            return E_OUTOFMEMORY;

+        }

+    }

+

+    D3D12_HEAP_PROPERTIES heapProps = {};

+    heapProps.Type = pAllocDesc->HeapType;

+

+    const D3D12_HEAP_FLAGS heapFlags = pAllocDesc->ExtraHeapFlags;

+

+    ID3D12Resource* res = NULL;

+    HRESULT hr = m_Device4->CreateCommittedResource1(

+        &heapProps, heapFlags, pResourceDesc, InitialResourceState,

+        pOptimizedClearValue, pProtectedSession, IID_PPV_ARGS(&res));

+    if(SUCCEEDED(hr))

+    {

+        if(ppvResource != NULL)

+        {

+            hr = res->QueryInterface(riidResource, ppvResource);

+        }

+        if(SUCCEEDED(hr))

+        {

+            const BOOL wasZeroInitialized = TRUE;

+            Allocation* alloc = m_AllocationObjectAllocator.Allocate(this, resAllocInfo.SizeInBytes, wasZeroInitialized);

+            alloc->InitCommitted(pAllocDesc->HeapType);

+            alloc->SetResource(res, pResourceDesc);

+

+            *ppAllocation = alloc;

+

+            RegisterCommittedAllocation(*ppAllocation, pAllocDesc->HeapType);

+

+            const UINT heapTypeIndex = HeapTypeToIndex(pAllocDesc->HeapType);

+            m_Budget.AddAllocation(heapTypeIndex, resAllocInfo.SizeInBytes);

+            m_Budget.m_BlockBytes[heapTypeIndex] += resAllocInfo.SizeInBytes;

+        }

+        else

+        {

+            res->Release();

+        }

+    }

+    return hr;

+}

+#endif // #ifdef __ID3D12Device4_INTERFACE_DEFINED__

+

 HRESULT AllocatorPimpl::AllocateHeap(

     const ALLOCATION_DESC* pAllocDesc,

     const D3D12_RESOURCE_ALLOCATION_INFO& allocInfo,

@@ -4603,6 +4805,60 @@
     return hr;

 }

 

+#ifdef __ID3D12Device4_INTERFACE_DEFINED__

+HRESULT AllocatorPimpl::AllocateHeap1(

+    const ALLOCATION_DESC* pAllocDesc,

+    const D3D12_RESOURCE_ALLOCATION_INFO& allocInfo,

+    ID3D12ProtectedResourceSession *pProtectedSession,

+    Allocation** ppAllocation)

+{

+    *ppAllocation = nullptr;

+

+    if(m_Device4 == NULL)

+    {

+        return E_NOINTERFACE;

+    }

+

+    if((pAllocDesc->Flags & ALLOCATION_FLAG_NEVER_ALLOCATE) != 0)

+    {

+        return E_OUTOFMEMORY;

+    }

+

+    if((pAllocDesc->Flags & ALLOCATION_FLAG_WITHIN_BUDGET) != 0)

+    {

+        Budget budget = {};

+        GetBudgetForHeapType(budget, pAllocDesc->HeapType);

+        if(budget.UsageBytes + allocInfo.SizeInBytes > budget.BudgetBytes)

+        {

+            return E_OUTOFMEMORY;

+        }

+    }

+

+    D3D12_HEAP_FLAGS heapFlags = pAllocDesc->ExtraHeapFlags;

+

+    D3D12_HEAP_DESC heapDesc = {};

+    heapDesc.SizeInBytes = allocInfo.SizeInBytes;

+    heapDesc.Properties.Type = pAllocDesc->HeapType;

+    heapDesc.Alignment = allocInfo.Alignment;

+    heapDesc.Flags = heapFlags;

+

+    ID3D12Heap* heap = nullptr;

+    HRESULT hr = m_Device4->CreateHeap1(&heapDesc, pProtectedSession, __uuidof(*heap), (void**)&heap);

+    if(SUCCEEDED(hr))

+    {

+        const BOOL wasZeroInitialized = TRUE;

+        (*ppAllocation) = m_AllocationObjectAllocator.Allocate(this, allocInfo.SizeInBytes, wasZeroInitialized);

+        (*ppAllocation)->InitHeap(pAllocDesc->HeapType, heap);

+        RegisterCommittedAllocation(*ppAllocation, pAllocDesc->HeapType);

+

+        const UINT heapTypeIndex = HeapTypeToIndex(pAllocDesc->HeapType);

+        m_Budget.AddAllocation(heapTypeIndex, allocInfo.SizeInBytes);

+        m_Budget.m_BlockBytes[heapTypeIndex] += allocInfo.SizeInBytes;

+    }

+    return hr;

+}

+#endif // #ifdef __ID3D12Device4_INTERFACE_DEFINED__

+

 UINT AllocatorPimpl::CalcDefaultPoolCount() const

 {

     if(SupportsResourceHeapTier2())

@@ -5472,6 +5728,27 @@
     return m_Pimpl->CreateResource(pAllocDesc, pResourceDesc, InitialResourceState, pOptimizedClearValue, ppAllocation, riidResource, ppvResource);

 }

 

+#ifdef __ID3D12Device4_INTERFACE_DEFINED__

+HRESULT Allocator::CreateResource1(

+    const ALLOCATION_DESC* pAllocDesc,

+    const D3D12_RESOURCE_DESC* pResourceDesc,

+    D3D12_RESOURCE_STATES InitialResourceState,

+    const D3D12_CLEAR_VALUE *pOptimizedClearValue,

+    ID3D12ProtectedResourceSession *pProtectedSession,

+    Allocation** ppAllocation,

+    REFIID riidResource,

+    void** ppvResource)

+{

+    if(!pAllocDesc || !pResourceDesc || !ppAllocation)

+    {

+        D3D12MA_ASSERT(0 && "Invalid arguments passed to Allocator::CreateResource1.");

+        return E_INVALIDARG;

+    }

+    D3D12MA_DEBUG_GLOBAL_MUTEX_LOCK

+    return m_Pimpl->CreateResource1(pAllocDesc, pResourceDesc, InitialResourceState, pOptimizedClearValue, pProtectedSession, ppAllocation, riidResource, ppvResource);

+}

+#endif // #ifdef __ID3D12Device4_INTERFACE_DEFINED__

+

 HRESULT Allocator::AllocateMemory(

     const ALLOCATION_DESC* pAllocDesc,

     const D3D12_RESOURCE_ALLOCATION_INFO* pAllocInfo,

@@ -5493,6 +5770,30 @@
     return m_Pimpl->AllocateMemory(pAllocDesc, pAllocInfo, ppAllocation);

 }

 

+#ifdef __ID3D12Device4_INTERFACE_DEFINED__

+HRESULT Allocator::AllocateMemory1(

+    const ALLOCATION_DESC* pAllocDesc,

+    const D3D12_RESOURCE_ALLOCATION_INFO* pAllocInfo,

+    ID3D12ProtectedResourceSession *pProtectedSession,

+    Allocation** ppAllocation)

+{

+    if(!pAllocDesc ||

+        !pAllocInfo ||

+        !ppAllocation ||

+        !(pAllocInfo->Alignment == 0 ||

+            pAllocInfo->Alignment == D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT ||

+            pAllocInfo->Alignment == D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT) ||

+        pAllocInfo->SizeInBytes == 0 ||

+        pAllocInfo->SizeInBytes % (64ull * 1024) != 0)

+    {

+        D3D12MA_ASSERT(0 && "Invalid arguments passed to Allocator::AllocateMemory.");

+        return E_INVALIDARG;

+    }

+    D3D12MA_DEBUG_GLOBAL_MUTEX_LOCK

+    return m_Pimpl->AllocateMemory1(pAllocDesc, pAllocInfo, pProtectedSession, ppAllocation);

+}

+#endif // #ifdef __ID3D12Device4_INTERFACE_DEFINED__

+

 HRESULT Allocator::CreateAliasingResource(

     Allocation* pAllocation,

     UINT64 AllocationLocalOffset,

diff --git a/src/D3D12MemAlloc.h b/src/D3D12MemAlloc.h
index 7ac8cf2..9382948 100644
--- a/src/D3D12MemAlloc.h
+++ b/src/D3D12MemAlloc.h
@@ -1253,6 +1253,25 @@
         REFIID riidResource,

         void** ppvResource);

 

+#ifdef __ID3D12Device4_INTERFACE_DEFINED__

+    /** \brief Similar to Allocator::CreateResource, but supports additional parameter `pProtectedSession`.

+    

+    If `pProtectedSession` is not null, current implementation always creates the resource as committed

+    using `ID3D12Device4::CreateCommittedResource1`.

+

+    To work correctly, `ID3D12Device4` interface must be available in the current system. Otherwise, `E_NOINTERFACE` is returned.

+    */

+    HRESULT CreateResource1(

+        const ALLOCATION_DESC* pAllocDesc,

+        const D3D12_RESOURCE_DESC* pResourceDesc,

+        D3D12_RESOURCE_STATES InitialResourceState,

+        const D3D12_CLEAR_VALUE *pOptimizedClearValue,

+        ID3D12ProtectedResourceSession *pProtectedSession,

+        Allocation** ppAllocation,

+        REFIID riidResource,

+        void** ppvResource);

+#endif // #ifdef __ID3D12Device4_INTERFACE_DEFINED__

+

     /** \brief Allocates memory without creating any resource placed in it.

 

     This function is similar to `ID3D12Device::CreateHeap`, but it may really assign

@@ -1277,6 +1296,21 @@
         const D3D12_RESOURCE_ALLOCATION_INFO* pAllocInfo,

         Allocation** ppAllocation);

 

+#ifdef __ID3D12Device4_INTERFACE_DEFINED__

+    /** \brief Similar to Allocator::AllocateMemory, but supports additional parameter `pProtectedSession`.

+    

+    If `pProtectedSession` is not null, current implementation always creates separate heap

+    using `ID3D12Device4::CreateHeap1`.

+

+    To work correctly, `ID3D12Device4` interface must be available in the current system. Otherwise, `E_NOINTERFACE` is returned.

+    */

+    HRESULT AllocateMemory1(

+        const ALLOCATION_DESC* pAllocDesc,

+        const D3D12_RESOURCE_ALLOCATION_INFO* pAllocInfo,

+        ID3D12ProtectedResourceSession *pProtectedSession,

+        Allocation** ppAllocation);

+#endif // #ifdef __ID3D12Device4_INTERFACE_DEFINED__

+

     /** \brief Creates a new resource in place of an existing allocation. This is useful for memory aliasing.

 

     \param pAllocation Existing allocation indicating the memory where the new resource should be created.

diff --git a/src/Doxyfile b/src/Doxyfile
index 1bd8947..81f5850 100644
--- a/src/Doxyfile
+++ b/src/Doxyfile
@@ -2161,7 +2161,7 @@
 # The default value is: NO.

 # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.

 

-MACRO_EXPANSION        = NO

+MACRO_EXPANSION        = YES

 

 # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then

 # the macro expansion is limited to the macros specified with the PREDEFINED and

@@ -2169,7 +2169,7 @@
 # The default value is: NO.

 # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.

 

-EXPAND_ONLY_PREDEF     = NO

+EXPAND_ONLY_PREDEF     = YES

 

 # If the SEARCH_INCLUDES tag is set to YES, the include files in the

 # INCLUDE_PATH will be searched if a #include is found.

@@ -2201,7 +2201,7 @@
 # recursively expanded use the := operator instead of the = operator.

 # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.

 

-PREDEFINED             =

+PREDEFINED             = __ID3D12Device4_INTERFACE_DEFINED__

 

 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this

 # tag can be used to specify a list of macro names that should be expanded. The

diff --git a/src/Tests.cpp b/src/Tests.cpp
index d37aa28..c075834 100644
--- a/src/Tests.cpp
+++ b/src/Tests.cpp
@@ -1335,6 +1335,44 @@
     }

 }

 

+static void TestDevice4(const TestContext& ctx)

+{

+    wprintf(L"Test ID3D12Device4\n");

+

+    CComPtr<ID3D12Device4> dev4;

+    CHECK_HR(ctx.device->QueryInterface(&dev4));

+

+    D3D12_PROTECTED_RESOURCE_SESSION_DESC sessionDesc = {};

+    CComPtr<ID3D12ProtectedResourceSession> session;

+    CHECK_HR(dev4->CreateProtectedResourceSession(&sessionDesc, IID_PPV_ARGS(&session)));

+

+    // Create a buffer

+

+    D3D12_RESOURCE_DESC resourceDesc;

+    FillResourceDescForBuffer(resourceDesc, 1024);

+

+    D3D12MA::ALLOCATION_DESC allocDesc = {};

+    allocDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT;

+

+    D3D12MA::Allocation* alloc = nullptr;

+    CComPtr<ID3D12Resource> bufRes;

+    CHECK_HR(ctx.allocator->CreateResource1(&allocDesc, &resourceDesc,

+        D3D12_RESOURCE_STATE_COMMON, NULL,

+        session, &alloc, IID_PPV_ARGS(&bufRes)));

+    AllocationUniquePtr bufAllocPtr{alloc};

+

+    // Create a heap

+

+    D3D12_RESOURCE_ALLOCATION_INFO heapAllocInfo = {

+        D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT * 100, // SizeInBytes

+        D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT, // Alignment

+    };

+

+    CHECK_HR(ctx.allocator->AllocateMemory1(&allocDesc, &heapAllocInfo, session, &alloc));

+    AllocationUniquePtr heapAllocPtr{alloc};

+

+}

+

 static void TestGroupVirtual(const TestContext& ctx)

 {

     TestVirtualBlocks(ctx);

@@ -1355,6 +1393,7 @@
     TestTransfer(ctx);

     TestZeroInitialized(ctx);

     TestMultithreading(ctx);

+    TestDevice4(ctx);

 }

 

 void Test(const TestContext& ctx)