Skip to content

Commit e0e91ff

Browse files
committed
Work on deferred freeing the descriptors
1 parent 289e424 commit e0e91ff

File tree

1 file changed

+75
-11
lines changed

1 file changed

+75
-11
lines changed

include/nbl/video/alloc/SubAllocatedDescriptorSet.h

Lines changed: 75 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,49 @@ class SubAllocatedDescriptorSet : public core::IReferenceCounted
2323
using value_type = typename AddressAllocator::size_type;
2424
static constexpr value_type invalid_value = AddressAllocator::invalid_address;
2525

26+
class DeferredFreeFunctor
27+
{
28+
public:
29+
inline DeferredFreeFunctor(SubAllocatedDescriptorSet* composed, uint32_t binding, size_type count, value_type* addresses)
30+
: m_addresses(addresses, addresses + count), m_binding(binding), m_composed(composed)
31+
{
32+
}
33+
34+
// Just does the de-allocation
35+
inline void operator()()
36+
{
37+
// isn't assert already debug-only?
38+
#ifdef _NBL_DEBUG
39+
assert(m_composed);
40+
#endif // _NBL_DEBUG
41+
m_composed->multi_deallocate(m_binding, m_addresses.size(), &m_addresses[0]);
42+
}
43+
44+
// Takes count of allocations we want to free up as reference, true is returned if
45+
// the amount of allocations freed was >= allocationsToFreeUp
46+
// False is returned if there are more allocations to free up
47+
inline bool operator()(size_type allocationsToFreeUp)
48+
{
49+
auto prevCount = m_addresses.size();
50+
operator()();
51+
auto totalFreed = m_addresses.size() - prevCount;
52+
53+
// This does the same logic as bool operator()(size_type&) on
54+
// CAsyncSingleBufferSubAllocator
55+
return totalFreed >= allocationsToFreeUp;
56+
}
57+
protected:
58+
SubAllocatedDescriptorSet* m_composed;
59+
uint32_t m_binding;
60+
std::vector<value_type> m_addresses;
61+
};
2662
protected:
2763
struct SubAllocDescriptorSetRange {
2864
std::shared_ptr<AddressAllocator> addressAllocator;
2965
std::shared_ptr<ReservedAllocator> reservedAllocator;
3066
size_t reservedSize;
3167
};
68+
MultiTimelineEventHandlerST<DeferredFreeFunctor> eventHandler;
3269
std::map<uint32_t, SubAllocDescriptorSetRange> m_allocatableRanges = {};
3370

3471
#ifdef _NBL_DEBUG
@@ -39,6 +76,7 @@ class SubAllocatedDescriptorSet : public core::IReferenceCounted
3976
constexpr static inline uint32_t MinDescriptorSetAllocationSize = 1u;
4077

4178
public:
79+
4280
// constructors
4381
template<typename... Args>
4482
inline SubAllocatedDescriptorSet(video::IGPUDescriptorSetLayout* layout)
@@ -100,39 +138,65 @@ class SubAllocatedDescriptorSet : public core::IReferenceCounted
100138

101139
// main methods
102140

103-
//! Warning `outAddresses` needs to be primed with `invalid_value` values, otherwise no allocation happens for elements not equal to `invalid_value`
104-
inline void multi_allocate(uint32_t binding, uint32_t count, value_type* outAddresses)
141+
#ifdef _NBL_DEBUG
142+
std::unique_lock<std::recursive_mutex> stAccessVerifyDebugGuard()
105143
{
106-
#ifdef _NBL_DEBUG
107144
std::unique_lock<std::recursive_mutex> tLock(stAccessVerfier,std::try_to_lock_t());
108145
assert(tLock.owns_lock());
109-
#endif // _NBL_DEBUG
146+
return tLock;
147+
}
148+
#else
149+
bool stAccessVerifyDebugGuard() { return false; }
150+
#endif
151+
152+
//! Warning `outAddresses` needs to be primed with `invalid_value` values, otherwise no allocation happens for elements not equal to `invalid_value`
153+
inline void multi_allocate(uint32_t binding, size_type count, value_type* outAddresses)
154+
{
155+
auto debugGuard = stAccessVerifyDebugGuard();
110156

111157
auto allocator = getBindingAllocator(binding);
112-
for (uint32_t i=0; i<count; i++)
158+
for (size_type i=0; i<count; i++)
113159
{
114160
if (outAddresses[i]!=AddressAllocator::invalid_address)
115161
continue;
116162

117163
outAddresses[i] = allocator->alloc_addr(1,1);
118164
}
119165
}
120-
inline void multi_deallocate(uint32_t binding, uint32_t count, const size_type* addr)
166+
inline void multi_deallocate(uint32_t binding, size_type count, const size_type* addr)
121167
{
122-
#ifdef _NBL_DEBUG
123-
std::unique_lock<std::recursive_mutex> tLock(stAccessVerfier,std::try_to_lock_t());
124-
assert(tLock.owns_lock());
125-
#endif // _NBL_DEBUG
168+
auto debugGuard = stAccessVerifyDebugGuard();
126169

127170
auto allocator = getBindingAllocator(binding);
128-
for (uint32_t i=0; i<count; i++)
171+
for (size_type i=0; i<count; i++)
129172
{
130173
if (addr[i]==AddressAllocator::invalid_address)
131174
continue;
132175

133176
allocator->free_addr(addr[i],1);
134177
}
135178
}
179+
//!
180+
inline void multi_deallocate(const ISemaphore::SWaitInfo& futureWait, DeferredFreeFunctor&& functor) noexcept
181+
{
182+
auto debugGuard = stAccessVerifyDebugGuard();
183+
eventHandler.latch(futureWait,std::move(functor));
184+
}
185+
// TODO: improve signature of this function in the future
186+
template<typename T=core::IReferenceCounted>
187+
inline void multi_deallocate(uint32_t binding, uint32_t count, const value_type* addr, const ISemaphore::SWaitInfo& futureWait) noexcept
188+
{
189+
if (futureWait.semaphore)
190+
multi_deallocate(futureWait, DeferredFreeFunctor(&m_composed, binding, count, addr));
191+
else
192+
multi_deallocate(binding, count, addr);
193+
}
194+
//! Returns free events still outstanding
195+
inline uint32_t cull_frees() noexcept
196+
{
197+
auto debugGuard = stAccessVerifyDebugGuard();
198+
return eventHandler.poll().eventsLeft;
199+
}
136200
};
137201

138202
}

0 commit comments

Comments
 (0)