@@ -23,12 +23,49 @@ class SubAllocatedDescriptorSet : public core::IReferenceCounted
23
23
using value_type = typename AddressAllocator::size_type;
24
24
static constexpr value_type invalid_value = AddressAllocator::invalid_address;
25
25
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
+ };
26
62
protected:
27
63
struct SubAllocDescriptorSetRange {
28
64
std::shared_ptr<AddressAllocator> addressAllocator;
29
65
std::shared_ptr<ReservedAllocator> reservedAllocator;
30
66
size_t reservedSize;
31
67
};
68
+ MultiTimelineEventHandlerST<DeferredFreeFunctor> eventHandler;
32
69
std::map<uint32_t , SubAllocDescriptorSetRange> m_allocatableRanges = {};
33
70
34
71
#ifdef _NBL_DEBUG
@@ -39,6 +76,7 @@ class SubAllocatedDescriptorSet : public core::IReferenceCounted
39
76
constexpr static inline uint32_t MinDescriptorSetAllocationSize = 1u ;
40
77
41
78
public:
79
+
42
80
// constructors
43
81
template <typename ... Args>
44
82
inline SubAllocatedDescriptorSet (video::IGPUDescriptorSetLayout* layout)
@@ -100,39 +138,65 @@ class SubAllocatedDescriptorSet : public core::IReferenceCounted
100
138
101
139
// main methods
102
140
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 ( )
105
143
{
106
- #ifdef _NBL_DEBUG
107
144
std::unique_lock<std::recursive_mutex> tLock (stAccessVerfier,std::try_to_lock_t ());
108
145
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 ();
110
156
111
157
auto allocator = getBindingAllocator (binding);
112
- for (uint32_t i=0 ; i<count; i++)
158
+ for (size_type i=0 ; i<count; i++)
113
159
{
114
160
if (outAddresses[i]!=AddressAllocator::invalid_address)
115
161
continue ;
116
162
117
163
outAddresses[i] = allocator->alloc_addr (1 ,1 );
118
164
}
119
165
}
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)
121
167
{
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 ();
126
169
127
170
auto allocator = getBindingAllocator (binding);
128
- for (uint32_t i=0 ; i<count; i++)
171
+ for (size_type i=0 ; i<count; i++)
129
172
{
130
173
if (addr[i]==AddressAllocator::invalid_address)
131
174
continue ;
132
175
133
176
allocator->free_addr (addr[i],1 );
134
177
}
135
178
}
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
+ }
136
200
};
137
201
138
202
}
0 commit comments