Skip to content

Commit d980fa2

Browse files
author
devsh
committed
added a streaming version of updateBufferRangeViaStagingBuffer to IUtilities
1 parent bde8b9f commit d980fa2

File tree

1 file changed

+32
-8
lines changed

1 file changed

+32
-8
lines changed

include/nbl/video/utilities/IUtilities.h

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,10 @@ class NBL_API2 IUtilities : public core::IReferenceCounted
297297
// updateBufferRangeViaStagingBuffer
298298
// --------------
299299

300-
//! Copies `data` to stagingBuffer and Records the commands needed to copy the data from stagingBuffer to `bufferRange.buffer`
300+
/* Callback signature used for upstreaming requests, `dst` is already pre-scrolled it points at the start of the staging block. */
301+
using data_production_callback_t = void(void* /*dst*/, const size_t /*offsetInRange*/, const size_t /*blockSize*/);
302+
303+
//! Fills ranges with callback allocated in stagingBuffer and Records the commands needed to copy the data from stagingBuffer to `bufferRange.buffer`
301304
//! If the allocation from staging memory fails due to large buffer size or fragmentation then This function may need to submit the command buffer via the `submissionQueue`.
302305
//! Returns:
303306
//! True on successful recording of copy commands and handling of overflows if any, and false on failure for any reason.
@@ -311,8 +314,7 @@ class NBL_API2 IUtilities : public core::IReferenceCounted
311314
//! * nextSubmit must be valid (see `SIntendedSubmitInfo::valid()`)
312315
//! * bufferRange must be valid (see `SBufferRange::isValid()`)
313316
//! * data must not be nullptr
314-
template<typename IntendedSubmitInfo> requires std::is_same_v<std::decay_t<IntendedSubmitInfo>,SIntendedSubmitInfo>
315-
inline bool updateBufferRangeViaStagingBuffer(IntendedSubmitInfo&& nextSubmit, const asset::SBufferRange<IGPUBuffer>& bufferRange, const void* data)
317+
inline bool updateBufferRangeViaStagingBuffer(SIntendedSubmitInfo& nextSubmit, const asset::SBufferRange<IGPUBuffer>& bufferRange, std::function<data_production_callback_t>& callback)
316318
{
317319
if (!bufferRange.isValid() || !bufferRange.buffer->getCreationParams().usage.hasFlags(asset::IBuffer::EUF_TRANSFER_DST_BIT))
318320
{
@@ -325,7 +327,7 @@ class NBL_API2 IUtilities : public core::IReferenceCounted
325327
return false;
326328

327329
const auto& limits = m_device->getPhysicalDevice()->getLimits();
328-
// TODO: Why did we settle on `/4` ? It definitely wasn't about the uint32_t size!
330+
// TODO: Why did we settle on `/4` ? It was something about worst case fragmentation due to alignment in General Purpose Address Allocator. But need to remember what exactly.
329331
const uint32_t optimalTransferAtom = core::min<uint32_t>(limits.maxResidentInvocations*OptimalCoalescedInvocationXferSize,m_defaultUploadBuffer->get_total_size()/4);
330332

331333
// no pipeline barriers necessary because write and optional flush happens before submit, and memory allocation is reclaimed after fence signal
@@ -344,10 +346,7 @@ class NBL_API2 IUtilities : public core::IReferenceCounted
344346
m_defaultUploadBuffer.get()->multi_allocate(std::chrono::steady_clock::now()+std::chrono::microseconds(500u),1u,&localOffset,&allocationSize,&m_allocationAlignment);
345347
// copy only the unpadded part
346348
if (localOffset!=StreamingTransientDataBufferMT<>::invalid_value)
347-
{
348-
const void* dataPtr = reinterpret_cast<const uint8_t*>(data) + uploadedSize;
349-
memcpy(reinterpret_cast<uint8_t*>(m_defaultUploadBuffer->getBufferPointer()) + localOffset, dataPtr, subSize);
350-
}
349+
callback(reinterpret_cast<uint8_t*>(m_defaultUploadBuffer->getBufferPointer())+localOffset,uploadedSize,subSize);
351350
else
352351
{
353352
const auto completed = nextSubmit.getFutureScratchSemaphore();
@@ -377,6 +376,31 @@ class NBL_API2 IUtilities : public core::IReferenceCounted
377376
}
378377
return true;
379378
}
379+
// overload to make invokers not care about l-value or r-value
380+
template<typename IntendedSubmitInfo> requires std::is_same_v<std::decay_t<IntendedSubmitInfo>,SIntendedSubmitInfo>
381+
inline bool updateBufferRangeViaStagingBuffer(IntendedSubmitInfo&& nextSubmit, const asset::SBufferRange<IGPUBuffer>& bufferRange, std::function<data_production_callback_t>&& callback)
382+
{
383+
return updateBufferRangeViaStagingBuffer(nextSubmit,bufferRange,callback);
384+
}
385+
386+
//! Copies `data` to stagingBuffer and Records the commands needed to copy the data from stagingBuffer to `bufferRange.buffer`.
387+
//! Returns same as `updateBufferRangeViaStagingBuffer` with a callback instead of a pointer, make sure to submit with `nextSubmit.popSubmit()` after this function returns.
388+
//! Parameters:
389+
//! - nextSubmit: same as `updateBufferRangeViaStagingBuffer` with a callback
390+
//! - bufferRange: same as `updateBufferRangeViaStagingBuffer` with a callback
391+
//! - data: raw pointer to data that will be copied to `bufferRange::buffer` at `bufferRange::offset`
392+
//! Valid Usage:
393+
//! * same as `updateBufferRangeViaStagingBuffer` with a callback
394+
//! * data must not be nullptr
395+
template<typename IntendedSubmitInfo> requires std::is_same_v<std::decay_t<IntendedSubmitInfo>,SIntendedSubmitInfo>
396+
inline bool updateBufferRangeViaStagingBuffer(IntendedSubmitInfo&& nextSubmit, const asset::SBufferRange<IGPUBuffer>& bufferRange, const void* data)
397+
{
398+
auto callback = [data](void* dst, const size_t offsetInRange, const size_t blockSize)->void
399+
{
400+
memcpy(dst,reinterpret_cast<const uint8_t*>(data)+offsetInRange,blockSize);
401+
};
402+
return updateBufferRangeViaStagingBuffer(nextSubmit,bufferRange,callback);
403+
}
380404

381405
//! This only needs a valid queue in `submit`
382406
template<typename IntendedSubmitInfo> requires std::is_same_v<std::decay_t<IntendedSubmitInfo>,SIntendedSubmitInfo>

0 commit comments

Comments
 (0)