summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineD3D12
diff options
context:
space:
mode:
authorassiduous <assiduous@diligentgraphics.com>2021-02-15 22:48:21 +0000
committerassiduous <assiduous@diligentgraphics.com>2021-03-19 00:31:37 +0000
commitf69a435bfcc7977edfb89aa04d77aa99b6084833 (patch)
tree7c7897b63de5a17944d0b579da347dd62aa91ff9 /Graphics/GraphicsEngineD3D12
parentfixed some bugs in dx12 resource signature (diff)
downloadDiligentCore-f69a435bfcc7977edfb89aa04d77aa99b6084833.tar.gz
DiligentCore-f69a435bfcc7977edfb89aa04d77aa99b6084833.zip
D3D12 descriptor heap: initializing new allocated region with invalid descriptors
Diffstat (limited to 'Graphics/GraphicsEngineD3D12')
-rw-r--r--Graphics/GraphicsEngineD3D12/include/DescriptorHeap.hpp11
-rw-r--r--Graphics/GraphicsEngineD3D12/src/DescriptorHeap.cpp134
2 files changed, 127 insertions, 18 deletions
diff --git a/Graphics/GraphicsEngineD3D12/include/DescriptorHeap.hpp b/Graphics/GraphicsEngineD3D12/include/DescriptorHeap.hpp
index cd3ad1b7..3f542f9a 100644
--- a/Graphics/GraphicsEngineD3D12/include/DescriptorHeap.hpp
+++ b/Graphics/GraphicsEngineD3D12/include/DescriptorHeap.hpp
@@ -275,7 +275,8 @@ public:
rhs.m_MaxAllocatedSize = 0;
#ifdef DILIGENT_DEVELOPMENT
m_AllocationsCounter.store(rhs.m_AllocationsCounter.load());
- rhs.m_AllocationsCounter = 0;
+ rhs.m_AllocationsCounter = 0;
+ m_pd3d12InvalidDescriptorHeap = std::move(rhs.m_pd3d12InvalidDescriptorHeap);
#endif
}
@@ -339,6 +340,12 @@ private:
#ifdef DILIGENT_DEVELOPMENT
std::atomic_int32_t m_AllocationsCounter = 0;
+ // This descriptor heap is only used to copy invalid descriptors to
+ // a new allocated region. Using these descriptors will result in device
+ // removal. Note that using null descriptors is perfectly valid in D3D12
+ // and does not produce any errors.
+ static constexpr Uint32 InvalidDescriptorsCount = 128;
+ CComPtr<ID3D12DescriptorHeap> m_pd3d12InvalidDescriptorHeap;
#endif
// Note: when adding new members, do not forget to update move ctor
@@ -495,7 +502,7 @@ protected:
RenderDeviceD3D12Impl& m_DeviceD3D12Impl;
const D3D12_DESCRIPTOR_HEAP_DESC m_HeapDesc;
- CComPtr<ID3D12DescriptorHeap> m_pd3d12DescriptorHeap;
+ CComPtr<ID3D12DescriptorHeap> m_pd3d12DescriptorHeap; // Must be defined after m_HeapDesc
const UINT m_DescriptorSize;
diff --git a/Graphics/GraphicsEngineD3D12/src/DescriptorHeap.cpp b/Graphics/GraphicsEngineD3D12/src/DescriptorHeap.cpp
index a1859a71..1159c041 100644
--- a/Graphics/GraphicsEngineD3D12/src/DescriptorHeap.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/DescriptorHeap.cpp
@@ -39,27 +39,109 @@ DescriptorHeapAllocationManager::DescriptorHeapAllocationManager(IMemoryAllocato
IDescriptorAllocator& ParentAllocator,
size_t ThisManagerId,
const D3D12_DESCRIPTOR_HEAP_DESC& HeapDesc) :
- // clang-format off
- m_ParentAllocator {ParentAllocator},
- m_DeviceD3D12Impl {DeviceD3D12Impl},
- m_ThisManagerId {ThisManagerId },
- m_HeapDesc {HeapDesc },
- m_DescriptorSize {DeviceD3D12Impl.GetD3D12Device()->GetDescriptorHandleIncrementSize(m_HeapDesc.Type)},
- m_NumDescriptorsInAllocation {HeapDesc.NumDescriptors},
- m_FreeBlockManager {HeapDesc.NumDescriptors, Allocator}
-// clang-format on
+ DescriptorHeapAllocationManager //
+ {
+ Allocator,
+ DeviceD3D12Impl,
+ ParentAllocator,
+ ThisManagerId,
+ [&HeapDesc, &DeviceD3D12Impl]() -> CComPtr<ID3D12DescriptorHeap> //
+ {
+ auto* pDevice = DeviceD3D12Impl.GetD3D12Device();
+
+ CComPtr<ID3D12DescriptorHeap> pd3d12DescriptorHeap;
+ pDevice->CreateDescriptorHeap(&HeapDesc, __uuidof(pd3d12DescriptorHeap), reinterpret_cast<void**>(static_cast<ID3D12DescriptorHeap**>(&pd3d12DescriptorHeap)));
+ return pd3d12DescriptorHeap;
+ }(),
+ 0, // First descriptor
+ HeapDesc.NumDescriptors // Num descriptors
+ }
{
- auto pDevice = DeviceD3D12Impl.GetD3D12Device();
+}
- m_FirstCPUHandle.ptr = 0;
- m_FirstGPUHandle.ptr = 0;
+#ifdef DILIGENT_DEVELOPMENT
+namespace
+{
- pDevice->CreateDescriptorHeap(&m_HeapDesc, __uuidof(m_pd3d12DescriptorHeap), reinterpret_cast<void**>(static_cast<ID3D12DescriptorHeap**>(&m_pd3d12DescriptorHeap)));
- m_FirstCPUHandle = m_pd3d12DescriptorHeap->GetCPUDescriptorHandleForHeapStart();
- if (m_HeapDesc.Flags & D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE)
- m_FirstGPUHandle = m_pd3d12DescriptorHeap->GetGPUDescriptorHandleForHeapStart();
+CComPtr<ID3D12Resource> CreateDummyTexture(ID3D12Device* pd3d12Device, DXGI_FORMAT dxgiFmt, D3D12_RESOURCE_FLAGS d3d12ResourceFlags)
+{
+ D3D12_RESOURCE_DESC d3d12TexDesc{};
+ d3d12TexDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
+ d3d12TexDesc.Alignment = 0;
+ d3d12TexDesc.Width = 128;
+ d3d12TexDesc.Height = 128;
+ d3d12TexDesc.DepthOrArraySize = 1;
+ d3d12TexDesc.MipLevels = 1;
+ d3d12TexDesc.Format = dxgiFmt;
+ d3d12TexDesc.SampleDesc = DXGI_SAMPLE_DESC{1, 0};
+ d3d12TexDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
+ d3d12TexDesc.Flags = d3d12ResourceFlags;
+
+ D3D12_HEAP_PROPERTIES d3d12HeapProps{};
+ d3d12HeapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
+ d3d12HeapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
+ d3d12HeapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
+ d3d12HeapProps.CreationNodeMask = 1;
+ d3d12HeapProps.VisibleNodeMask = 1;
+
+ CComPtr<ID3D12Resource> pd3d12Texture;
+
+ auto hr = pd3d12Device->CreateCommittedResource(&d3d12HeapProps, D3D12_HEAP_FLAG_NONE,
+ &d3d12TexDesc, D3D12_RESOURCE_STATE_COMMON, nullptr,
+ __uuidof(pd3d12Texture),
+ reinterpret_cast<void**>(static_cast<ID3D12Resource**>(&pd3d12Texture)));
+ VERIFY_EXPR(SUCCEEDED(hr));
+ (void)hr;
+
+ return pd3d12Texture;
}
+CComPtr<ID3D12DescriptorHeap> CreateInvalidDescriptorHeap(ID3D12Device* pd3d12Device, const D3D12_DESCRIPTOR_HEAP_DESC& InvalidHeapDesc)
+{
+ CComPtr<ID3D12DescriptorHeap> pd3d12InvalidDescriptorHeap;
+
+ pd3d12Device->CreateDescriptorHeap(&InvalidHeapDesc, __uuidof(pd3d12InvalidDescriptorHeap), reinterpret_cast<void**>(static_cast<ID3D12DescriptorHeap**>(&pd3d12InvalidDescriptorHeap)));
+ DEV_CHECK_ERR(pd3d12InvalidDescriptorHeap, "Failed to create Null descriptor heap");
+ const auto DescriptorSize = pd3d12Device->GetDescriptorHandleIncrementSize(InvalidHeapDesc.Type);
+ // Initialize descriptors with invalid handle - create a view and then delete the resource.
+ auto CPUHandle = pd3d12InvalidDescriptorHeap->GetCPUDescriptorHandleForHeapStart();
+ if (InvalidHeapDesc.Type == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV)
+ {
+ auto pDummyTex = CreateDummyTexture(pd3d12Device, DXGI_FORMAT_R8G8B8A8_UNORM, D3D12_RESOURCE_FLAG_NONE);
+
+ for (Uint32 i = 0; i < InvalidHeapDesc.NumDescriptors; ++i, CPUHandle.ptr += DescriptorSize)
+ pd3d12Device->CreateShaderResourceView(pDummyTex, nullptr, CPUHandle);
+ }
+ else if (InvalidHeapDesc.Type == D3D12_DESCRIPTOR_HEAP_TYPE_RTV)
+ {
+ auto pDummyTex = CreateDummyTexture(pd3d12Device, DXGI_FORMAT_R8G8B8A8_UNORM, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET);
+
+ for (Uint32 i = 0; i < InvalidHeapDesc.NumDescriptors; ++i, CPUHandle.ptr += DescriptorSize)
+ pd3d12Device->CreateRenderTargetView(pDummyTex, nullptr, CPUHandle);
+ }
+ else if (InvalidHeapDesc.Type == D3D12_DESCRIPTOR_HEAP_TYPE_DSV)
+ {
+ auto pDummyTex = CreateDummyTexture(pd3d12Device, DXGI_FORMAT_D32_FLOAT, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL);
+
+ for (Uint32 i = 0; i < InvalidHeapDesc.NumDescriptors; ++i, CPUHandle.ptr += DescriptorSize)
+ pd3d12Device->CreateDepthStencilView(pDummyTex, nullptr, CPUHandle);
+ }
+ else if (InvalidHeapDesc.Type == D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER)
+ {
+ // Nothing can be done - sampler is not an object and initialized right in the heap.
+ // It is impossible to create invalid sampler.
+ }
+ else
+ {
+ UNEXPECTED("Unexpected heap type");
+ }
+
+ return pd3d12InvalidDescriptorHeap;
+}
+
+} // namespace
+#endif // DILIGENT_DEVELOPMENT
+
// Uses subrange of descriptors in the existing D3D12 descriptor heap
// that starts at offset FirstDescriptor and uses NumDescriptors descriptors
DescriptorHeapAllocationManager::DescriptorHeapAllocationManager(IMemoryAllocator& Allocator,
@@ -88,6 +170,15 @@ DescriptorHeapAllocationManager::DescriptorHeapAllocationManager(IMemoryAllocato
m_FirstGPUHandle = pd3d12DescriptorHeap->GetGPUDescriptorHandleForHeapStart();
m_FirstGPUHandle.ptr += m_DescriptorSize * FirstDescriptor;
}
+
+#ifdef DILIGENT_DEVELOPMENT
+ {
+ auto InvalidHeapDesc = m_HeapDesc;
+ InvalidHeapDesc.NumDescriptors = InvalidDescriptorsCount;
+ InvalidHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
+ m_pd3d12InvalidDescriptorHeap = CreateInvalidDescriptorHeap(DeviceD3D12Impl.GetD3D12Device(), InvalidHeapDesc);
+ }
+#endif
}
@@ -124,6 +215,17 @@ DescriptorHeapAllocation DescriptorHeapAllocationManager::Allocate(uint32_t Coun
#ifdef DILIGENT_DEVELOPMENT
++m_AllocationsCounter;
+ // Copy invalid descriptors. If the descriptors are accessed, this will cause device removal.
+ {
+ auto* pd3d12Device = m_DeviceD3D12Impl.GetD3D12Device();
+ const auto InvalidCPUHandles = m_pd3d12InvalidDescriptorHeap->GetCPUDescriptorHandleForHeapStart();
+ auto DstCPUHandle = CPUHandle;
+ for (Uint32 FisrtDescr = 0; FisrtDescr < Count; FisrtDescr += InvalidDescriptorsCount, DstCPUHandle.ptr += InvalidDescriptorsCount)
+ {
+ auto NumDescrsToCopy = std::min(Count - FisrtDescr, InvalidDescriptorsCount);
+ pd3d12Device->CopyDescriptorsSimple(NumDescrsToCopy, DstCPUHandle, InvalidCPUHandles, m_HeapDesc.Type);
+ }
+ }
#endif
VERIFY(m_ThisManagerId < std::numeric_limits<Uint16>::max(), "ManagerID exceeds 16-bit range");