Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/src/util/d3d12_descriptor_heap_manager.cpp
4214 views
1
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <[email protected]>
2
// SPDX-License-Identifier: CC-BY-NC-ND-4.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
#if defined(_DEBUG) || defined(_DEVEL)
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
return false;
87
}
88
89
void D3D12DescriptorHeapManager::Free(u32 index)
90
{
91
DebugAssert(index < m_num_descriptors);
92
93
u32 group = index / BITSET_SIZE;
94
u32 bit = index % BITSET_SIZE;
95
m_free_slots[group][bit] = true;
96
}
97
98
void D3D12DescriptorHeapManager::Free(D3D12DescriptorHandle* handle)
99
{
100
if (handle->index == D3D12DescriptorHandle::INVALID_INDEX)
101
return;
102
103
Free(handle->index);
104
handle->Clear();
105
}
106
107
D3D12DescriptorAllocator::D3D12DescriptorAllocator() = default;
108
D3D12DescriptorAllocator::~D3D12DescriptorAllocator() = default;
109
110
bool D3D12DescriptorAllocator::Create(ID3D12Device* device, D3D12_DESCRIPTOR_HEAP_TYPE type, u32 num_descriptors, Error* error)
111
{
112
const D3D12_DESCRIPTOR_HEAP_DESC desc = {type, static_cast<UINT>(num_descriptors),
113
D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, 0u};
114
const HRESULT hr = device->CreateDescriptorHeap(&desc, IID_PPV_ARGS(m_descriptor_heap.ReleaseAndGetAddressOf()));
115
if (FAILED(hr))
116
{
117
Error::SetHResult(error, "CreateDescriptorHeap() failed: ", hr);
118
return false;
119
}
120
121
m_num_descriptors = num_descriptors;
122
m_descriptor_increment_size = device->GetDescriptorHandleIncrementSize(type);
123
m_heap_base_cpu = m_descriptor_heap->GetCPUDescriptorHandleForHeapStart();
124
m_heap_base_gpu = m_descriptor_heap->GetGPUDescriptorHandleForHeapStart();
125
return true;
126
}
127
128
void D3D12DescriptorAllocator::Destroy()
129
{
130
m_descriptor_heap.Reset();
131
m_descriptor_increment_size = 0;
132
m_num_descriptors = 0;
133
m_current_offset = 0;
134
m_heap_base_cpu = {};
135
m_heap_base_gpu = {};
136
}
137
138
bool D3D12DescriptorAllocator::Allocate(u32 num_handles, D3D12DescriptorHandle* out_base_handle)
139
{
140
if ((m_current_offset + num_handles) > m_num_descriptors)
141
return false;
142
143
out_base_handle->index = m_current_offset;
144
out_base_handle->cpu_handle.ptr = m_heap_base_cpu.ptr + m_current_offset * m_descriptor_increment_size;
145
out_base_handle->gpu_handle.ptr = m_heap_base_gpu.ptr + m_current_offset * m_descriptor_increment_size;
146
m_current_offset += num_handles;
147
return true;
148
}
149
150
void D3D12DescriptorAllocator::Reset()
151
{
152
m_current_offset = 0;
153
}
154
155