Skip to content

Commit 14cf8e7

Browse files
Merge pull request #345 from Devsh-Graphics-Programming/descriptor_lifetime_tracking
Descriptor lifetime tracking & Command Pool revamp
2 parents d173c04 + 1acc6c4 commit 14cf8e7

File tree

76 files changed

+5911
-2866
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+5911
-2866
lines changed

cmake/common.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ macro(nbl_create_executable_project _EXTRA_SOURCES _EXTRA_OPTIONS _EXTRA_INCLUDE
8484

8585
target_include_directories(${EXECUTABLE_NAME}
8686
PUBLIC "${NBL_ROOT_PATH}/examples_tests/common"
87+
PUBLIC "${NBL_ROOT_PATH_BINARY}/include"
8788
PUBLIC ../../include
8889
PRIVATE ${_EXTRA_INCLUDES}
8990
)

include/nbl/asset/ICPUBuffer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ class ICPUBuffer : public asset::IBuffer, public asset::IAsset
7070
}
7171

7272
_NBL_STATIC_INLINE_CONSTEXPR auto AssetType = ET_BUFFER;
73-
inline E_TYPE getAssetType() const override { return AssetType; }
73+
inline IAsset::E_TYPE getAssetType() const override { return AssetType; }
7474

7575
virtual size_t conservativeSizeEstimate() const override { return getSize(); }
7676

include/nbl/asset/ICPUBufferView.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class ICPUBufferView : public IBufferView<ICPUBuffer>, public IAsset
4444
}
4545

4646
_NBL_STATIC_INLINE_CONSTEXPR auto AssetType = ET_BUFFER_VIEW;
47-
inline E_TYPE getAssetType() const override { return AssetType; }
47+
inline IAsset::E_TYPE getAssetType() const override { return AssetType; }
4848

4949
ICPUBuffer* getUnderlyingBuffer()
5050
{

include/nbl/asset/ICPUDescriptorSet.h

Lines changed: 103 additions & 238 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2018-2020 - DevSH Graphics Programming Sp. z O.O.
1+
// Copyright (C) 2018-2022 - DevSH Graphics Programming Sp. z O.O.
22
// This file is part of the "Nabla Engine".
33
// For conditions of distribution and use, see copyright notice in nabla.h
44

@@ -25,250 +25,115 @@ namespace nbl::asset
2525
@see IDescriptorSet
2626
*/
2727

28-
class ICPUDescriptorSet final : public IDescriptorSet<ICPUDescriptorSetLayout>, public IAsset, public impl::IEmulatedDescriptorSet<ICPUDescriptorSetLayout>
28+
class ICPUDescriptorSet final : public IDescriptorSet<ICPUDescriptorSetLayout>, public IAsset
2929
{
30-
using impl_t = impl::IEmulatedDescriptorSet<ICPUDescriptorSetLayout>;
31-
public:
32-
using base_t = IDescriptorSet<ICPUDescriptorSetLayout>;
33-
34-
//! Contructor preallocating memory for SDescriptorBindings which user can fill later (using non-const getDescriptors()).
35-
//! @see getDescriptors()
36-
ICPUDescriptorSet(core::smart_refctd_ptr<ICPUDescriptorSetLayout>&& _layout) : base_t(std::move(_layout)), IAsset(), impl_t(m_layout.get())
37-
{
38-
}
39-
40-
41-
inline size_t conservativeSizeEstimate() const override
42-
{
43-
return sizeof(void*)+m_descriptors->size()*sizeof(SDescriptorInfo)+m_bindingInfo->size()*sizeof(impl::IEmulatedDescriptorSet<ICPUDescriptorSetLayout>::SBindingInfo);
44-
}
45-
46-
core::smart_refctd_ptr<IAsset> clone(uint32_t _depth = ~0u) const override
47-
{
48-
auto layout = (_depth > 0u && m_layout) ? core::smart_refctd_ptr_static_cast<ICPUDescriptorSetLayout>(m_layout->clone(_depth - 1u)) : m_layout;
49-
auto cp = core::make_smart_refctd_ptr<ICPUDescriptorSet>(std::move(layout));
50-
clone_common(cp.get());
51-
52-
const uint32_t max_ix = getMaxDescriptorBindingIndex();
53-
for (uint32_t i = 0u; i <= max_ix; ++i)
54-
{
55-
auto cloneDescriptor = [](const core::smart_refctd_ptr<IDescriptor>& _desc, uint32_t _depth) -> core::smart_refctd_ptr<IDescriptor> {
56-
if (!_desc)
57-
return nullptr;
58-
59-
IAsset* asset = nullptr;
60-
switch (_desc->getTypeCategory())
61-
{
62-
case IDescriptor::EC_BUFFER:
63-
asset = static_cast<ICPUBuffer*>(_desc.get()); break;
64-
case IDescriptor::EC_BUFFER_VIEW:
65-
asset = static_cast<ICPUBufferView*>(_desc.get()); break;
66-
case IDescriptor::EC_IMAGE:
67-
asset = static_cast<ICPUImageView*>(_desc.get()); break;
68-
}
69-
70-
auto cp = asset->clone(_depth);
71-
72-
switch (_desc->getTypeCategory())
73-
{
74-
case IDescriptor::EC_BUFFER:
75-
return core::smart_refctd_ptr_static_cast<ICPUBuffer>(std::move(cp));
76-
case IDescriptor::EC_BUFFER_VIEW:
77-
return core::smart_refctd_ptr_static_cast<ICPUBufferView>(std::move(cp));
78-
case IDescriptor::EC_IMAGE:
79-
return core::smart_refctd_ptr_static_cast<ICPUImageView>(std::move(cp));
80-
}
81-
return nullptr;
82-
};
83-
84-
auto desc = getDescriptors(i);
85-
auto cp_desc = cp->getDescriptors(i);
86-
87-
const E_DESCRIPTOR_TYPE type = getDescriptorsType(i);
88-
for (uint32_t d = 0u; d < desc.size(); ++d)
89-
{
90-
cp_desc.begin()[d] = desc.begin()[d];
91-
if (_depth > 0u)
92-
{
93-
cp_desc.begin()[d].desc = cloneDescriptor(cp_desc.begin()[d].desc, _depth-1u);
94-
if (cp_desc.begin()[d].image.sampler && type==EDT_COMBINED_IMAGE_SAMPLER)
95-
cp_desc.begin()[d].image.sampler = core::smart_refctd_ptr_static_cast<ICPUSampler>(cp_desc.begin()[d].image.sampler->clone(_depth-1u));
96-
}
97-
}
98-
}
99-
100-
return cp;
101-
}
102-
103-
inline void convertToDummyObject(uint32_t referenceLevelsBelowToConvert=0u) override
104-
{
105-
convertToDummyObject_common(referenceLevelsBelowToConvert);
106-
107-
if (referenceLevelsBelowToConvert)
108-
{
109-
--referenceLevelsBelowToConvert;
110-
m_layout->convertToDummyObject(referenceLevelsBelowToConvert);
111-
for (auto it=m_descriptors->begin(); it!=m_descriptors->end(); it++)
112-
{
113-
auto descriptor = it->desc.get();
114-
if (!descriptor)
115-
continue;
116-
switch (descriptor->getTypeCategory())
117-
{
118-
case IDescriptor::EC_BUFFER:
119-
static_cast<asset::ICPUBuffer*>(descriptor)->convertToDummyObject(referenceLevelsBelowToConvert);
120-
break;
121-
case IDescriptor::EC_IMAGE:
122-
static_cast<asset::ICPUImageView*>(descriptor)->convertToDummyObject(referenceLevelsBelowToConvert);
123-
if (descriptor->getTypeCategory()==IDescriptor::EC_IMAGE && it->image.sampler)
124-
it->image.sampler->convertToDummyObject(referenceLevelsBelowToConvert);
125-
break;
126-
case IDescriptor::EC_BUFFER_VIEW:
127-
static_cast<asset::ICPUBufferView*>(descriptor)->convertToDummyObject(referenceLevelsBelowToConvert);
128-
break;
129-
}
130-
}
131-
}
132-
//dont drop descriptors so that we can access GPU descriptors through driver->getGPUObjectsFromAssets()
133-
//m_descriptors = nullptr;
134-
//m_bindingInfo = nullptr;
135-
}
136-
137-
_NBL_STATIC_INLINE_CONSTEXPR auto AssetType = ET_DESCRIPTOR_SET;
138-
inline E_TYPE getAssetType() const override { return AssetType; }
139-
140-
inline ICPUDescriptorSetLayout* getLayout()
141-
{
142-
assert(!isImmutable_debug());
143-
return m_layout.get();
144-
}
145-
inline const ICPUDescriptorSetLayout* getLayout() const { return m_layout.get(); }
146-
147-
//!
148-
inline uint32_t getMaxDescriptorBindingIndex() const
149-
{
150-
return m_bindingInfo ? static_cast<uint32_t>(m_bindingInfo->size()-1u):0u;
151-
}
152-
153-
//!
154-
inline E_DESCRIPTOR_TYPE getDescriptorsType(uint32_t index) const
155-
{
156-
if (m_bindingInfo && index<m_bindingInfo->size())
157-
return m_bindingInfo->operator[](index).descriptorType;
158-
return EDT_INVALID;
159-
}
160-
161-
//! Can modify the array of descriptors bound to a particular bindings
162-
inline core::SRange<SDescriptorInfo> getDescriptors(uint32_t index)
163-
{
164-
assert(!isImmutable_debug());
165-
166-
if (m_bindingInfo && index<m_bindingInfo->size())
167-
{
168-
const auto& info = m_bindingInfo->operator[](index);
169-
auto _begin = m_descriptors->begin()+info.offset;
170-
if (index+1u!=m_bindingInfo->size())
171-
return core::SRange<SDescriptorInfo>{_begin, m_descriptors->begin()+m_bindingInfo->operator[](index+1u).offset};
172-
else
173-
return core::SRange<SDescriptorInfo>{_begin, m_descriptors->end()};
174-
}
175-
else
176-
return core::SRange<SDescriptorInfo>{nullptr, nullptr};
177-
}
178-
inline core::SRange<const SDescriptorInfo> getDescriptors(uint32_t index) const
179-
{
180-
if (m_bindingInfo && index<m_bindingInfo->size())
181-
{
182-
const auto& info = m_bindingInfo->operator[](index);
183-
auto _begin = m_descriptors->begin()+info.offset;
184-
if (index+1u!=m_bindingInfo->size())
185-
return core::SRange<const SDescriptorInfo>{_begin, m_descriptors->begin()+m_bindingInfo->operator[](index+1u).offset};
186-
else
187-
return core::SRange<const SDescriptorInfo>{_begin, m_descriptors->end()};
188-
}
189-
else
190-
return core::SRange<const SDescriptorInfo>{nullptr, nullptr};
191-
}
192-
193-
inline auto getTotalDescriptorCount() const
30+
using base_t = IDescriptorSet<ICPUDescriptorSetLayout>;
31+
32+
public:
33+
//! Contructor preallocating memory for SDescriptorInfos which user can fill later (using non-const getDescriptorInfos()).
34+
//! @see getDescriptorInfos()
35+
ICPUDescriptorSet(core::smart_refctd_ptr<ICPUDescriptorSetLayout>&& _layout) : base_t(std::move(_layout)), IAsset()
36+
{
37+
for (uint32_t t = 0u; t < static_cast<uint32_t>(IDescriptor::E_TYPE::ET_COUNT); ++t)
19438
{
195-
return m_descriptors->size();
196-
}
39+
const auto type = static_cast<IDescriptor::E_TYPE>(t);
40+
const uint32_t count = m_layout->getTotalDescriptorCount(type);
41+
if (count == 0u)
42+
continue;
19743

198-
bool canBeRestoredFrom(const IAsset* _other) const override
199-
{
200-
auto* other = static_cast<const ICPUDescriptorSet*>(_other);
201-
return m_layout->canBeRestoredFrom(other->m_layout.get());
44+
m_descriptorInfos[t] = core::make_refctd_dynamic_array<core::smart_refctd_dynamic_array<ICPUDescriptorSet::SDescriptorInfo>>(count);
20245
}
203-
204-
protected:
205-
void restoreFromDummy_impl(IAsset* _other, uint32_t _levelsBelow) override
46+
}
47+
48+
_NBL_STATIC_INLINE_CONSTEXPR auto AssetType = ET_DESCRIPTOR_SET;
49+
inline E_TYPE getAssetType() const override { return AssetType; }
50+
51+
inline ICPUDescriptorSetLayout* getLayout()
52+
{
53+
assert(!isImmutable_debug());
54+
return m_layout.get();
55+
}
56+
57+
inline const ICPUDescriptorSetLayout* getLayout() const { return m_layout.get(); }
58+
59+
inline bool canBeRestoredFrom(const IAsset* _other) const override
60+
{
61+
auto* other = static_cast<const ICPUDescriptorSet*>(_other);
62+
return m_layout->canBeRestoredFrom(other->m_layout.get());
63+
}
64+
65+
inline size_t conservativeSizeEstimate() const override
66+
{
67+
assert(!"Invalid code path.");
68+
return 0xdeadbeefull;
69+
}
70+
71+
inline core::SRange<SDescriptorInfo> getDescriptorInfoStorage(const IDescriptor::E_TYPE type) const
72+
{
73+
// TODO: @Hazardu
74+
// Cannot do the mutability check here because it requires the function to be non-const, but the function cannot be non-const because it's called
75+
// from const functions in the asset converter.
76+
// Relevant comments/conversations:
77+
// https://github.com/Devsh-Graphics-Programming/Nabla/pull/345#discussion_r1054258384
78+
// https://github.com/Devsh-Graphics-Programming/Nabla/pull/345#discussion_r1056289599
79+
//
80+
// assert(!isImmutable_debug());
81+
if (!m_descriptorInfos[static_cast<uint32_t>(type)])
82+
return { nullptr, nullptr };
83+
else
84+
return { m_descriptorInfos[static_cast<uint32_t>(type)]->begin(), m_descriptorInfos[static_cast<uint32_t>(type)]->end() };
85+
}
86+
87+
core::SRange<SDescriptorInfo> getDescriptorInfos(const ICPUDescriptorSetLayout::CBindingRedirect::binding_number_t binding, IDescriptor::E_TYPE type = IDescriptor::E_TYPE::ET_COUNT);
88+
89+
core::SRange<const SDescriptorInfo> getDescriptorInfos(const ICPUDescriptorSetLayout::CBindingRedirect::binding_number_t binding, IDescriptor::E_TYPE type = IDescriptor::E_TYPE::ET_COUNT) const;
90+
91+
core::smart_refctd_ptr<IAsset> clone(uint32_t _depth = ~0u) const override;
92+
93+
void convertToDummyObject(uint32_t referenceLevelsBelowToConvert = 0u) override;
94+
95+
protected:
96+
void restoreFromDummy_impl(IAsset* _other, uint32_t _levelsBelow) override;
97+
98+
bool isAnyDependencyDummy_impl(uint32_t _levelsBelow) const override;
99+
100+
virtual ~ICPUDescriptorSet() = default;
101+
102+
private:
103+
static inline IDescriptor::E_CATEGORY getCategoryFromType(const IDescriptor::E_TYPE type)
104+
{
105+
auto category = IDescriptor::E_CATEGORY::EC_COUNT;
106+
switch (type)
206107
{
207-
auto* other = static_cast<ICPUDescriptorSet*>(_other);
208-
209-
if (_levelsBelow)
210-
{
211-
--_levelsBelow;
212-
restoreFromDummy_impl_call(m_layout.get(), other->getLayout(), _levelsBelow);
213-
for (auto it = m_descriptors->begin(); it != m_descriptors->end(); it++)
214-
{
215-
auto descriptor = it->desc.get();
216-
if (!descriptor)
217-
continue;
218-
const auto i = it - m_descriptors->begin();
219-
auto* d_other = other->m_descriptors->begin()[i].desc.get();
220-
221-
switch (descriptor->getTypeCategory())
222-
{
223-
case IDescriptor::EC_BUFFER:
224-
restoreFromDummy_impl_call(static_cast<ICPUBuffer*>(descriptor), static_cast<ICPUBuffer*>(d_other), _levelsBelow);
225-
break;
226-
case IDescriptor::EC_IMAGE:
227-
restoreFromDummy_impl_call(static_cast<ICPUImageView*>(descriptor), static_cast<ICPUImageView*>(d_other), _levelsBelow);
228-
if (descriptor->getTypeCategory() == IDescriptor::EC_IMAGE && it->image.sampler)
229-
restoreFromDummy_impl_call(it->image.sampler.get(), other->m_descriptors->begin()[i].image.sampler.get(), _levelsBelow);
230-
break;
231-
case IDescriptor::EC_BUFFER_VIEW:
232-
restoreFromDummy_impl_call(static_cast<ICPUBufferView*>(descriptor), static_cast<ICPUBufferView*>(d_other), _levelsBelow);
233-
break;
234-
}
235-
}
236-
}
237-
}
238-
239-
bool isAnyDependencyDummy_impl(uint32_t _levelsBelow) const override
240-
{
241-
--_levelsBelow;
242-
if (m_layout->isAnyDependencyDummy(_levelsBelow))
243-
return true;
244-
for (auto it = m_descriptors->begin(); it != m_descriptors->end(); it++)
245-
{
246-
auto descriptor = it->desc.get();
247-
if (!descriptor)
248-
continue;
249-
250-
switch (descriptor->getTypeCategory())
251-
{
252-
case IDescriptor::EC_BUFFER:
253-
if (static_cast<ICPUBuffer*>(descriptor)->isAnyDependencyDummy(_levelsBelow))
254-
return true;
255-
break;
256-
case IDescriptor::EC_IMAGE:
257-
if (static_cast<ICPUImageView*>(descriptor)->isAnyDependencyDummy(_levelsBelow))
258-
return true;
259-
if (it->image.sampler && it->image.sampler->isAnyDependencyDummy(_levelsBelow))
260-
return true;
261-
break;
262-
case IDescriptor::EC_BUFFER_VIEW:
263-
if (static_cast<ICPUBufferView*>(descriptor)->isAnyDependencyDummy(_levelsBelow))
264-
return true;
265-
break;
266-
}
267-
}
268-
return false;
108+
case IDescriptor::E_TYPE::ET_COMBINED_IMAGE_SAMPLER: [[fallthrough]];
109+
case IDescriptor::E_TYPE::ET_STORAGE_IMAGE: [[fallthrough]];
110+
case IDescriptor::E_TYPE::ET_INPUT_ATTACHMENT:
111+
category = IDescriptor::E_CATEGORY::EC_IMAGE;
112+
break;
113+
114+
case IDescriptor::E_TYPE::ET_UNIFORM_BUFFER: [[fallthrough]];
115+
case IDescriptor::E_TYPE::ET_UNIFORM_BUFFER_DYNAMIC: [[fallthrough]];
116+
case IDescriptor::E_TYPE::ET_STORAGE_BUFFER: [[fallthrough]];
117+
case IDescriptor::E_TYPE::ET_STORAGE_BUFFER_DYNAMIC:
118+
category = IDescriptor::E_CATEGORY::EC_BUFFER;
119+
break;
120+
121+
case IDescriptor::E_TYPE::ET_UNIFORM_TEXEL_BUFFER:
122+
case IDescriptor::E_TYPE::ET_STORAGE_TEXEL_BUFFER:
123+
category = IDescriptor::E_CATEGORY::EC_BUFFER_VIEW;
124+
break;
125+
126+
case IDescriptor::E_TYPE::ET_ACCELERATION_STRUCTURE:
127+
category = IDescriptor::E_CATEGORY::EC_ACCELERATION_STRUCTURE;
128+
break;
129+
130+
default:
131+
assert(!"Invalid code path.");
269132
}
133+
return category;
134+
}
270135

271-
virtual ~ICPUDescriptorSet() = default;
136+
core::smart_refctd_dynamic_array<ICPUDescriptorSet::SDescriptorInfo> m_descriptorInfos[static_cast<uint32_t>(IDescriptor::E_TYPE::ET_COUNT)];
272137
};
273138

274139
}

0 commit comments

Comments
 (0)