You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
improve allocate strategy, serve tight chunks without wasting memory from which I can suballocate buffers with padding & alignments taken into account - but I still hit asserts when requesting streaming buffer's max_size after finishing render call
Copy file name to clipboardExpand all lines: src/nbl/ext/ImGui/ImGui.cpp
+99-97Lines changed: 99 additions & 97 deletions
Original file line number
Diff line number
Diff line change
@@ -34,11 +34,19 @@ namespace nbl::ext::imgui
34
34
35
35
structDrawItemMeta
36
36
{
37
+
enum SBufferIx
38
+
{
39
+
VERTEX,
40
+
INDEX,
41
+
42
+
COUNT
43
+
};
44
+
37
45
//! total left bytes to upload for X-th command list
38
46
size_t totalLeftBytesToUpload;
39
47
40
-
//! we suballocate total of (command buffers count * 2u /*vertex & index buffers*/) buffers, we assume we have [ ... [vertex buffer, index buffer] ... ]
//! those buffers will be suballocated & filled from a block of memory, each block memory request is multiplied with this factor - if a block fails to be allocated the factor decreases (divided by 2 on fail)
@@ -96,7 +104,7 @@ namespace nbl::ext::imgui
96
104
//! with our allocation strategy unless we split indirect call into smaller pieces (however it doesnt make any sense if we assume all objects must be uploaded anyway imo - if all then why to bother?), also there is a very low chance this memory block will ever exceed 1KB even if you have a lot of GUI windows (< 45 draw commands, 22 bytes * limits.totalIndirectDrawCount) since its very small.
97
105
structSTightStructs
98
106
{
99
-
// we have total COUNT of blocks to allocate first
107
+
// we have total StructureIx::COUNT of blocks to allocate first before uploading command lists data
//! sum of metaList[x].sizes - all bytes which needs to be uploaded to cover all of totalIndirectDrawCount objects, note we don't count element & indirect structers there
// not only memoryBlockFactor divided by 2 will fail us, but even without it we will always fail suballocator with one offset becauase delta is too tight
mdi_size_t chunkOffset = InvalidAddress, chunkSize = min(streamingBuffer->max_size(), limits.totalByteSizeRequest * drawItem.meta.memoryBlockFactor/* temporary giving MORE then required for suballocator because of padding.. */);
1262
-
1263
-
//! (*) note we request single tight chunk of memory with fixed max alignment - big address space from which we fill try to suballocate to fill buffers
drawItem.meta.memoryBlockFactor *= 0.5f; // the problem is if another chunk failed because of SUBALLOCATOR then its because of padding probably.. decreasing the chunk request size wont help in that case and we should rather INCREASE the delta then with left bytes to upload for the suballocator to success with alignment restrictions
1269
-
return;
1270
-
}
1271
-
else
1255
+
if (drawItem.meta.totalLeftBytesToUpload >= 0u)
1256
+
{
1257
+
// we have 2 buffers to fill per command list, we will try with as tight streaming memory chunks as possible to not waste block memory (too big chunks allocated but only certain % used in reality) & make it a way our suballocator likes them (we respect required alignments)
1258
+
for (uint16_t bufferIx = 0u; bufferIx < DrawItemMeta::COUNT; ++bufferIx)
1272
1259
{
1273
-
// chunk allocated? update the state & let suballocator do the job
auto [chunkOffset, chunkSize] = std::make_tuple(InvalidAddress, min(streamingBuffer->max_size(), bufferSizeTotalUploadRequest + MdiMaxAlignment/* (**) add extra padding to let suballocator start at nice offset */));
1280
1265
1281
-
//! (*) we suballocate from the allocated chunk with required alignments - multi request all with single traits call per imgui command list
//! (*) note we request single tight chunk of memory with fixed max alignment - big address space from which we fill try to suballocate to fill buffers
// chunk allocated for a buffer? update the state & let suballocator do the job (we tried to waste minimum required memory and not leave empty space in the chunk)
// we consider buffers valid for command list if we suballocated them (under the hood filled at first time then skipped to not repeat memcpy) - if buffers are valid then command list is as well
// we consider buffers valid for command list if we suballocated BOTH of them (under the hood filled at first time then skipped to not repeat memcpy) - if buffers are valid then command list is as well
0 commit comments