d3d12_descriptor_heap_manager.cpp (4781B)
1 // SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com> 2 // SPDX-License-Identifier: (GPL-3.0 OR PolyForm-Strict-1.0.0) 3 4 #include "d3d12_descriptor_heap_manager.h" 5 6 #include "common/assert.h" 7 #include "common/error.h" 8 9 D3D12DescriptorHeapManager::D3D12DescriptorHeapManager() = default; 10 D3D12DescriptorHeapManager::~D3D12DescriptorHeapManager() = default; 11 12 bool D3D12DescriptorHeapManager::Create(ID3D12Device* device, D3D12_DESCRIPTOR_HEAP_TYPE type, u32 num_descriptors, 13 bool shader_visible, Error* error) 14 { 15 D3D12_DESCRIPTOR_HEAP_DESC desc = { 16 type, static_cast<UINT>(num_descriptors), 17 shader_visible ? D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE : D3D12_DESCRIPTOR_HEAP_FLAG_NONE, 0u}; 18 19 HRESULT hr = device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(m_descriptor_heap.ReleaseAndGetAddressOf())); 20 if (FAILED(hr)) [[unlikely]] 21 { 22 Error::SetHResult(error, "CreateDescriptorHeap() failed: ", hr); 23 return false; 24 } 25 26 m_heap_base_cpu = m_descriptor_heap->GetCPUDescriptorHandleForHeapStart(); 27 if (shader_visible) 28 m_heap_base_gpu = m_descriptor_heap->GetGPUDescriptorHandleForHeapStart(); 29 30 m_num_descriptors = num_descriptors; 31 m_descriptor_increment_size = device->GetDescriptorHandleIncrementSize(type); 32 m_shader_visible = shader_visible; 33 34 // Set all slots to unallocated (1) 35 const u32 bitset_count = num_descriptors / BITSET_SIZE + (((num_descriptors % BITSET_SIZE) != 0) ? 1 : 0); 36 m_free_slots.resize(bitset_count); 37 for (BitSetType& bs : m_free_slots) 38 bs.flip(); 39 40 return true; 41 } 42 43 void D3D12DescriptorHeapManager::Destroy() 44 { 45 #ifdef _DEBUG 46 for (BitSetType& bs : m_free_slots) 47 { 48 DebugAssert(bs.all()); 49 } 50 #endif 51 52 m_shader_visible = false; 53 m_num_descriptors = 0; 54 m_descriptor_increment_size = 0; 55 m_heap_base_cpu = {}; 56 m_heap_base_gpu = {}; 57 m_descriptor_heap.Reset(); 58 m_free_slots.clear(); 59 } 60 61 bool D3D12DescriptorHeapManager::Allocate(D3D12DescriptorHandle* handle) 62 { 63 // Start past the temporary slots, no point in searching those. 64 for (u32 group = 0; group < m_free_slots.size(); group++) 65 { 66 BitSetType& bs = m_free_slots[group]; 67 if (bs.none()) 68 continue; 69 70 u32 bit = 0; 71 for (; bit < BITSET_SIZE; bit++) 72 { 73 if (bs[bit]) 74 break; 75 } 76 77 u32 index = group * BITSET_SIZE + bit; 78 bs[bit] = false; 79 80 handle->index = index; 81 handle->cpu_handle.ptr = m_heap_base_cpu.ptr + index * m_descriptor_increment_size; 82 handle->gpu_handle.ptr = m_shader_visible ? (m_heap_base_gpu.ptr + index * m_descriptor_increment_size) : 0; 83 return true; 84 } 85 86 Panic("Out of fixed descriptors"); 87 return false; 88 } 89 90 void D3D12DescriptorHeapManager::Free(u32 index) 91 { 92 DebugAssert(index < m_num_descriptors); 93 94 u32 group = index / BITSET_SIZE; 95 u32 bit = index % BITSET_SIZE; 96 m_free_slots[group][bit] = true; 97 } 98 99 void D3D12DescriptorHeapManager::Free(D3D12DescriptorHandle* handle) 100 { 101 if (handle->index == D3D12DescriptorHandle::INVALID_INDEX) 102 return; 103 104 Free(handle->index); 105 handle->Clear(); 106 } 107 108 D3D12DescriptorAllocator::D3D12DescriptorAllocator() = default; 109 D3D12DescriptorAllocator::~D3D12DescriptorAllocator() = default; 110 111 bool D3D12DescriptorAllocator::Create(ID3D12Device* device, D3D12_DESCRIPTOR_HEAP_TYPE type, u32 num_descriptors, Error* error) 112 { 113 const D3D12_DESCRIPTOR_HEAP_DESC desc = {type, static_cast<UINT>(num_descriptors), 114 D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, 0u}; 115 const HRESULT hr = device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(m_descriptor_heap.ReleaseAndGetAddressOf())); 116 if (FAILED(hr)) 117 { 118 Error::SetHResult(error, "CreateDescriptorHeap() failed: ", hr); 119 return false; 120 } 121 122 m_num_descriptors = num_descriptors; 123 m_descriptor_increment_size = device->GetDescriptorHandleIncrementSize(type); 124 m_heap_base_cpu = m_descriptor_heap->GetCPUDescriptorHandleForHeapStart(); 125 m_heap_base_gpu = m_descriptor_heap->GetGPUDescriptorHandleForHeapStart(); 126 return true; 127 } 128 129 void D3D12DescriptorAllocator::Destroy() 130 { 131 m_descriptor_heap.Reset(); 132 m_descriptor_increment_size = 0; 133 m_num_descriptors = 0; 134 m_current_offset = 0; 135 m_heap_base_cpu = {}; 136 m_heap_base_gpu = {}; 137 } 138 139 bool D3D12DescriptorAllocator::Allocate(u32 num_handles, D3D12DescriptorHandle* out_base_handle) 140 { 141 if ((m_current_offset + num_handles) > m_num_descriptors) 142 return false; 143 144 out_base_handle->index = m_current_offset; 145 out_base_handle->cpu_handle.ptr = m_heap_base_cpu.ptr + m_current_offset * m_descriptor_increment_size; 146 out_base_handle->gpu_handle.ptr = m_heap_base_gpu.ptr + m_current_offset * m_descriptor_increment_size; 147 m_current_offset += num_handles; 148 return true; 149 } 150 151 void D3D12DescriptorAllocator::Reset() 152 { 153 m_current_offset = 0; 154 }