Skip to content

Commit 67f84b0

Browse files
Fix an eternal bug w.r.t. CPUBuffer in GPUBuffer packing
1 parent c6a7cc9 commit 67f84b0

File tree

1 file changed

+39
-22
lines changed

1 file changed

+39
-22
lines changed

include/nbl/video/IGPUObjectFromAssetConverter.h

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -300,34 +300,51 @@ auto IGPUObjectFromAssetConverter::create(const asset::ICPUBuffer** const _begin
300300
std::max<uint64_t>(m_driver->getRequiredTBOAlignment(), m_driver->getRequiredUBOAlignment()),
301301
std::max<uint64_t>(m_driver->getRequiredSSBOAlignment(), _NBL_SIMD_ALIGNMENT)
302302
);
303-
304-
305-
core::LinearAddressAllocator<uint64_t> addrAllctr(nullptr, 0u, 0u, alignment, m_driver->getMaxBufferSize());
306-
uint64_t addr = 0ull;
307-
for (auto i=0u; i<assetCount; i++)
308-
{
309-
const uint64_t addr = addrAllctr.alloc_addr(_begin[i]->getSize(), alignment);
310-
assert(addr != decltype(addrAllctr)::invalid_address); // fix this to work better with really large buffers in the future
311-
if (addr == decltype(addrAllctr)::invalid_address)
312-
return {};
313-
res->operator[](i) = core::make_smart_refctd_ptr<typename video::asset_traits<asset::ICPUBuffer>::GPUObjectType>(addr);
314-
}
303+
315304

316305
auto reqs = m_driver->getDeviceLocalGPUMemoryReqs();
317-
reqs.vulkanReqs.size = addrAllctr.get_allocated_size();
318306
reqs.vulkanReqs.alignment = alignment;
319-
320-
auto gpubuffer = m_driver->createGPUBufferOnDedMem(reqs);
321-
322-
for (size_t i = 0u; i < res->size(); ++i)
307+
const uint64_t maxBufferSize = m_driver->getMaxBufferSize();
308+
auto out = res->begin();
309+
auto firstInBlock = out;
310+
auto newBlock = [&]() -> auto
323311
{
324-
auto& output = res->operator[](i);
325-
if (!output)
326-
continue;
312+
return core::LinearAddressAllocator<uint64_t>(nullptr, 0u, 0u, alignment, maxBufferSize);
313+
};
314+
auto addrAllctr = newBlock();
315+
auto finalizeBlock = [&]() -> void
316+
{
317+
reqs.vulkanReqs.size = addrAllctr.get_allocated_size();
318+
if (reqs.vulkanReqs.size==0u)
319+
return;
320+
321+
auto gpubuffer = m_driver->createGPUBufferOnDedMem(reqs);
322+
for (auto it=firstInBlock; it!=out; it++)
323+
if (auto output = *it)
324+
{
325+
auto cpubuffer = _begin[std::distance(res->begin(),it)];
326+
m_driver->updateBufferRangeViaStagingBuffer(gpubuffer.get(),output->getOffset(),cpubuffer->getSize(),cpubuffer->getPointer());
327+
output->setBuffer(core::smart_refctd_ptr(gpubuffer));
328+
}
329+
};
330+
for (auto it=_begin; it!=_end; it++,out++)
331+
{
332+
auto cpubuffer = *it;
333+
if (cpubuffer->getSize()>maxBufferSize)
334+
continue;
327335

328-
m_driver->updateBufferRangeViaStagingBuffer(gpubuffer.get(), output->getOffset(), _begin[i]->getSize(), _begin[i]->getPointer());
329-
output->setBuffer(core::smart_refctd_ptr(gpubuffer));
336+
uint64_t addr = addrAllctr.alloc_addr(cpubuffer->getSize(),alignment);
337+
if (addr==decltype(addrAllctr)::invalid_address)
338+
{
339+
finalizeBlock();
340+
firstInBlock = out;
341+
addrAllctr = newBlock();
342+
addr = addrAllctr.alloc_addr(cpubuffer->getSize(),alignment);
343+
}
344+
assert(addr != decltype(addrAllctr)::invalid_address);
345+
*out = core::make_smart_refctd_ptr<typename video::asset_traits<asset::ICPUBuffer>::GPUObjectType>(addr);
330346
}
347+
finalizeBlock();
331348

332349
return res;
333350
}

0 commit comments

Comments
 (0)