Skip to content

Commit 21c9a18

Browse files
author
devsh
committed
Fix ImGUI's layout transition issues and validation errors.
also add command pool bitwise ops for creationg flags
1 parent 52a0a8b commit 21c9a18

File tree

4 files changed

+61
-32
lines changed

4 files changed

+61
-32
lines changed

include/nbl/ext/ImGui/ImGui.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ class UI final : public core::IReferenceCounted
4141
core::smart_refctd_ptr<video::IGPUDescriptorSetLayout> CreateDescriptorSetLayout();
4242

4343
void CreatePipeline(video::IGPURenderpass* renderpass, video::IGPUPipelineCache* pipelineCache);
44-
void CreateFontTexture(video::IGPUCommandBuffer* cmdBuffer, video::IQueue* queue);
44+
// TODO: just take an intended next submit instead of queue and cmdbuf, so we're consistent across utilities
45+
video::ISemaphore::future_t<video::IQueue::RESULT> CreateFontTexture(video::IGPUCommandBuffer* cmdBuffer, video::IQueue* queue);
4546
void UpdateDescriptorSets();
4647
void createSystem();
4748
void CreateFontSampler();

include/nbl/video/IGPUCommandPool.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,8 @@ class IGPUCommandPool::CCopyAccelerationStructureToOrFromMemoryCmd final : publi
822822
core::smart_refctd_ptr<const IGPUBuffer> m_buffer;
823823
};
824824

825+
NBL_ENUM_ADD_BITWISE_OPERATORS(IGPUCommandPool::CREATE_FLAGS)
826+
825827
}
826828

827829

src/nbl/ext/ImGui/ImGui.cpp

Lines changed: 56 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ namespace nbl::ext::imgui
3232
.createFlags = IGPUDescriptorSetLayout::SBinding::E_CREATE_FLAGS::ECF_NONE,
3333
.stageFlags = IShader::ESS_FRAGMENT,
3434
.count = 1,
35-
.samplers = nullptr // TODO: m_fontSampler?
35+
.immutableSamplers = nullptr // TODO: m_fontSampler?
3636
}
3737
};
3838

@@ -156,7 +156,7 @@ namespace nbl::ext::imgui
156156
}
157157
}
158158

159-
void UI::CreateFontTexture(video::IGPUCommandBuffer* cmdBuffer, video::IQueue* transfer)
159+
ISemaphore::future_t<IQueue::RESULT> UI::CreateFontTexture(video::IGPUCommandBuffer* cmdBuffer, video::IQueue* transfer)
160160
{
161161
// Load Fonts
162162
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
@@ -173,17 +173,14 @@ namespace nbl::ext::imgui
173173
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
174174
ImGuiIO& io = ImGui::GetIO();
175175

176+
// TODO: don't `pixels` need to be freed somehow!? (Use a uniqueptr with custom deleter lambda)
176177
uint8_t* pixels = nullptr;
177178
int32_t width, height;
178179
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
179-
assert(pixels != nullptr);
180-
assert(width > 0);
181-
assert(height > 0);
182-
const size_t componentsCount = 4, image_size = width * height * componentsCount * sizeof(uint8_t);
183-
184-
_NBL_STATIC_INLINE_CONSTEXPR auto NBL_FORMAT_FONT = EF_R8G8B8A8_UNORM;
185-
const auto buffer = core::make_smart_refctd_ptr< asset::CCustomAllocatorCPUBuffer<core::null_allocator<uint8_t>, true> >(image_size, pixels, core::adopt_memory);
180+
if (!pixels || width<=0 || height<=0)
181+
return IQueue::RESULT::OTHER_ERROR;
186182

183+
constexpr auto NBL_FORMAT_FONT = EF_R8G8B8A8_UNORM;
187184
IGPUImage::SCreationParams params;
188185
params.flags = static_cast<IImage::E_CREATE_FLAGS>(0u);
189186
params.type = IImage::ET_2D;
@@ -192,7 +189,7 @@ namespace nbl::ext::imgui
192189
params.mipLevels = 1;
193190
params.arrayLayers = 1u;
194191
params.samples = IImage::ESCF_1_BIT;
195-
params.usage |= IGPUImage::EUF_TRANSFER_DST_BIT | IGPUImage::EUF_SAMPLED_BIT | IGPUImage::E_USAGE_FLAGS::EUF_TRANSFER_SRC_BIT;
192+
params.usage |= IGPUImage::EUF_TRANSFER_DST_BIT | IGPUImage::EUF_SAMPLED_BIT | IGPUImage::E_USAGE_FLAGS::EUF_TRANSFER_SRC_BIT; // do you really need the SRC bit?
196193

197194
struct
198195
{
@@ -224,57 +221,80 @@ namespace nbl::ext::imgui
224221
if (!image)
225222
{
226223
logger->log("Could not create font image!", system::ILogger::ELL_ERROR);
227-
assert(false);
224+
return IQueue::RESULT::OTHER_ERROR;
228225
}
226+
image->setObjectDebugName("Nabla IMGUI extension Font Image");
229227

230228
if (!m_device->allocate(image->getMemoryReqs(), image.get()).isValid())
231229
{
232230
logger->log("Could not allocate memory for font image!", system::ILogger::ELL_ERROR);
233-
assert(false);
231+
return IQueue::RESULT::OTHER_ERROR;
234232
}
235-
236-
image->setObjectDebugName("Nabla IMGUI extension Font Image");
233+
234+
SIntendedSubmitInfo sInfo;
237235
{
238236
IQueue::SSubmitInfo::SCommandBufferInfo cmdInfo = { cmdBuffer };
239-
SIntendedSubmitInfo sInfo;
240237

241238
auto scratchSemaphore = m_device->createSemaphore(0);
242239
if (!scratchSemaphore)
243240
{
244241
logger->log("Could not create scratch semaphore", system::ILogger::ELL_ERROR);
245-
assert(false);
242+
return IQueue::RESULT::OTHER_ERROR;
246243
}
247244
scratchSemaphore->setObjectDebugName("Nabla IMGUI extension Scratch Semaphore");
248245

249246
sInfo.queue = transfer;
250247
sInfo.waitSemaphores = {};
251248
sInfo.commandBuffers = { &cmdInfo, 1 };
252-
sInfo.scratchSemaphore = // TODO: do I really need it?
249+
sInfo.scratchSemaphore = // TODO: do I really need it? YES, ALWAYS!
253250
{
254251
.semaphore = scratchSemaphore.get(),
255252
.value = 0,
256253
.stageMask = PIPELINE_STAGE_FLAGS::ALL_TRANSFER_BITS
257254
};
258-
259-
const SMemoryBarrier toTransferBarrier = {
255+
256+
// we have no explicit source stage and access to sync against, brand new clean image.
257+
const asset::SMemoryBarrier toTransferDep = {
260258
.dstStageMask = PIPELINE_STAGE_FLAGS::COPY_BIT,
261-
.dstAccessMask = ACCESS_FLAGS::TRANSFER_WRITE_BIT
259+
.dstAccessMask = ACCESS_FLAGS::TRANSFER_WRITE_BIT,
262260
};
263-
264-
cmdBuffer->begin(IGPUCommandBuffer::USAGE::ONE_TIME_SUBMIT_BIT);
265-
const IGPUCommandBuffer::SImageMemoryBarrier<IGPUCommandBuffer::SOwnershipTransferBarrier> barriers[] =
261+
const auto transferLayout = IGPUImage::LAYOUT::TRANSFER_DST_OPTIMAL;
262+
// transition to TRANSFER_DST
263+
IGPUCommandBuffer::SImageMemoryBarrier<IGPUCommandBuffer::SOwnershipTransferBarrier> barriers[] =
266264
{
267265
{
268-
.barrier = { .dep = toTransferBarrier },
266+
.barrier = {.dep = toTransferDep},
269267
.image = image.get(),
270268
.subresourceRange = regions.subresource,
271-
.newLayout = IGPUImage::LAYOUT::TRANSFER_DST_OPTIMAL
269+
.oldLayout = IGPUImage::LAYOUT::UNDEFINED, // wiping transition
270+
.newLayout = transferLayout
272271
}
273272
};
274273

275-
cmdBuffer->pipelineBarrier(E_DEPENDENCY_FLAGS::EDF_NONE, { .imgBarriers = barriers });
274+
cmdBuffer->begin(IGPUCommandBuffer::USAGE::ONE_TIME_SUBMIT_BIT);
275+
cmdBuffer->pipelineBarrier(E_DEPENDENCY_FLAGS::EDF_NONE,{.imgBarriers=barriers});
276+
// We cannot use the `AutoSubmit` variant of the util because we need to add a pipeline barrier with a transition onto the command buffer after the upload.
277+
// old layout is UNDEFINED because we don't want a content preserving transition, we can just put ourselves in transfer right away
278+
if (!utilities->updateImageViaStagingBuffer(sInfo,pixels,image->getCreationParameters().format,image.get(),transferLayout,regions.range))
279+
{
280+
logger->log("Could not upload font image contents", system::ILogger::ELL_ERROR);
281+
return IQueue::RESULT::OTHER_ERROR;
282+
}
276283

277-
utilities->updateImageViaStagingBufferAutoSubmit(sInfo, buffer->getPointer(), NBL_FORMAT_FONT, image.get(), IGPUImage::LAYOUT::TRANSFER_DST_OPTIMAL, regions.range);
284+
// we only need to sync with semaphore signal
285+
barriers[0].barrier.dep = toTransferDep.nextBarrier(sInfo.scratchSemaphore.stageMask,ACCESS_FLAGS::NONE);
286+
// transition to READ_ONLY_OPTIMAL ready for rendering with sampling
287+
barriers[0].oldLayout = barriers[0].newLayout;
288+
barriers[0].newLayout = IGPUImage::LAYOUT::READ_ONLY_OPTIMAL;
289+
cmdBuffer->pipelineBarrier(E_DEPENDENCY_FLAGS::EDF_NONE,{.imgBarriers=barriers});
290+
cmdBuffer->end();
291+
292+
const auto submit = sInfo.popSubmit({});
293+
if (transfer->submit(submit)!=IQueue::RESULT::SUCCESS)
294+
{
295+
logger->log("Could not submit workload for font texture upload.", system::ILogger::ELL_ERROR);
296+
return IQueue::RESULT::OTHER_ERROR;
297+
}
278298
}
279299

280300
{
@@ -286,6 +306,10 @@ namespace nbl::ext::imgui
286306

287307
m_fontTexture = m_device->createImageView(std::move(params));
288308
}
309+
310+
ISemaphore::future_t<IQueue::RESULT> retval(IQueue::RESULT::SUCCESS);
311+
retval.set({sInfo.scratchSemaphore.semaphore,sInfo.scratchSemaphore.value});
312+
return retval;
289313
}
290314

291315
void prepareKeyMapForDesktop()
@@ -328,8 +352,8 @@ namespace nbl::ext::imgui
328352
IGPUDescriptorSet::SDescriptorInfo info;
329353
{
330354
info.desc = m_fontTexture;
331-
info.info.image.sampler = m_fontSampler;
332-
info.info.image.imageLayout = nbl::asset::IImage::LAYOUT::READ_ONLY_OPTIMAL;
355+
info.info.combinedImageSampler.sampler = m_fontSampler;
356+
info.info.combinedImageSampler.imageLayout = nbl::asset::IImage::LAYOUT::READ_ONLY_OPTIMAL;
333357
}
334358

335359
IGPUDescriptorSet::SWriteDescriptorSet writeDescriptorSet{};
@@ -462,7 +486,9 @@ namespace nbl::ext::imgui
462486

463487
smart_refctd_ptr<nbl::video::IGPUCommandBuffer> transistentCMD;
464488
{
465-
smart_refctd_ptr<nbl::video::IGPUCommandPool> pool = device->createCommandPool(families.id.transfer, IGPUCommandPool::CREATE_FLAGS::TRANSIENT_BIT);
489+
using pool_flags_t = IGPUCommandPool::CREATE_FLAGS;
490+
// need to be individually resettable such that we can form a valid SIntendedSubmit out of the commandbuffer allocated from the pool
491+
smart_refctd_ptr<nbl::video::IGPUCommandPool> pool = device->createCommandPool(families.id.transfer, pool_flags_t::RESET_COMMAND_BUFFER_BIT|pool_flags_t::TRANSIENT_BIT);
466492
if (!pool)
467493
{
468494
logger->log("Could not create command pool!", system::ILogger::ELL_ERROR);

0 commit comments

Comments
 (0)