Skip to content

Commit 650e2e4

Browse files
committed
update getters to return dumb pointers, let users pass MDI streaming buffer themselves & validate its creation params, memory, allocate + mapping flags, update examples_tests submodule
1 parent 35af49d commit 650e2e4

File tree

3 files changed

+82
-52
lines changed

3 files changed

+82
-52
lines changed

examples_tests

include/nbl/ext/ImGui/ImGui.h

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,24 @@ namespace nbl::ext::imgui
88
class UI final : public core::IReferenceCounted
99
{
1010
public:
11-
UI(core::smart_refctd_ptr<video::ILogicalDevice> _device, core::smart_refctd_ptr<video::IGPUDescriptorSetLayout> _descriptorSetLayout, video::IGPURenderpass* renderpass, uint32_t subpassIx, video::IGPUPipelineCache* pipelineCache = nullptr, uint32_t mdiTotalByteSize = 1024u * 1024u * 2u /* 2Mb */);
11+
struct MDI
12+
{
13+
using COMPOSE_T = nbl::video::StreamingTransientDataBufferST<nbl::core::allocator<uint8_t>>;
14+
15+
enum E_BUFFER_CONTENT : uint8_t
16+
{
17+
EBC_DRAW_INDIRECT_STRUCTURES,
18+
EBC_ELEMENT_STRUCTURES,
19+
EBC_INDEX_BUFFERS,
20+
EBC_VERTEX_BUFFERS,
21+
22+
EBC_COUNT,
23+
};
24+
25+
nbl::core::smart_refctd_ptr<typename COMPOSE_T> streamingTDBufferST; // composed buffer layout is [EBC_DRAW_INDIRECT_STRUCTURES] [EBC_ELEMENT_STRUCTURES] [EBC_INDEX_BUFFERS] [EBC_VERTEX_BUFFERS]
26+
};
27+
28+
UI(core::smart_refctd_ptr<video::ILogicalDevice> _device, core::smart_refctd_ptr<video::IGPUDescriptorSetLayout> _descriptorSetLayout, video::IGPURenderpass* renderpass, uint32_t subpassIx, video::IGPUPipelineCache* pipelineCache = nullptr, nbl::core::smart_refctd_ptr<typename MDI::COMPOSE_T> _streamingMDIBuffer = nullptr);
1229
~UI() override;
1330

1431
//! Nabla ImGUI backend reserves this index for font atlas, any attempt to hook user defined texture within the index will cause runtime error [TODO: could have a setter & getter to control the default & currently hooked font texture ID and init 0u by default]
@@ -17,7 +34,7 @@ class UI final : public core::IReferenceCounted
1734
//! update ImGUI internal state & cpu draw command lists, call it before this->render
1835
bool update(const ui::IWindow* window, float deltaTimeInSec, const core::SRange<const nbl::ui::SMouseEvent> mouseEvents, const core::SRange<const nbl::ui::SKeyboardEvent> keyboardEvents);
1936

20-
//! updates mapped mdi buffer & records draw calls [TODO: maybe its a good idea to update mdi at the end of .update call instead of doing it here?]
37+
//! updates mapped mdi buffer & records draw calls
2138
bool render(nbl::video::SIntendedSubmitInfo& info, const nbl::video::IGPUDescriptorSet* const descriptorSet);
2239

2340
//! registers lambda listener in which ImGUI calls should be recorded
@@ -27,18 +44,18 @@ class UI final : public core::IReferenceCounted
2744
//! sets ImGUI context, you are supposed to pass valid ImGuiContext* context
2845
void setContext(void* imguiContext);
2946

30-
//! image view getter to access default font texture
31-
inline auto getFontAtlasView() -> decltype(auto) { return core::smart_refctd_ptr(m_fontAtlasTexture); }
47+
//! image view default font texture
48+
inline nbl::video::IGPUImageView* getFontAtlasView() { return m_fontAtlasTexture.get(); }
3249

33-
//! mdi streaming buffer getter
34-
inline auto getStreamingBuffer() -> decltype(auto) { return (std::as_const(m_mdi.streamingTDBufferST)); }
50+
//! mdi streaming buffer
51+
inline typename MDI::COMPOSE_T* getStreamingBuffer() { return m_mdi.streamingTDBufferST.get(); }
3552

3653
//! ImGUI context getter, you are supposed to cast it, eg. reinterpret_cast<ImGuiContext*>(this->getContext());
3754
void* getContext();
3855
private:
3956
void createSystem();
4057
void createPipeline(core::smart_refctd_ptr<video::IGPUDescriptorSetLayout> descriptorSetLayout, video::IGPURenderpass* renderpass, uint32_t subpassIx, video::IGPUPipelineCache* pipelineCache);
41-
void createMDIBuffer(const uint32_t totalByteSize);
58+
void createMDIBuffer(nbl::core::smart_refctd_ptr<typename MDI::COMPOSE_T> _streamingMDIBuffer);
4259
video::ISemaphore::future_t<video::IQueue::RESULT> createFontAtlasTexture(video::IGPUCommandBuffer* cmdBuffer, video::IQueue* queue);
4360
void handleMouseEvents(const core::SRange<const nbl::ui::SMouseEvent>& events, const ui::IWindow* window) const;
4461
void handleKeyEvents(const core::SRange<const nbl::ui::SKeyboardEvent>& events) const;
@@ -51,23 +68,6 @@ class UI final : public core::IReferenceCounted
5168
core::smart_refctd_ptr<video::IGPUGraphicsPipeline> pipeline;
5269
core::smart_refctd_ptr<video::IGPUImageView> m_fontAtlasTexture;
5370

54-
struct MDI
55-
{
56-
using COMPOSE_T = nbl::video::StreamingTransientDataBufferST<nbl::core::allocator<uint8_t>>;
57-
58-
enum E_BUFFER_CONTENT : uint8_t
59-
{
60-
EBC_DRAW_INDIRECT_STRUCTURES,
61-
EBC_ELEMENT_STRUCTURES,
62-
EBC_INDEX_BUFFERS,
63-
EBC_VERTEX_BUFFERS,
64-
65-
EBC_COUNT,
66-
};
67-
68-
nbl::core::smart_refctd_ptr<typename COMPOSE_T> streamingTDBufferST; // composed buffer layout is [EBC_DRAW_INDIRECT_STRUCTURES] [EBC_ELEMENT_STRUCTURES] [EBC_INDEX_BUFFERS] [EBC_VERTEX_BUFFERS]
69-
};
70-
7171
MDI m_mdi;
7272

7373
// TODO: Use a signal class instead like Signal<> UIRecordSignal{};

src/nbl/ext/ImGui/ImGui.cpp

Lines changed: 57 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,7 @@ namespace nbl::ext::imgui
522522
}
523523
}
524524

525-
UI::UI(smart_refctd_ptr<ILogicalDevice> _device, core::smart_refctd_ptr<video::IGPUDescriptorSetLayout> _descriptorSetLayout, video::IGPURenderpass* renderpass, uint32_t subpassIx, IGPUPipelineCache* pipelineCache, uint32_t mdiTotalByteSize)
525+
UI::UI(smart_refctd_ptr<ILogicalDevice> _device, core::smart_refctd_ptr<video::IGPUDescriptorSetLayout> _descriptorSetLayout, video::IGPURenderpass* renderpass, uint32_t subpassIx, IGPUPipelineCache* pipelineCache, nbl::core::smart_refctd_ptr<typename MDI::COMPOSE_T> _streamingMDIBuffer)
526526
: m_device(core::smart_refctd_ptr(_device))
527527
{
528528
createSystem();
@@ -602,7 +602,7 @@ namespace nbl::ext::imgui
602602
}
603603
tQueue->endCapture();
604604

605-
createMDIBuffer(mdiTotalByteSize);
605+
createMDIBuffer(_streamingMDIBuffer);
606606

607607
auto & io = ImGui::GetIO();
608608
io.DisplayFramebufferScale = ImVec2(1.0f, 1.0f);
@@ -629,41 +629,71 @@ namespace nbl::ext::imgui
629629
}
630630
}
631631

632-
void UI::createMDIBuffer(const uint32_t totalByteSize)
632+
void UI::createMDIBuffer(nbl::core::smart_refctd_ptr<typename MDI::COMPOSE_T> _streamingMDIBuffer)
633633
{
634-
constexpr static core::bitflag<IDeviceMemoryAllocation::E_MEMORY_ALLOCATE_FLAGS> allocateFlags(IDeviceMemoryAllocation::EMAF_DEVICE_ADDRESS_BIT);
635-
constexpr static uint32_t minStreamingBufferAllocationSize = 4u,
636-
maxStreamingBufferAllocationAlignment = 1024u * 64u;
634+
constexpr static uint32_t minStreamingBufferAllocationSize = 4u, maxStreamingBufferAllocationAlignment = 1024u * 64u, mdiBufferDefaultSize = /* 2MB */ 1024u * 1024u * 2u;
635+
constexpr static auto requiredAllocateFlags = core::bitflag<IDeviceMemoryAllocation::E_MEMORY_ALLOCATE_FLAGS>(IDeviceMemoryAllocation::EMAF_DEVICE_ADDRESS_BIT);
636+
constexpr static auto requiredUsageFlags = nbl::core::bitflag(nbl::asset::IBuffer::EUF_INDIRECT_BUFFER_BIT) | nbl::asset::IBuffer::EUF_INDEX_BUFFER_BIT | nbl::asset::IBuffer::EUF_VERTEX_BUFFER_BIT | nbl::asset::IBuffer::EUF_SHADER_DEVICE_ADDRESS_BIT | nbl::asset::IBuffer::EUF_INLINE_UPDATE_VIA_CMDBUF;
637637

638-
IGPUBuffer::SCreationParams mdiCreationParams = {};
639-
mdiCreationParams.usage = nbl::core::bitflag(nbl::asset::IBuffer::EUF_INDIRECT_BUFFER_BIT) | nbl::asset::IBuffer::EUF_INDEX_BUFFER_BIT | nbl::asset::IBuffer::EUF_VERTEX_BUFFER_BIT | nbl::asset::IBuffer::EUF_SHADER_DEVICE_ADDRESS_BIT | nbl::asset::IBuffer::EUF_INLINE_UPDATE_VIA_CMDBUF;
640-
mdiCreationParams.size = totalByteSize;
638+
auto getRequiredAccessFlags = [&](const core::bitflag<video::IDeviceMemoryAllocation::E_MEMORY_PROPERTY_FLAGS>& properties)
639+
{
640+
core::bitflag<IDeviceMemoryAllocation::E_MAPPING_CPU_ACCESS_FLAGS> flags (IDeviceMemoryAllocation::EMCAF_NO_MAPPING_ACCESS);
641+
642+
if (properties.hasFlags(IDeviceMemoryAllocation::EMPF_HOST_READABLE_BIT))
643+
flags |= IDeviceMemoryAllocation::EMCAF_READ;
644+
if (properties.hasFlags(IDeviceMemoryAllocation::EMPF_HOST_WRITABLE_BIT))
645+
flags |= IDeviceMemoryAllocation::EMCAF_WRITE;
641646

642-
auto buffer = m_device->createBuffer(std::move(mdiCreationParams));
647+
return flags;
648+
};
643649

644-
auto memoryReqs = buffer->getMemoryReqs();
645-
memoryReqs.memoryTypeBits &= m_device->getPhysicalDevice()->getUpStreamingMemoryTypeBits();
650+
if (_streamingMDIBuffer)
651+
m_mdi.streamingTDBufferST = core::smart_refctd_ptr(_streamingMDIBuffer);
652+
else
653+
{
654+
IGPUBuffer::SCreationParams mdiCreationParams = {};
655+
mdiCreationParams.usage = requiredUsageFlags;
656+
mdiCreationParams.size = mdiBufferDefaultSize;
646657

647-
auto offset = m_device->allocate(memoryReqs, buffer.get(), allocateFlags);
648-
auto memory = offset.memory;
649-
const bool allocated = offset.isValid();
650-
assert(allocated);
658+
auto buffer = m_device->createBuffer(std::move(mdiCreationParams));
659+
660+
auto memoryReqs = buffer->getMemoryReqs();
661+
memoryReqs.memoryTypeBits &= m_device->getPhysicalDevice()->getUpStreamingMemoryTypeBits();
662+
663+
auto allocation = m_device->allocate(memoryReqs, buffer.get(), requiredAllocateFlags);
664+
{
665+
const bool allocated = allocation.isValid();
666+
assert(allocated);
667+
}
668+
auto memory = allocation.memory;
651669

652-
const auto properties = memory->getMemoryPropertyFlags();
670+
if (!memory->map({ 0ull, memoryReqs.size }, getRequiredAccessFlags(memory->getMemoryPropertyFlags())))
671+
logger->log("Could not map device memory!", system::ILogger::ELL_ERROR);
653672

654-
core::bitflag<IDeviceMemoryAllocation::E_MAPPING_CPU_ACCESS_FLAGS> accessFlags(IDeviceMemoryAllocation::EMCAF_NO_MAPPING_ACCESS);
655-
if (properties.hasFlags(IDeviceMemoryAllocation::EMPF_HOST_READABLE_BIT))
656-
accessFlags |= IDeviceMemoryAllocation::EMCAF_READ;
657-
if (properties.hasFlags(IDeviceMemoryAllocation::EMPF_HOST_WRITABLE_BIT))
658-
accessFlags |= IDeviceMemoryAllocation::EMCAF_WRITE;
673+
m_mdi.streamingTDBufferST = core::make_smart_refctd_ptr<MDI::COMPOSE_T>(asset::SBufferRange<video::IGPUBuffer>{0ull, mdiCreationParams.size, std::move(buffer)}, maxStreamingBufferAllocationAlignment, minStreamingBufferAllocationSize);
674+
m_mdi.streamingTDBufferST->getBuffer()->setObjectDebugName("MDI Upstream Buffer");
675+
}
659676

660-
assert(accessFlags.value);
677+
auto buffer = m_mdi.streamingTDBufferST->getBuffer();
678+
auto binding = buffer->getBoundMemory();
661679

662-
if (!memory->map({ 0ull, memoryReqs.size }, accessFlags))
663-
logger->log("Could not map device memory!", system::ILogger::ELL_ERROR);
680+
const auto validation = std::to_array
681+
({
682+
std::make_pair(buffer->getCreationParams().usage.hasFlags(requiredUsageFlags), "MDI buffer must be created with IBuffer::EUF_INDIRECT_BUFFER_BIT | IBuffer::EUF_INDEX_BUFFER_BIT | IBuffer::EUF_VERTEX_BUFFER_BIT | IBuffer::EUF_SHADER_DEVICE_ADDRESS_BIT | IBuffer::EUF_INLINE_UPDATE_VIA_CMDBUF enabled!"),
683+
std::make_pair(bool(buffer->getMemoryReqs().memoryTypeBits & m_device->getPhysicalDevice()->getUpStreamingMemoryTypeBits()), "MDI buffer must have up-streaming memory type bits enabled!"),
684+
std::make_pair(binding.memory->getAllocateFlags().hasFlags(requiredAllocateFlags), "MDI buffer's memory must be allocated with IDeviceMemoryAllocation::EMAF_DEVICE_ADDRESS_BIT enabled!"),
685+
std::make_pair(binding.memory->isCurrentlyMapped(), "MDI buffer's memory must be mapped!"), // streaming buffer contructor already validates it, but cannot assume user won't unmap its own buffer for some reason (sorry if you have just hit it)
686+
std::make_pair(binding.memory->getCurrentMappingAccess().hasFlags(getRequiredAccessFlags(binding.memory->getMemoryPropertyFlags())), "MDI buffer's memory current mapping access flags don't meet requirements!")
687+
});
664688

665-
m_mdi.streamingTDBufferST = core::make_smart_refctd_ptr<MDI::COMPOSE_T>(asset::SBufferRange<video::IGPUBuffer>{0ull, totalByteSize, std::move(buffer)}, maxStreamingBufferAllocationAlignment, minStreamingBufferAllocationSize);
666-
m_mdi.streamingTDBufferST->getBuffer()->setObjectDebugName("MDI Upstream Buffer");
689+
for (const auto& [ok, error] : validation)
690+
{
691+
if (!ok)
692+
{
693+
logger->log(error, system::ILogger::ELL_ERROR);
694+
assert(false);
695+
}
696+
}
667697
}
668698

669699
bool UI::render(SIntendedSubmitInfo& info, const IGPUDescriptorSet* const descriptorSet)

0 commit comments

Comments
 (0)