Changed the way ProtectedSession is passed. COMPATIBILITY BREAKING!

Using ProtectedSession now requires using custom pools.
Added POOL_DESC::pProtectedSession. Removed Allocator::CreateResource1, AllocateMemory1. Removed parameter pProtectedSession from Allocator::CreateCommittedResource2.
Code mostly by @medranSolus.
diff --git a/include/D3D12MemAlloc.h b/include/D3D12MemAlloc.h
index a85c1f5..c8a7988 100644
--- a/include/D3D12MemAlloc.h
+++ b/include/D3D12MemAlloc.h
@@ -126,6 +126,9 @@
     #define D3D12MA_API

 #endif

 

+// Forward declaration if ID3D12ProtectedResourceSession is not defined inside the headers (older SDK, pre ID3D12Device4)

+struct ID3D12ProtectedResourceSession;

+

 namespace D3D12MA

 {

 class D3D12MA_API IUnknownImpl : public IUnknown

@@ -468,6 +471,12 @@
     Leave 0 (default) not to impose any additional alignment. If not 0, it must be a power of two.

     */

     UINT64 MinAllocationAlignment;

+    /** \brief Additional parameter allowing pool to create resources with passed protected session.

+    

+    If not null then all the heaps and committed resources will be created with this parameter.

+    Valid only if ID3D12Device4 interface is present in current Windows SDK!

+    */

+    ID3D12ProtectedResourceSession* pProtectedSession;

 };

 

 /** \brief Custom memory pool

@@ -725,27 +734,8 @@
         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__

-

 #ifdef __ID3D12Device8_INTERFACE_DEFINED__

-    /** \brief Similar to Allocator::CreateResource1, but supports new structure `D3D12_RESOURCE_DESC1`.

+    /** \brief Similar to Allocator::CreateResource, but supports new structure `D3D12_RESOURCE_DESC1`.

     

     It internally uses `ID3D12Device8::CreateCommittedResource2` or `ID3D12Device8::CreatePlacedResource1`.

 

@@ -756,7 +746,6 @@
         const D3D12_RESOURCE_DESC1* pResourceDesc,

         D3D12_RESOURCE_STATES InitialResourceState,

         const D3D12_CLEAR_VALUE *pOptimizedClearValue,

-        ID3D12ProtectedResourceSession *pProtectedSession,

         Allocation** ppAllocation,

         REFIID riidResource,

         void** ppvResource);

@@ -786,21 +775,6 @@
         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/Common.h b/src/Common.h
index 0f6d356..f2c42aa 100644
--- a/src/Common.h
+++ b/src/Common.h
@@ -66,6 +66,10 @@
         throw std::runtime_error(__FILE__ "(" LINE_STRING "): FAILED( " #expr " )"); \

     } } while(false)

 

+const uint32_t VENDOR_ID_AMD = 0x1002;

+const uint32_t VENDOR_ID_NVIDIA = 0x10DE;

+const uint32_t VENDOR_ID_INTEL = 0x8086;

+

 template <typename T>

 inline constexpr T CeilDiv(T x, T y)

 {

diff --git a/src/D3D12MemAlloc.cpp b/src/D3D12MemAlloc.cpp
index 7655e72..e0d52ae 100644
--- a/src/D3D12MemAlloc.cpp
+++ b/src/D3D12MemAlloc.cpp
@@ -2731,7 +2731,7 @@
     const UINT64 m_Size;

     const UINT m_Id;

 

-    HRESULT Init();

+    HRESULT Init(ID3D12ProtectedResourceSession* pProtectedSession);

 

 private:

     ID3D12Heap* m_Heap = NULL;

@@ -2760,7 +2760,7 @@
         UINT64 size,

         UINT id);

     virtual ~NormalBlock();

-    HRESULT Init();

+    HRESULT Init(ID3D12ProtectedResourceSession* pProtectedSession);

 

     BlockVector* GetBlockVector() const { return m_BlockVector; }

 

@@ -2852,7 +2852,8 @@
         size_t minBlockCount,

         size_t maxBlockCount,

         bool explicitBlockSize,

-        UINT64 minAllocationAlignment);

+        UINT64 minAllocationAlignment,

+        ID3D12ProtectedResourceSession* pProtectedSession);

     ~BlockVector();

 

     HRESULT CreateMinBlocks();

@@ -2891,7 +2892,6 @@
         const D3D12_RESOURCE_DESC1& resourceDesc,

         D3D12_RESOURCE_STATES InitialResourceState,

         const D3D12_CLEAR_VALUE *pOptimizedClearValue,

-        ID3D12ProtectedResourceSession *pProtectedSession,

         Allocation** ppAllocation,

         REFIID riidResource,

         void** ppvResource);

@@ -2911,6 +2911,7 @@
     const size_t m_MaxBlockCount;

     const bool m_ExplicitBlockSize;

     const UINT64 m_MinAllocationAlignment;

+    ID3D12ProtectedResourceSession* const m_ProtectedSession;

     /* There can be at most one allocation that is completely empty - a

     hysteresis to avoid pessimistic case of alternating creation and destruction

     of a VkDeviceMemory. */

@@ -2943,7 +2944,9 @@
         ALLOCATION_FLAGS allocFlags,

         Allocation** pAllocation);

 

-    HRESULT CreateBlock(UINT64 blockSize, size_t* pNewBlockIndex);

+    HRESULT CreateBlock(

+        UINT64 blockSize,

+        size_t* pNewBlockIndex);

 };

 

 ////////////////////////////////////////////////////////////////////////////////

@@ -3050,6 +3053,7 @@
     CommittedAllocationList* m_List = NULL;

     D3D12_HEAP_PROPERTIES m_HeapProperties = {};

     D3D12_HEAP_FLAGS m_HeapFlags = D3D12_HEAP_FLAG_NONE;

+    ID3D12ProtectedResourceSession* m_ProtectedSession = NULL;

 

     bool IsValid() const { return m_List != NULL; }

 };

@@ -3090,25 +3094,12 @@
         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__

-

 #ifdef __ID3D12Device8_INTERFACE_DEFINED__

     HRESULT CreateResource2(

         const ALLOCATION_DESC* pAllocDesc,

         const D3D12_RESOURCE_DESC1* pResourceDesc,

         D3D12_RESOURCE_STATES InitialResourceState,

         const D3D12_CLEAR_VALUE *pOptimizedClearValue,

-        ID3D12ProtectedResourceSession *pProtectedSession,

         Allocation** ppAllocation,

         REFIID riidResource,

         void** ppvResource);

@@ -3119,14 +3110,6 @@
         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,

@@ -3209,23 +3192,12 @@
         D3D12_RESOURCE_STATES InitialResourceState, const D3D12_CLEAR_VALUE *pOptimizedClearValue,

         Allocation** ppAllocation, REFIID riidResource, void** ppvResource);

 

-#ifdef __ID3D12Device4_INTERFACE_DEFINED__

-    HRESULT AllocateCommittedResource1(

-        const CommittedAllocationParameters& committedAllocParams,

-        UINT64 resourceSize, bool withinBudget,

-        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__

-

 #ifdef __ID3D12Device8_INTERFACE_DEFINED__

     HRESULT AllocateCommittedResource2(

         const CommittedAllocationParameters& committedAllocParams,

         UINT64 resourceSize, bool withinBudget,

         const D3D12_RESOURCE_DESC1* pResourceDesc,

         D3D12_RESOURCE_STATES InitialResourceState, const D3D12_CLEAR_VALUE *pOptimizedClearValue,

-        ID3D12ProtectedResourceSession *pProtectedSession,

         Allocation** ppAllocation, REFIID riidResource, void** ppvResource);

 #endif // #ifdef __ID3D12Device8_INTERFACE_DEFINED__

 

@@ -3236,14 +3208,6 @@
         const D3D12_RESOURCE_ALLOCATION_INFO& allocInfo, bool withinBudget,

         Allocation** ppAllocation);

 

-#ifdef __ID3D12Device4_INTERFACE_DEFINED__

-    HRESULT AllocateHeap1(

-        const CommittedAllocationParameters& committedAllocParams,

-        const D3D12_RESOURCE_ALLOCATION_INFO& allocInfo, bool withinBudget,

-        ID3D12ProtectedResourceSession *pProtectedSession,

-        Allocation** ppAllocation);

-#endif // #ifdef __ID3D12Device4_INTERFACE_DEFINED__

-

     template<typename D3D12_RESOURCE_DESC_T>

     HRESULT CalcAllocationParams(const ALLOCATION_DESC& allocDesc, UINT64 allocSize,

         const D3D12_RESOURCE_DESC_T* resDesc, // Optional

@@ -3924,14 +3888,14 @@
     }

 }

 

-HRESULT NormalBlock::Init()

+HRESULT NormalBlock::Init(ID3D12ProtectedResourceSession* pProtectedSession)

 {

-    HRESULT hr = MemoryBlock::Init();

+    HRESULT hr = MemoryBlock::Init(pProtectedSession);

     if(FAILED(hr))

     {

         return hr;

     }

-    

+

     m_pMetadata = D3D12MA_NEW(m_Allocator->GetAllocs(), BlockMetadata_Generic)(&m_Allocator->GetAllocs(), false);

     m_pMetadata->Init(m_Size);

 

@@ -3973,7 +3937,7 @@
     }

 }

 

-HRESULT MemoryBlock::Init()

+HRESULT MemoryBlock::Init(ID3D12ProtectedResourceSession* pProtectedSession)

 {

     D3D12MA_ASSERT(m_Heap == NULL && m_Size > 0);

 

@@ -3983,7 +3947,12 @@
     heapDesc.Alignment = HeapFlagsToAlignment(m_HeapFlags);

     heapDesc.Flags = m_HeapFlags;

 

+#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

     if(SUCCEEDED(hr))

     {

         m_Allocator->m_Budget.m_BlockBytes[HeapTypeToIndex(m_HeapProps.Type)] += m_Size;

@@ -4073,7 +4042,8 @@
     size_t minBlockCount,

     size_t maxBlockCount,

     bool explicitBlockSize,

-    UINT64 minAllocationAlignment) :

+    UINT64 minAllocationAlignment,

+    ID3D12ProtectedResourceSession* pProtectedSession) :

     m_hAllocator(hAllocator),

     m_HeapProps(heapProps),

     m_HeapFlags(heapFlags),

@@ -4082,6 +4052,7 @@
     m_MaxBlockCount(maxBlockCount),

     m_ExplicitBlockSize(explicitBlockSize),

     m_MinAllocationAlignment(minAllocationAlignment),

+    m_ProtectedSession(pProtectedSession),

     m_HasEmptyBlock(false),

     m_Blocks(hAllocator->GetAllocs()),

     m_NextBlockId(0)

@@ -4393,13 +4364,10 @@
     const D3D12_RESOURCE_DESC1& resourceDesc,

     D3D12_RESOURCE_STATES InitialResourceState,

     const D3D12_CLEAR_VALUE *pOptimizedClearValue,

-    ID3D12ProtectedResourceSession *pProtectedSession,

     Allocation** ppAllocation,

     REFIID riidResource,

     void** ppvResource)

 {

-    D3D12MA_ASSERT(pProtectedSession == NULL && "Should never get here. pProtectedSession != NULL currently requires committed resources.");

-

     ID3D12Device8* const device8 = m_hAllocator->GetDevice8();

     if(device8 == NULL)

     {

@@ -4523,7 +4491,9 @@
     return E_OUTOFMEMORY;

 }

 

-HRESULT BlockVector::CreateBlock(UINT64 blockSize, size_t* pNewBlockIndex)

+HRESULT BlockVector::CreateBlock(

+    UINT64 blockSize,

+    size_t* pNewBlockIndex)

 {

     NormalBlock* const pBlock = D3D12MA_NEW(m_hAllocator->GetAllocs(), NormalBlock)(

         m_hAllocator,

@@ -4532,7 +4502,7 @@
         m_HeapFlags,

         blockSize,

         m_NextBlockId++);

-    HRESULT hr = pBlock->Init();

+    HRESULT hr = pBlock->Init(m_ProtectedSession);

     if(FAILED(hr))

     {

         D3D12MA_DELETE(m_hAllocator->GetAllocs(), pBlock);

@@ -4614,17 +4584,19 @@
 {

     const bool explicitBlockSize = desc.BlockSize != 0;

     const UINT64 preferredBlockSize = explicitBlockSize ? desc.BlockSize : D3D12MA_DEFAULT_BLOCK_SIZE;

-

-    D3D12_HEAP_FLAGS heapFlags = desc.HeapFlags;

-

     UINT maxBlockCount = desc.MaxBlockCount != 0 ? desc.MaxBlockCount : UINT_MAX;

 

+#ifndef __ID3D12Device4_INTERFACE_DEFINED__

+    D3D12MA_ASSERT(m_Desc.pProtectedSession == NULL);

+#endif

+

     m_BlockVector = D3D12MA_NEW(allocator->GetAllocs(), BlockVector)(

-        allocator, desc.HeapProperties, heapFlags,

+        allocator, desc.HeapProperties, desc.HeapFlags,

         preferredBlockSize,

         desc.MinBlockCount, maxBlockCount,

         explicitBlockSize,

-        D3D12MA_MAX(desc.MinAllocationAlignment, (UINT64)D3D12MA_DEBUG_ALIGNMENT));

+        D3D12MA_MAX(desc.MinAllocationAlignment, (UINT64)D3D12MA_DEBUG_ALIGNMENT),

+        desc.pProtectedSession);

 }

 

 HRESULT PoolPimpl::Init()

@@ -4819,7 +4791,8 @@
             0, // minBlockCount

             SIZE_MAX, // maxBlockCount

             false, // explicitBlockSize

-            D3D12MA_DEBUG_ALIGNMENT); // minAllocationAlignment

+            D3D12MA_DEBUG_ALIGNMENT, // minAllocationAlignment

+            NULL); // pProtectedSession

         // No need to call m_pBlockVectors[i]->CreateMinBlocks here, becase minBlockCount is 0.

     }

 

@@ -4940,64 +4913,12 @@
     return hr;

 }

 

-#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;

-    }

-

-    D3D12_RESOURCE_DESC finalResourceDesc = *pResourceDesc;

-    D3D12_RESOURCE_ALLOCATION_INFO resAllocInfo = GetResourceAllocationInfo(finalResourceDesc);

-    D3D12MA_ASSERT(IsPow2(resAllocInfo.Alignment));

-    D3D12MA_ASSERT(resAllocInfo.SizeInBytes > 0);

-

-    BlockVector* blockVector = NULL;

-    CommittedAllocationParameters committedAllocationParams = {};

-    bool preferCommitted = false;

-    HRESULT hr = CalcAllocationParams<D3D12_RESOURCE_DESC>(*pAllocDesc, resAllocInfo.SizeInBytes,

-        pResourceDesc,

-        blockVector, committedAllocationParams, preferCommitted);

-    if(FAILED(hr))

-        return hr;

-

-    const bool withinBudget = (pAllocDesc->Flags & ALLOCATION_FLAG_WITHIN_BUDGET) != 0;

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

-    if(committedAllocationParams.IsValid())

-    {

-        return AllocateCommittedResource1(committedAllocationParams,

-            resAllocInfo.SizeInBytes, withinBudget, &finalResourceDesc,

-            InitialResourceState, pOptimizedClearValue,

-            pProtectedSession, ppAllocation, riidResource, ppvResource);

-    }

-    else

-        return E_INVALIDARG;

-}

-#endif // #ifdef __ID3D12Device4_INTERFACE_DEFINED__

-

 #ifdef __ID3D12Device8_INTERFACE_DEFINED__

 HRESULT AllocatorPimpl::CreateResource2(

     const ALLOCATION_DESC* pAllocDesc,

     const D3D12_RESOURCE_DESC1* pResourceDesc,

     D3D12_RESOURCE_STATES InitialResourceState,

     const D3D12_CLEAR_VALUE *pOptimizedClearValue,

-    ID3D12ProtectedResourceSession *pProtectedSession,

     Allocation** ppAllocation,

     REFIID riidResource,

     void** ppvResource)

@@ -5028,16 +4949,13 @@
     if(FAILED(hr))

         return hr;

     

-    if(pProtectedSession != NULL)

-        blockVector = NULL; // Must be committed allocation.

-

     const bool withinBudget = (pAllocDesc->Flags & ALLOCATION_FLAG_WITHIN_BUDGET) != 0;

     hr = E_INVALIDARG;

     if(committedAllocationParams.IsValid() && preferCommitted)

     {

         hr = AllocateCommittedResource2(committedAllocationParams,

             resAllocInfo.SizeInBytes, withinBudget,&finalResourceDesc,

-            InitialResourceState, pOptimizedClearValue, pProtectedSession,

+            InitialResourceState, pOptimizedClearValue,

             ppAllocation, riidResource, ppvResource);

         if(SUCCEEDED(hr))

             return hr;

@@ -5046,7 +4964,7 @@
     {

         hr = blockVector->CreateResource2(resAllocInfo.SizeInBytes, resAllocInfo.Alignment,

             *pAllocDesc, finalResourceDesc,

-            InitialResourceState, pOptimizedClearValue, pProtectedSession,

+            InitialResourceState, pOptimizedClearValue,

             ppAllocation, riidResource, ppvResource);

         if(SUCCEEDED(hr))

             return hr;

@@ -5055,7 +4973,7 @@
     {

         hr = AllocateCommittedResource2(committedAllocationParams,

             resAllocInfo.SizeInBytes, withinBudget,&finalResourceDesc,

-            InitialResourceState, pOptimizedClearValue, pProtectedSession,

+            InitialResourceState, pOptimizedClearValue,

             ppAllocation, riidResource, ppvResource);

         if(SUCCEEDED(hr))

             return hr;

@@ -5104,42 +5022,6 @@
     return hr;

 }

 

-#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;

-

-    BlockVector* blockVector = NULL;

-    CommittedAllocationParameters committedAllocationParams = {};

-    bool preferCommitted = false;

-    HRESULT hr = CalcAllocationParams<D3D12_RESOURCE_DESC>(*pAllocDesc, pAllocInfo->SizeInBytes,

-        NULL, // pResDesc

-        blockVector, committedAllocationParams, preferCommitted);

-    if(FAILED(hr))

-        return hr;

-

-    const bool withinBudget = (pAllocDesc->Flags & ALLOCATION_FLAG_WITHIN_BUDGET) != 0;

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

-    if(committedAllocationParams.IsValid())

-    {

-        return AllocateHeap1(committedAllocationParams,

-            *pAllocInfo, withinBudget, pProtectedSession, ppAllocation);

-    }

-    else

-        return E_INVALIDARG;

-}

-#endif // #ifdef __ID3D12Device4_INTERFACE_DEFINED__

-

 HRESULT AllocatorPimpl::CreateAliasingResource(

     Allocation* pAllocation,

     UINT64 AllocationLocalOffset,

@@ -5201,67 +5083,33 @@
     }

 

     ID3D12Resource* res = NULL;

-    HRESULT hr = m_Device->CreateCommittedResource(

-        &committedAllocParams.m_HeapProperties,

-        committedAllocParams.m_HeapFlags & ~RESOURCE_CLASS_HEAP_FLAGS, // D3D12 ERROR: ID3D12Device::CreateCommittedResource: When creating a committed resource, D3D12_HEAP_FLAGS must not have either D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES, D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES, nor D3D12_HEAP_FLAG_DENY_BUFFERS set. These flags will be set automatically to correspond with the committed resource type. [ STATE_CREATION ERROR #640: CREATERESOURCEANDHEAP_INVALIDHEAPMISCFLAGS]

-        pResourceDesc, InitialResourceState,

-        pOptimizedClearValue, D3D12MA_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, resourceSize, wasZeroInitialized);

-            alloc->InitCommitted(committedAllocParams.m_List);

-            alloc->SetResource(res, pResourceDesc);

-

-            *ppAllocation = alloc;

-

-            committedAllocParams.m_List->Register(alloc);

-

-            const UINT heapTypeIndex = HeapTypeToIndex(committedAllocParams.m_HeapProperties.Type);

-            m_Budget.AddCommittedAllocation(heapTypeIndex, resourceSize);

-        }

-        else

-        {

-            res->Release();

-        }

-    }

-    return hr;

-}

-

+    /* D3D12 ERROR:

+     * ID3D12Device::CreateCommittedResource: 

+     * When creating a committed resource, D3D12_HEAP_FLAGS must not have either

+     *      D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES,

+     *      D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES,

+     *      nor D3D12_HEAP_FLAG_DENY_BUFFERS set.

+     * These flags will be set automatically to correspond with the committed resource type.

+     * 

+     * [ STATE_CREATION ERROR #640: CREATERESOURCEANDHEAP_INVALIDHEAPMISCFLAGS]

+    */

 #ifdef __ID3D12Device4_INTERFACE_DEFINED__

-HRESULT AllocatorPimpl::AllocateCommittedResource1(

-    const CommittedAllocationParameters& committedAllocParams,

-    UINT64 resourceSize, bool withinBudget,

-    const D3D12_RESOURCE_DESC* pResourceDesc,

-    D3D12_RESOURCE_STATES InitialResourceState, const D3D12_CLEAR_VALUE *pOptimizedClearValue,

-    ID3D12ProtectedResourceSession *pProtectedSession,

-    Allocation** ppAllocation, REFIID riidResource, void** ppvResource)

-{

-    D3D12MA_ASSERT(committedAllocParams.IsValid());

-

     if(m_Device4 == NULL)

-    {

         return E_NOINTERFACE;

-    }

 

-    if(withinBudget &&

-        !NewAllocationWithinBudget(committedAllocParams.m_HeapProperties.Type, resourceSize))

-    {

-        return E_OUTOFMEMORY;

-    }

-

-    ID3D12Resource* res = NULL;

     HRESULT hr = m_Device4->CreateCommittedResource1(

         &committedAllocParams.m_HeapProperties,

-        committedAllocParams.m_HeapFlags & ~RESOURCE_CLASS_HEAP_FLAGS, // D3D12 ERROR: ID3D12Device::CreateCommittedResource: When creating a committed resource, D3D12_HEAP_FLAGS must not have either D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES, D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES, nor D3D12_HEAP_FLAG_DENY_BUFFERS set. These flags will be set automatically to correspond with the committed resource type. [ STATE_CREATION ERROR #640: CREATERESOURCEANDHEAP_INVALIDHEAPMISCFLAGS]

+        committedAllocParams.m_HeapFlags & ~RESOURCE_CLASS_HEAP_FLAGS,

         pResourceDesc, InitialResourceState,

-        pOptimizedClearValue, pProtectedSession, D3D12MA_IID_PPV_ARGS(&res));

+        pOptimizedClearValue, committedAllocParams.m_ProtectedSession, D3D12MA_IID_PPV_ARGS(&res));

+#else

+    D3D12MA_ASSERT(committedAllocParams.m_ProtectedSession == NULL);

+    HRESULT hr = m_Device->CreateCommittedResource(

+        &committedAllocParams.m_HeapProperties,

+        committedAllocParams.m_HeapFlags & ~RESOURCE_CLASS_HEAP_FLAGS, 

+        pResourceDesc, InitialResourceState,

+        pOptimizedClearValue, D3D12MA_IID_PPV_ARGS(&res));

+#endif

     if(SUCCEEDED(hr))

     {

         if(ppvResource != NULL)

@@ -5289,7 +5137,6 @@
     }

     return hr;

 }

-#endif // #ifdef __ID3D12Device4_INTERFACE_DEFINED__

 

 #ifdef __ID3D12Device8_INTERFACE_DEFINED__

 HRESULT AllocatorPimpl::AllocateCommittedResource2(

@@ -5297,7 +5144,6 @@
     UINT64 resourceSize, bool withinBudget,

     const D3D12_RESOURCE_DESC1* pResourceDesc,

     D3D12_RESOURCE_STATES InitialResourceState, const D3D12_CLEAR_VALUE *pOptimizedClearValue,

-    ID3D12ProtectedResourceSession *pProtectedSession,

     Allocation** ppAllocation, REFIID riidResource, void** ppvResource)

 {

     D3D12MA_ASSERT(committedAllocParams.IsValid());

@@ -5318,7 +5164,7 @@
         &committedAllocParams.m_HeapProperties,

         committedAllocParams.m_HeapFlags & ~RESOURCE_CLASS_HEAP_FLAGS, // D3D12 ERROR: ID3D12Device::CreateCommittedResource: When creating a committed resource, D3D12_HEAP_FLAGS must not have either D3D12_HEAP_FLAG_DENY_NON_RT_DS_TEXTURES, D3D12_HEAP_FLAG_DENY_RT_DS_TEXTURES, nor D3D12_HEAP_FLAG_DENY_BUFFERS set. These flags will be set automatically to correspond with the committed resource type. [ STATE_CREATION ERROR #640: CREATERESOURCEANDHEAP_INVALIDHEAPMISCFLAGS]

         pResourceDesc, InitialResourceState,

-        pOptimizedClearValue, pProtectedSession, D3D12MA_IID_PPV_ARGS(&res));

+        pOptimizedClearValue, committedAllocParams.m_ProtectedSession, D3D12MA_IID_PPV_ARGS(&res));

     if(SUCCEEDED(hr))

     {

         if(ppvResource != NULL)

@@ -5370,50 +5216,15 @@
     heapDesc.Flags = committedAllocParams.m_HeapFlags;

 

     ID3D12Heap* heap = nullptr;

-    HRESULT hr = m_Device->CreateHeap(&heapDesc, D3D12MA_IID_PPV_ARGS(&heap));

-    if(SUCCEEDED(hr))

-    {

-        const BOOL wasZeroInitialized = TRUE;

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

-        (*ppAllocation)->InitHeap(committedAllocParams.m_List, heap);

-        committedAllocParams.m_List->Register(*ppAllocation);

-

-        const UINT heapTypeIndex = HeapTypeToIndex(committedAllocParams.m_HeapProperties.Type);

-        m_Budget.AddCommittedAllocation(heapTypeIndex, allocInfo.SizeInBytes);

-    }

-    return hr;

-}

-

 #ifdef __ID3D12Device4_INTERFACE_DEFINED__

-HRESULT AllocatorPimpl::AllocateHeap1(

-    const CommittedAllocationParameters& committedAllocParams,

-    const D3D12_RESOURCE_ALLOCATION_INFO& allocInfo, bool withinBudget,

-    ID3D12ProtectedResourceSession *pProtectedSession,

-    Allocation** ppAllocation)

-{

-    D3D12MA_ASSERT(committedAllocParams.IsValid());

-

-    *ppAllocation = nullptr;

-

     if(m_Device4 == NULL)

-    {

         return E_NOINTERFACE;

-    }

 

-    if(withinBudget &&

-        !NewAllocationWithinBudget(committedAllocParams.m_HeapProperties.Type, allocInfo.SizeInBytes))

-    {

-        return E_OUTOFMEMORY;

-    }

-

-    D3D12_HEAP_DESC heapDesc = {};

-    heapDesc.SizeInBytes = allocInfo.SizeInBytes;

-    heapDesc.Properties = committedAllocParams.m_HeapProperties;

-    heapDesc.Alignment = allocInfo.Alignment;

-    heapDesc.Flags = committedAllocParams.m_HeapFlags;

-

-    ID3D12Heap* heap = nullptr;

-    HRESULT hr = m_Device4->CreateHeap1(&heapDesc, pProtectedSession, D3D12MA_IID_PPV_ARGS(&heap));

+    HRESULT hr = m_Device4->CreateHeap1(&heapDesc, committedAllocParams.m_ProtectedSession, D3D12MA_IID_PPV_ARGS(&heap));

+#else

+    D3D12MA_ASSERT(committedAllocParams.m_ProtectedSession == NULL);

+    HRESULT hr = m_Device->CreateHeap(&heapDesc, D3D12MA_IID_PPV_ARGS(&heap));

+#endif

     if(SUCCEEDED(hr))

     {

         const BOOL wasZeroInitialized = TRUE;

@@ -5426,7 +5237,6 @@
     }

     return hr;

 }

-#endif // #ifdef __ID3D12Device4_INTERFACE_DEFINED__

 

 template<typename D3D12_RESOURCE_DESC_T>

 HRESULT AllocatorPimpl::CalcAllocationParams(const ALLOCATION_DESC& allocDesc, UINT64 allocSize,

@@ -5443,6 +5253,7 @@
 

         outBlockVector = pool->GetBlockVector();

 

+        outCommittedAllocationParams.m_ProtectedSession = pool->GetDesc().pProtectedSession;

         outCommittedAllocationParams.m_HeapProperties = pool->GetDesc().HeapProperties;

         outCommittedAllocationParams.m_HeapFlags = pool->GetDesc().HeapFlags;

         outCommittedAllocationParams.m_List = pool->GetCommittedAllocationList();

@@ -6379,34 +6190,12 @@
     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__

-

 #ifdef __ID3D12Device8_INTERFACE_DEFINED__

 HRESULT Allocator::CreateResource2(

     const ALLOCATION_DESC* pAllocDesc,

     const D3D12_RESOURCE_DESC1* pResourceDesc,

     D3D12_RESOURCE_STATES InitialResourceState,

     const D3D12_CLEAR_VALUE *pOptimizedClearValue,

-    ID3D12ProtectedResourceSession *pProtectedSession,

     Allocation** ppAllocation,

     REFIID riidResource,

     void** ppvResource)

@@ -6417,7 +6206,7 @@
         return E_INVALIDARG;

     }

     D3D12MA_DEBUG_GLOBAL_MUTEX_LOCK

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

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

 }

 #endif // #ifdef __ID3D12Device8_INTERFACE_DEFINED__

 

@@ -6450,23 +6239,6 @@
     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(!ValidateAllocateMemoryParameters(pAllocDesc, pAllocInfo, ppAllocation))

-    {

-        D3D12MA_ASSERT(0 && "Invalid arguments passed to Allocator::AllocateMemory1.");

-        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/D3D12Sample.cpp b/src/D3D12Sample.cpp
index 699d5dc..f9dc855 100644
--- a/src/D3D12Sample.cpp
+++ b/src/D3D12Sample.cpp
@@ -90,6 +90,7 @@
 

 static DXGIUsage* g_DXGIUsage;

 static ComPtr<ID3D12Device> g_Device;

+DXGI_ADAPTER_DESC1 g_AdapterDesc;

 static ComPtr<D3D12MA::Allocator> g_Allocator;

 

 static ComPtr<IDXGISwapChain3> g_SwapChain; // swapchain used to switch between render targets

@@ -513,10 +514,6 @@
     return adapter;

 }

 

-static const uint32_t VENDOR_ID_AMD = 0x1002;

-static const uint32_t VENDOR_ID_NVIDIA = 0x10DE;

-static const uint32_t VENDOR_ID_INTEL = 0x8086;

-

 static const wchar_t* VendorIDToStr(uint32_t vendorID)

 {

     switch(vendorID)

@@ -566,17 +563,15 @@
 

 static void PrintAdapterInformation(IDXGIAdapter1* adapter)

 {

-    DXGI_ADAPTER_DESC1 adapterDesc = {};

-    adapter->GetDesc1(&adapterDesc);

     wprintf(L"DXGI_ADAPTER_DESC1:\n");

-    wprintf(L"    Description = %s\n", adapterDesc.Description);

-    wprintf(L"    VendorId = 0x%X (%s)\n", adapterDesc.VendorId, VendorIDToStr(adapterDesc.VendorId));

-    wprintf(L"    DeviceId = 0x%X\n", adapterDesc.DeviceId);

-    wprintf(L"    SubSysId = 0x%X\n", adapterDesc.SubSysId);

-    wprintf(L"    Revision = 0x%X\n", adapterDesc.Revision);

-    wprintf(L"    DedicatedVideoMemory = %zu B (%s)\n", adapterDesc.DedicatedVideoMemory, SizeToStr(adapterDesc.DedicatedVideoMemory).c_str());

-    wprintf(L"    DedicatedSystemMemory = %zu B (%s)\n", adapterDesc.DedicatedSystemMemory, SizeToStr(adapterDesc.DedicatedSystemMemory).c_str());

-    wprintf(L"    SharedSystemMemory = %zu B (%s)\n", adapterDesc.SharedSystemMemory, SizeToStr(adapterDesc.SharedSystemMemory).c_str());

+    wprintf(L"    Description = %s\n", g_AdapterDesc.Description);

+    wprintf(L"    VendorId = 0x%X (%s)\n", g_AdapterDesc.VendorId, VendorIDToStr(g_AdapterDesc.VendorId));

+    wprintf(L"    DeviceId = 0x%X\n", g_AdapterDesc.DeviceId);

+    wprintf(L"    SubSysId = 0x%X\n", g_AdapterDesc.SubSysId);

+    wprintf(L"    Revision = 0x%X\n", g_AdapterDesc.Revision);

+    wprintf(L"    DedicatedVideoMemory = %zu B (%s)\n", g_AdapterDesc.DedicatedVideoMemory, SizeToStr(g_AdapterDesc.DedicatedVideoMemory).c_str());

+    wprintf(L"    DedicatedSystemMemory = %zu B (%s)\n", g_AdapterDesc.DedicatedSystemMemory, SizeToStr(g_AdapterDesc.DedicatedSystemMemory).c_str());

+    wprintf(L"    SharedSystemMemory = %zu B (%s)\n", g_AdapterDesc.SharedSystemMemory, SizeToStr(g_AdapterDesc.SharedSystemMemory).c_str());

 

     const D3D12_FEATURE_DATA_D3D12_OPTIONS& options = g_Allocator->GetD3D12Options();

     wprintf(L"D3D12_FEATURE_DATA_D3D12_OPTIONS:\n");

@@ -630,6 +625,8 @@
     ComPtr<IDXGIAdapter1> adapter = g_DXGIUsage->CreateAdapter(g_CommandLineParameters.m_GPUSelection);

     CHECK_BOOL(adapter);

 

+    CHECK_HR(adapter->GetDesc1(&g_AdapterDesc));

+

     // Must be done before D3D12 device is created.

     if(ENABLE_DEBUG_LAYER)

     {

diff --git a/src/Tests.cpp b/src/Tests.cpp
index 8b011cc..b373d6e 100644
--- a/src/Tests.cpp
+++ b/src/Tests.cpp
@@ -25,6 +25,7 @@
 #include <thread>

 

 extern ID3D12GraphicsCommandList* BeginCommandList();

+extern DXGI_ADAPTER_DESC1 g_AdapterDesc;

 extern void EndCommandList(ID3D12GraphicsCommandList* cmdList);

 

 static constexpr UINT64 MEGABYTE = 1024 * 1024;

@@ -1613,6 +1614,7 @@
     return support.Support > D3D12_PROTECTED_RESOURCE_SESSION_SUPPORT_FLAG_NONE;

 }

 

+#ifdef __ID3D12Device4_INTERFACE_DEFINED__

 static void TestDevice4(const TestContext& ctx)

 {

     wprintf(L"Test ID3D12Device4\n");

@@ -1641,32 +1643,54 @@
         return;

     }

 

-    // Create a buffer

+    D3D12MA::POOL_DESC poolDesc = {};

+    poolDesc.HeapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;

+    poolDesc.pProtectedSession = session.Get();

+    poolDesc.MinAllocationAlignment = 0;

+    poolDesc.HeapFlags = D3D12_HEAP_FLAG_ALLOW_ONLY_BUFFERS;

+

+    ComPtr<D3D12MA::Pool> pool;

+    hr = ctx.allocator->CreatePool(&poolDesc, &pool);

+    if(FAILED(hr))

+    {

+        wprintf(L"Failed to create custom pool.\n");

+        return;

+    }

 

     D3D12_RESOURCE_DESC resourceDesc;

     FillResourceDescForBuffer(resourceDesc, 1024);

 

-    D3D12MA::ALLOCATION_DESC allocDesc = {};

-    allocDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT;

+    for(UINT testIndex = 0; testIndex < 2; ++testIndex)

+    {

+        // Create a buffer

+        D3D12MA::ALLOCATION_DESC allocDesc = {};

+        allocDesc.CustomPool = pool.Get();

+        if(testIndex == 0)

+            allocDesc.Flags = D3D12MA::ALLOCATION_FLAG_COMMITTED;

+        ComPtr<D3D12MA::Allocation> bufAlloc;

+        ComPtr<ID3D12Resource> bufRes;

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

+            D3D12_RESOURCE_STATE_COMMON, NULL,

+            &bufAlloc, IID_PPV_ARGS(&bufRes)));

+        CHECK_BOOL(bufAlloc && bufAlloc->GetResource() == bufRes.Get());

+        // Make sure it's (not) committed.

+        CHECK_BOOL((bufAlloc->GetHeap() == NULL) == (testIndex == 0));

 

-    ComPtr<D3D12MA::Allocation> bufAlloc;

-    ComPtr<ID3D12Resource> bufRes;

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

-        D3D12_RESOURCE_STATE_COMMON, NULL,

-        session.Get(), &bufAlloc, IID_PPV_ARGS(&bufRes)));

-

-    // Create a heap

-    // Temporarily commented out as it caues BSOD on RTX2080Ti driver 461.40.

-#if 0

-    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};

-#endif

+        // Allocate memory/heap

+        // Temporarily disabled on NVIDIA as it causes BSOD on RTX2080Ti driver 461.40.

+        if(g_AdapterDesc.VendorId != VENDOR_ID_NVIDIA)

+        {

+            D3D12_RESOURCE_ALLOCATION_INFO heapAllocInfo = {

+                D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT * 2, // SizeInBytes

+                D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT, // Alignment

+            };

+            ComPtr<D3D12MA::Allocation> memAlloc;

+            CHECK_HR(ctx.allocator->AllocateMemory(&allocDesc, &heapAllocInfo, &memAlloc));

+            CHECK_BOOL(memAlloc->GetHeap());

+        }

+    }

 }

+#endif // #ifdef __ID3D12Device4_INTERFACE_DEFINED__

 

 #ifdef __ID3D12Device8_INTERFACE_DEFINED__

 static void TestDevice8(const TestContext& ctx)

@@ -1688,7 +1712,7 @@
     ComPtr<D3D12MA::Allocation> allocPtr0;

     ComPtr<ID3D12Resource> res0;

     CHECK_HR(ctx.allocator->CreateResource2(&allocDesc, &resourceDesc,

-        D3D12_RESOURCE_STATE_COMMON, NULL, NULL,

+        D3D12_RESOURCE_STATE_COMMON, NULL,

         &allocPtr0, IID_PPV_ARGS(&res0)));

     CHECK_BOOL(allocPtr0->GetHeap() == NULL);

 

@@ -1699,7 +1723,7 @@
     ComPtr<D3D12MA::Allocation> allocPtr1;

     ComPtr<ID3D12Resource> res1;

     CHECK_HR(ctx.allocator->CreateResource2(&allocDesc, &resourceDesc,

-        D3D12_RESOURCE_STATE_COMMON, NULL, NULL,

+        D3D12_RESOURCE_STATE_COMMON, NULL,

         &allocPtr1, IID_PPV_ARGS(&res1)));

     CHECK_BOOL(allocPtr1->GetHeap()!= NULL);

 }

@@ -1729,7 +1753,9 @@
     TestTransfer(ctx);

     TestZeroInitialized(ctx);

     TestMultithreading(ctx);

+#ifdef __ID3D12Device4_INTERFACE_DEFINED__

     TestDevice4(ctx);

+#endif

 #ifdef __ID3D12Device8_INTERFACE_DEFINED__

     TestDevice8(ctx);

 #endif