Skip to content

Commit 4b8990b

Browse files
committed
sort out how we handle window in ImGUI backend - it's really only needed at update stage, should never be kept & passed with constructor. Let user pass subpassIx while creating the UI for internal pipeline creation purposes, update examples_tests submodule, clean some code & add comments
1 parent 5be870d commit 4b8990b

File tree

6 files changed

+46
-36
lines changed

6 files changed

+46
-36
lines changed

examples_tests

include/nbl/ext/ImGui/ImGui.h

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,35 +5,42 @@
55

66
namespace nbl::ext::imgui
77
{
8-
98
class UI final : public core::IReferenceCounted
109
{
1110
public:
12-
// Nabla IMGUI backend reserves this index for font atlas, any attempt to hook user defined texture within the index will cause runtime error
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 */);
12+
~UI() override;
13+
14+
//! 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]
1315
_NBL_STATIC_INLINE_CONSTEXPR auto NBL_FONT_ATLAS_TEX_ID = 0u;
1416

15-
UI(core::smart_refctd_ptr<video::ILogicalDevice> _device, core::smart_refctd_ptr<video::IGPUDescriptorSetLayout> _descriptorSetLayout, video::IGPURenderpass* renderpass, video::IGPUPipelineCache* pipelineCache, core::smart_refctd_ptr<ui::IWindow> window);
16-
~UI() override;
17+
//! update ImGUI internal state & cpu draw command lists, call it before this->render
18+
bool update(const ui::IWindow* window, float deltaTimeInSec, const core::SRange<const nbl::ui::SMouseEvent> mouseEvents, const core::SRange<const nbl::ui::SKeyboardEvent> keyboardEvents);
1719

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?]
1821
bool render(nbl::video::SIntendedSubmitInfo& info, const nbl::video::IGPUDescriptorSet* const descriptorSet);
19-
void update(float deltaTimeInSec, const nbl::hlsl::float32_t2 mousePosition, const core::SRange<const nbl::ui::SMouseEvent> mouseEvents, const core::SRange<const nbl::ui::SKeyboardEvent> keyboardEvents);
22+
23+
//! registers lambda listener in which ImGUI calls should be recorded
2024
int registerListener(std::function<void()> const& listener);
2125
bool unregisterListener(uint32_t id);
26+
27+
//! sets ImGUI context, you are supposed to pass valid ImGuiContext* context
2228
void setContext(void* imguiContext);
2329

24-
inline nbl::core::smart_refctd_ptr<nbl::video::IGPUImageView> getFontAtlasView() { return m_fontAtlasTexture; }
30+
//! image view getter to access default font texture
31+
inline auto getFontAtlasView() -> decltype(auto) { return core::smart_refctd_ptr(m_fontAtlasTexture); }
32+
33+
//! mdi streaming buffer getter
2534
inline auto getStreamingBuffer() -> decltype(auto) { return (std::as_const(m_mdi.streamingTDBufferST)); }
26-
void* getContext();
2735

36+
//! ImGUI context getter, you are supposed to cast it, eg. reinterpret_cast<ImGuiContext*>(this->getContext());
37+
void* getContext();
2838
private:
29-
void createPipeline(core::smart_refctd_ptr<video::IGPUDescriptorSetLayout> descriptorSetLayout, video::IGPURenderpass* renderpass, video::IGPUPipelineCache* pipelineCache);
30-
31-
// TODO: just take an intended next submit instead of queue and cmdbuf, so we're consistent across utilities
32-
39+
void createSystem();
40+
void createPipeline(core::smart_refctd_ptr<video::IGPUDescriptorSetLayout> descriptorSetLayout, video::IGPURenderpass* renderpass, uint32_t subpassIx, video::IGPUPipelineCache* pipelineCache);
3341
void createMDIBuffer(const uint32_t totalByteSize);
3442
video::ISemaphore::future_t<video::IQueue::RESULT> createFontAtlasTexture(video::IGPUCommandBuffer* cmdBuffer, video::IQueue* queue);
35-
void createSystem();
36-
void handleMouseEvents(const nbl::hlsl::float32_t2& mousePosition, const core::SRange<const nbl::ui::SMouseEvent>& events) const;
43+
void handleMouseEvents(const core::SRange<const nbl::ui::SMouseEvent>& events, const ui::IWindow* window) const;
3744
void handleKeyEvents(const core::SRange<const nbl::ui::SKeyboardEvent>& events) const;
3845

3946
core::smart_refctd_ptr<system::ISystem> system;
@@ -43,7 +50,6 @@ class UI final : public core::IReferenceCounted
4350

4451
core::smart_refctd_ptr<video::IGPUGraphicsPipeline> pipeline;
4552
core::smart_refctd_ptr<video::IGPUImageView> m_fontAtlasTexture;
46-
core::smart_refctd_ptr<ui::IWindow> m_window;
4753

4854
struct MDI
4955
{
@@ -71,7 +77,6 @@ class UI final : public core::IReferenceCounted
7177
std::function<void()> listener = nullptr;
7278
};
7379
std::vector<Subscriber> m_subscribers{};
74-
7580
};
7681
}
7782

include/nbl/ui/IWindow.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ class IWindow : public core::IReferenceCounted
194194
inline int32_t getY() const { return m_y; }
195195

196196
NBL_API2 virtual IClipboardManager* getClipboardManager() = 0;
197-
NBL_API2 virtual ICursorControl* getCursorControl() = 0;
197+
NBL_API2 virtual ICursorControl* getCursorControl() const = 0;
198198
NBL_API2 virtual IWindowManager* getManager() const = 0;
199199

200200
inline IEventCallback* getEventCallback() const { return m_cb.get(); }

src/nbl/ext/ImGui/ImGui.cpp

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#include <utility>
66

77
#include "nbl/system/IApplicationFramework.h"
8+
#include "nbl/ui/IWindow.h"
9+
#include "nbl/ui/ICursorControl.h"
810
#include "nbl/system/CStdoutLogger.h"
911
#include "nbl/ext/ImGui/ImGui.h"
1012
#include "shaders/common.hlsl"
@@ -21,7 +23,7 @@ using namespace nbl::ui;
2123

2224
namespace nbl::ext::imgui
2325
{
24-
void UI::createPipeline(core::smart_refctd_ptr<video::IGPUDescriptorSetLayout> descriptorSetLayout, video::IGPURenderpass* renderpass, IGPUPipelineCache* pipelineCache)
26+
void UI::createPipeline(core::smart_refctd_ptr<video::IGPUDescriptorSetLayout> descriptorSetLayout, video::IGPURenderpass* renderpass, uint32_t subpassIx, IGPUPipelineCache* pipelineCache)
2527
{
2628
// Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 3d projection matrix
2729
SPushConstantRange pushConstantRanges[] =
@@ -128,7 +130,7 @@ namespace nbl::ext::imgui
128130
param.layout = pipelineLayout.get();
129131
param.shaders = specs;
130132
param.renderpass = renderpass;
131-
param.cached = { .vertexInput = vertexInputParams, .primitiveAssembly = primitiveAssemblyParams, .rasterization = rasterizationParams, .blend = blendParams, .subpassIx = 0u }; // TODO: check "subpassIx"
133+
param.cached = { .vertexInput = vertexInputParams, .primitiveAssembly = primitiveAssemblyParams, .rasterization = rasterizationParams, .blend = blendParams, .subpassIx = subpassIx };
132134
};
133135

134136
if (!m_device->createGraphicsPipelines(pipelineCache, params, &pipeline))
@@ -309,13 +311,14 @@ namespace nbl::ext::imgui
309311
io.FontGlobalScale = 1.0f;
310312
}
311313

312-
void UI::handleMouseEvents(const nbl::hlsl::float32_t2& mousePosition, const core::SRange<const nbl::ui::SMouseEvent>& events) const
314+
void UI::handleMouseEvents(const core::SRange<const nbl::ui::SMouseEvent>& events, const ui::IWindow* window) const
313315
{
314316
auto& io = ImGui::GetIO();
315317

316-
const auto position = mousePosition - nbl::hlsl::float32_t2(m_window->getX(), m_window->getY());
318+
const auto cursorPosition = window->getCursorControl()->getPosition();
319+
const auto mousePixelPosition = nbl::hlsl::float32_t2(cursorPosition.x, cursorPosition.y) - nbl::hlsl::float32_t2(window->getX(), window->getY());
317320

318-
io.AddMousePosEvent(position.x, position.y);
321+
io.AddMousePosEvent(mousePixelPosition.x, mousePixelPosition.y);
319322

320323
for (const auto& e : events)
321324
{
@@ -519,8 +522,8 @@ namespace nbl::ext::imgui
519522
}
520523
}
521524

522-
UI::UI(smart_refctd_ptr<ILogicalDevice> _device, core::smart_refctd_ptr<video::IGPUDescriptorSetLayout> _descriptorSetLayout, video::IGPURenderpass* renderpass, IGPUPipelineCache* pipelineCache, smart_refctd_ptr<IWindow> window)
523-
: m_device(core::smart_refctd_ptr(_device)), m_window(core::smart_refctd_ptr(window))
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)
526+
: m_device(core::smart_refctd_ptr(_device))
524527
{
525528
createSystem();
526529
struct
@@ -571,7 +574,7 @@ namespace nbl::ext::imgui
571574
smart_refctd_ptr<nbl::video::IGPUCommandBuffer> transistentCMD;
572575
{
573576
using pool_flags_t = IGPUCommandPool::CREATE_FLAGS;
574-
// need to be individually resettable such that we can form a valid SIntendedSubmit out of the commandbuffer allocated from the pool
577+
575578
smart_refctd_ptr<nbl::video::IGPUCommandPool> pool = m_device->createCommandPool(families.id.transfer, pool_flags_t::RESET_COMMAND_BUFFER_BIT|pool_flags_t::TRANSIENT_BIT);
576579
if (!pool)
577580
{
@@ -593,17 +596,15 @@ namespace nbl::ext::imgui
593596
IMGUI_CHECKVERSION();
594597
ImGui::CreateContext();
595598

596-
createPipeline(core::smart_refctd_ptr(_descriptorSetLayout), renderpass, pipelineCache);
599+
createPipeline(core::smart_refctd_ptr(_descriptorSetLayout), renderpass, subpassIx, pipelineCache);
597600
createFontAtlasTexture(transistentCMD.get(), tQueue);
598601
adjustGlobalFontScale();
599602
}
600603
tQueue->endCapture();
601604

602-
static constexpr auto DEFAULT_MDI_SIZE = 1024u * 1024u * 2u; // 2 Mb
603-
createMDIBuffer(DEFAULT_MDI_SIZE);
605+
createMDIBuffer(mdiTotalByteSize);
604606

605607
auto & io = ImGui::GetIO();
606-
io.DisplaySize = ImVec2(m_window->getWidth(), m_window->getHeight());
607608
io.DisplayFramebufferScale = ImVec2(1.0f, 1.0f);
608609
io.BackendUsingLegacyKeyArrays = 0; // 0: using AddKeyEvent() [new way of handling events in imgui]
609610
}
@@ -931,7 +932,7 @@ namespace nbl::ext::imgui
931932
VkRect2D scissor[] = { {.offset = {(int32_t)viewport.x, (int32_t)viewport.y}, .extent = {(uint32_t)viewport.width, (uint32_t)viewport.height}} };
932933
commandBuffer->setScissor(scissor); // cover whole viewport (only to not throw validation errors)
933934
}
934-
935+
935936
/*
936937
Setup scale and translation, our visible imgui space lies from draw_data->DisplayPps (top left) to
937938
draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
@@ -976,14 +977,17 @@ namespace nbl::ext::imgui
976977
return true;
977978
}
978979

979-
void UI::update(float const deltaTimeInSec, const nbl::hlsl::float32_t2 mousePosition, const core::SRange<const nbl::ui::SMouseEvent> mouseEvents, const core::SRange<const nbl::ui::SKeyboardEvent> keyboardEvents)
980+
bool UI::update(const ui::IWindow* window, float const deltaTimeInSec, const core::SRange<const nbl::ui::SMouseEvent> mouseEvents, const core::SRange<const nbl::ui::SKeyboardEvent> keyboardEvents)
980981
{
982+
if (!window)
983+
return false;
984+
981985
auto & io = ImGui::GetIO();
982986

983987
io.DeltaTime = deltaTimeInSec;
984-
io.DisplaySize = ImVec2(m_window->getWidth(), m_window->getHeight());
988+
io.DisplaySize = ImVec2(window->getWidth(), window->getHeight());
985989

986-
handleMouseEvents(mousePosition, mouseEvents);
990+
handleMouseEvents(mouseEvents, window);
987991
handleKeyEvents(keyboardEvents);
988992

989993
ImGui::NewFrame();
@@ -992,6 +996,8 @@ namespace nbl::ext::imgui
992996
subscriber.listener();
993997

994998
ImGui::Render(); // note it doesn't touch GPU or graphics API at all, internal call for IMGUI cpu geometry buffers update
999+
1000+
return true;
9951001
}
9961002

9971003
int UI::registerListener(std::function<void()> const& listener)
@@ -1024,5 +1030,4 @@ namespace nbl::ext::imgui
10241030
{
10251031
ImGui::SetCurrentContext(reinterpret_cast<ImGuiContext*>(imguiContext));
10261032
}
1027-
10281033
}

src/nbl/ui/CWindowAndroid.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class CWindowAndroid : public IWindowAndroid
2323
}
2424

2525
virtual inline IClipboardManager* getClipboardManager() override { return nullptr; }
26-
virtual inline ICursorControl* getCursorControl() override { return nullptr; }
26+
virtual inline ICursorControl* getCursorControl() const override { return nullptr; }
2727

2828
inline const native_handle_t& getNativeHandle() const override { return m_native; }
2929

src/nbl/ui/CWindowWin32.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class NBL_API2 CWindowWin32 final : public IWindowWin32
3131
return m_clipboardManager.get();
3232
}
3333

34-
inline ICursorControl* getCursorControl() override {return m_windowManager.get();}
34+
inline ICursorControl* getCursorControl() const override {return m_windowManager.get();}
3535

3636
inline IWindowManager* getManager() const override {return m_windowManager.get();}
3737

0 commit comments

Comments
 (0)