@@ -64,9 +64,10 @@ class SubAllocatedDescriptorSet : public core::IReferenceCounted
64
64
uint32_t m_binding;
65
65
std::vector<value_type> m_addresses;
66
66
};
67
+ using EventHandler = MultiTimelineEventHandlerST<DeferredFreeFunctor>;
67
68
protected:
68
69
struct SubAllocDescriptorSetRange {
69
- MultiTimelineEventHandlerST<DeferredFreeFunctor> eventHandler = MultiTimelineEventHandlerST<DeferredFreeFunctor> ({});
70
+ EventHandler eventHandler = EventHandler ({});
70
71
std::unique_ptr<AddressAllocator> addressAllocator = nullptr ;
71
72
std::unique_ptr<ReservedAllocator> reservedAllocator = nullptr ;
72
73
size_t reservedSize = 0 ;
@@ -179,7 +180,7 @@ class SubAllocatedDescriptorSet : public core::IReferenceCounted
179
180
video::IGPUDescriptorSet* getDescriptorSet () { return m_descriptorSet.get (); }
180
181
181
182
// ! Warning `outAddresses` needs to be primed with `invalid_value` values, otherwise no allocation happens for elements not equal to `invalid_value`
182
- inline void multi_allocate (uint32_t binding, size_type count, video::IGPUDescriptorSet::SDescriptorInfo* descriptors, value_type* outAddresses)
183
+ inline size_type try_multi_allocate (uint32_t binding, size_type count, video::IGPUDescriptorSet::SDescriptorInfo* descriptors, value_type* outAddresses)
183
184
{
184
185
auto debugGuard = stAccessVerifyDebugGuard ();
185
186
@@ -190,13 +191,18 @@ class SubAllocatedDescriptorSet : public core::IReferenceCounted
190
191
writes.reserve (count);
191
192
infos.reserve (count);
192
193
194
+ size_type unallocatedSize = 0u ;
193
195
for (size_type i=0 ; i<count; i++)
194
196
{
195
197
if (outAddresses[i]!=AddressAllocator::invalid_address)
196
198
continue ;
197
199
198
200
outAddresses[i] = allocator->alloc_addr (1 ,1 );
199
- // TODO: should also write something to the descriptor set (or probably leave that to the caller?)
201
+ if (outAddresses[i] == AddressAllocator::invalid_address)
202
+ {
203
+ unallocatedSize = count - i;
204
+ break ;
205
+ }
200
206
201
207
auto & descriptor = descriptors[i];
202
208
@@ -216,12 +222,56 @@ class SubAllocatedDescriptorSet : public core::IReferenceCounted
216
222
}
217
223
218
224
m_logicalDevice->updateDescriptorSets (writes, {});
225
+ return unallocatedSize;
226
+ }
227
+
228
+ template <class Clock =typename std::chrono::steady_clock>
229
+ inline size_type multi_allocate (const std::chrono::time_point<Clock>& maxWaitPoint, uint32_t binding, size_type count, video::IGPUDescriptorSet::SDescriptorInfo* descriptors, value_type* outAddresses) noexcept
230
+ {
231
+ auto debugGuard = stAccessVerifyDebugGuard ();
232
+
233
+ auto range = m_allocatableRanges.find (binding);
234
+ // Check if this binding has an allocator
235
+ if (range == m_allocatableRanges.end ())
236
+ return count;
237
+
238
+ auto & eventHandler = range->second .eventHandler ;
239
+
240
+ // try allocate once
241
+ size_type unallocatedSize = try_multi_allocate (binding, count, descriptors, outAddresses);
242
+ if (!unallocatedSize)
243
+ return 0u ;
244
+
245
+ // then try to wait at least once and allocate
246
+ do
247
+ {
248
+ eventHandler.wait (maxWaitPoint, unallocatedSize);
249
+
250
+ unallocatedSize = try_multi_allocate (binding, unallocatedSize, &descriptors[count - unallocatedSize], &outAddresses[count - unallocatedSize]);
251
+ if (!unallocatedSize)
252
+ return 0u ;
253
+ } while (Clock::now ()<maxWaitPoint);
254
+
255
+ return unallocatedSize;
256
+ }
257
+
258
+ inline size_type multi_allocate (uint32_t binding, size_type count, video::IGPUDescriptorSet::SDescriptorInfo* descriptors, value_type* outAddresses) noexcept
259
+ {
260
+ auto range = m_allocatableRanges.find (binding);
261
+ // Check if this binding has an allocator
262
+ if (range == m_allocatableRanges.end ())
263
+ return count;
264
+
265
+ return multi_allocate (TimelineEventHandlerBase::default_wait (), binding, count, descriptors, outAddresses);
219
266
}
267
+
220
268
inline void multi_deallocate (uint32_t binding, size_type count, const size_type* addr)
221
269
{
222
270
auto debugGuard = stAccessVerifyDebugGuard ();
223
271
224
272
auto allocator = getBindingAllocator (binding);
273
+ if (!allocator)
274
+ return ;
225
275
for (size_type i=0 ; i<count; i++)
226
276
{
227
277
if (addr[i]==AddressAllocator::invalid_address)
@@ -231,7 +281,7 @@ class SubAllocatedDescriptorSet : public core::IReferenceCounted
231
281
// TODO: should also write something to the descriptor sets
232
282
}
233
283
}
234
- // !
284
+
235
285
inline void multi_deallocate (uint32_t binding, const ISemaphore::SWaitInfo& futureWait, DeferredFreeFunctor&& functor) noexcept
236
286
{
237
287
auto range = m_allocatableRanges.find (binding);
@@ -243,7 +293,7 @@ class SubAllocatedDescriptorSet : public core::IReferenceCounted
243
293
auto debugGuard = stAccessVerifyDebugGuard ();
244
294
eventHandler.latch (futureWait,std::move (functor));
245
295
}
246
- // TODO: improve signature of this function in the future
296
+
247
297
inline void multi_deallocate (uint32_t binding, size_type count, const value_type* addr, const ISemaphore::SWaitInfo& futureWait) noexcept
248
298
{
249
299
if (futureWait.semaphore )
0 commit comments