Skip to content

Commit 7f0e299

Browse files
committed
Merge branch 'gpgpuimgui' of github.com:Devsh-Graphics-Programming/Nabla into compute_ptr_2
2 parents 6f092a0 + 8604014 commit 7f0e299

File tree

11 files changed

+588
-389
lines changed

11 files changed

+588
-389
lines changed

3rdparty/CMakeLists.txt

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,62 @@ string(APPEND NBL_IMPL_IMCONFIG_CONTENT
384384
385385
// note we override it with default imguis (void*) type
386386
#include <cstdint>
387-
#define ImTextureID uint32_t
387+
388+
//! Custom "ImTextureID" info struct for Nabla UI backend purposes about resource sampler & texture descriptor binding's array indicies
389+
//! must be 4 bytes size & alignment to pass imgui static asserts (it checks for contiguous blocks in memory to make sure it can do some memcpies)
390+
struct SImResourceInfo
391+
{
392+
//! texture descriptor binding's array index
393+
uint32_t textureID : 26;
394+
395+
//! sampler descriptor binding's array index
396+
uint32_t samplerIx : 6;
397+
398+
SImResourceInfo() : textureID(0u), samplerIx(0u) {}
399+
400+
SImResourceInfo(uint32_t texID)
401+
{
402+
textureID = texID;
403+
samplerIx = 0u;
404+
}
405+
406+
explicit operator intptr_t() const
407+
{
408+
return static_cast<intptr_t>(textureID);
409+
}
410+
411+
bool operator==(const SImResourceInfo& other) const
412+
{
413+
return textureID == other.textureID;
414+
}
415+
416+
bool operator!=(const SImResourceInfo& other) const
417+
{
418+
return textureID != other.textureID;
419+
}
420+
421+
bool operator<(const SImResourceInfo& other) const
422+
{
423+
return textureID < other.textureID;
424+
}
425+
426+
bool operator>(const SImResourceInfo& other) const
427+
{
428+
return textureID > other.textureID;
429+
}
430+
431+
bool operator<=(const SImResourceInfo& other) const
432+
{
433+
return textureID <= other.textureID;
434+
}
435+
436+
bool operator>=(const SImResourceInfo& other) const
437+
{
438+
return textureID >= other.textureID;
439+
}
440+
};
441+
442+
#define ImTextureID SImResourceInfo
388443
#define IMGUI_ENABLE_FREETYPE
389444
#define IMGUI_DISABLE_OBSOLETE_KEYIO
390445
#undef IMGUI_DISABLE_OBSOLETE_FUNCTIONS // but remove this cuz it break things

include/nbl/ext/ImGui/ImGui.h

Lines changed: 127 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -9,124 +9,184 @@ namespace nbl::ext::imgui
99
class UI final : public core::IReferenceCounted
1010
{
1111
public:
12-
struct MDI
12+
//! Reserved font atlas indicies for default backend textures & samplers descriptor binding's array
13+
static constexpr auto FontAtlasTexId = 0u, FontAtlasSamplerId = 0u;
14+
15+
//! Reserved indexes for default backend samplers descriptor binding's array - use only if you created your pipeline layout with createDefaultPipelineLayout. If you need more or custom samplers then create the pipeline layout yourself
16+
enum class DefaultSamplerIx : uint16_t
17+
{
18+
FONT_ATLAS = FontAtlasSamplerId,
19+
USER,
20+
21+
COUNT,
22+
};
23+
24+
struct SMdiBuffer
1325
{
14-
using COMPOSE_T = nbl::video::StreamingTransientDataBufferST<nbl::core::allocator<uint8_t>>; //! composes memory available for the general purpose allocator to suballocate memory ranges
15-
using SUBALLOCATOR_TRAITS_T = nbl::core::address_allocator_traits<nbl::core::LinearAddressAllocatorST<uint32_t>>; //! traits for MDI buffer suballocator - fills the data given the mdi allocator memory request
26+
//! composes memory available for the general purpose allocator to suballocate memory ranges
27+
using compose_t = video::StreamingTransientDataBufferST<core::allocator<uint8_t>>;
1628

17-
enum E_BUFFER_CONTENT : uint8_t
29+
//! traits for MDI buffer suballocator - fills the data given the mdi allocator memory request
30+
using suballocator_traits_t = core::address_allocator_traits<core::LinearAddressAllocatorST<uint32_t>>;
31+
32+
enum class Content : uint16_t
1833
{
19-
EBC_DRAW_INDIRECT_STRUCTURES,
20-
EBC_ELEMENT_STRUCTURES,
21-
EBC_INDEX_BUFFERS,
22-
EBC_VERTEX_BUFFERS,
34+
INDIRECT_STRUCTURES,
35+
ELEMENT_STRUCTURES,
36+
INDEX_BUFFERS,
37+
VERTEX_BUFFERS,
2338

24-
EBC_COUNT,
39+
COUNT,
2540
};
2641

27-
nbl::core::smart_refctd_ptr<typename COMPOSE_T> buffer; //! streaming mdi buffer
42+
//! streaming mdi buffer
43+
core::smart_refctd_ptr<typename compose_t> compose;
44+
45+
//! required buffer allocate flags
46+
static constexpr auto RequiredAllocateFlags = core::bitflag<video::IDeviceMemoryAllocation::E_MEMORY_ALLOCATE_FLAGS>(video::IDeviceMemoryAllocation::EMAF_DEVICE_ADDRESS_BIT);
2847

29-
static constexpr auto MDI_BUFFER_REQUIRED_ALLOCATE_FLAGS = nbl::core::bitflag<nbl::video::IDeviceMemoryAllocation::E_MEMORY_ALLOCATE_FLAGS>(nbl::video::IDeviceMemoryAllocation::EMAF_DEVICE_ADDRESS_BIT); //! required flags
30-
static constexpr auto MDI_BUFFER_REQUIRED_USAGE_FLAGS = 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; //! required flags
48+
//! required buffer usage flags
49+
static constexpr auto RequiredUsageFlags = core::bitflag(asset::IBuffer::EUF_INDIRECT_BUFFER_BIT) | asset::IBuffer::EUF_INDEX_BUFFER_BIT | asset::IBuffer::EUF_VERTEX_BUFFER_BIT | asset::IBuffer::EUF_SHADER_DEVICE_ADDRESS_BIT;
3150
};
3251

33-
struct S_CREATION_PARAMETERS
52+
struct SResourceParameters
3453
{
35-
struct S_RESOURCE_PARAMETERS
54+
//! for a given pipeline layout we need to know what is intended for UI resources
55+
struct SBindingInfo
3656
{
37-
nbl::video::IGPUPipelineLayout* const pipelineLayout = nullptr; //! optional, default layout used if not provided declaring required UI resources such as textures (required font atlas + optional user defined textures) & corresponding samplers
38-
uint32_t count = 0x45u; //! amount of total UI textures (and corresponding samplers)
39-
40-
struct S_BINDING_REQUEST_INFO //! for a given pipeline layout we need to know what is intended for UI resources
41-
{
42-
uint32_t setIx, //! descriptor set index for a resource
43-
bindingIx; //! binding index for a given resource
44-
};
45-
46-
const S_BINDING_REQUEST_INFO textures = { .setIx = 0u, .bindingIx = 0u }, //! optional, default texture binding request info used if not provided (set & binding index)
47-
samplers = { .setIx = 0u, .bindingIx = 1u }; //! optional, default sampler binding request info used if not provided (set & binding index)
48-
49-
using binding_flags_t = nbl::video::IGPUDescriptorSetLayout::SBinding::E_CREATE_FLAGS;
50-
static constexpr auto TEXTURES_REQUIRED_CREATE_FLAGS = nbl::core::bitflag(binding_flags_t::ECF_UPDATE_AFTER_BIND_BIT) | binding_flags_t::ECF_PARTIALLY_BOUND_BIT | binding_flags_t::ECF_UPDATE_UNUSED_WHILE_PENDING_BIT; //! required flags
51-
static constexpr auto SAMPLERS_REQUIRED_CREATE_FLAGS = nbl::core::bitflag(binding_flags_t::ECF_NONE); //! required flags
52-
static constexpr auto RESOURCES_REQUIRED_STAGE_FLAGS = nbl::asset::IShader::E_SHADER_STAGE::ESS_FRAGMENT; //! required stage
57+
//! descriptor set index for a resource
58+
uint32_t setIx,
59+
60+
//! binding index for a given resource
61+
bindingIx;
5362
};
5463

55-
nbl::asset::IAssetManager* const assetManager; //! required
56-
nbl::video::IUtilities* const utilities; //! required
57-
nbl::video::IQueue* const transfer; //! required
58-
nbl::video::IGPURenderpass* const renderpass; //! required
59-
uint32_t subpassIx = 0u; //! optional, default value used if not provided
60-
S_RESOURCE_PARAMETERS resources; //! optional, default parameters used if not provided
61-
nbl::video::IGPUPipelineCache* const pipelineCache = nullptr; //! optional, no cache used if not provided
62-
typename MDI::COMPOSE_T* const streamingBuffer = nullptr; //! optional, default MDI buffer allocated if not provided
64+
using binding_flags_t = video::IGPUDescriptorSetLayout::SBinding::E_CREATE_FLAGS;
65+
66+
//! required textures binding creation flags
67+
static constexpr auto TexturesRequiredCreateFlags = core::bitflag(binding_flags_t::ECF_UPDATE_AFTER_BIND_BIT) | binding_flags_t::ECF_PARTIALLY_BOUND_BIT | binding_flags_t::ECF_UPDATE_UNUSED_WHILE_PENDING_BIT;
68+
69+
//! required samplers binding creation flags
70+
static constexpr auto SamplersRequiredCreateFlags = core::bitflag(binding_flags_t::ECF_UPDATE_AFTER_BIND_BIT);
71+
72+
//! required shader stage flags
73+
static constexpr auto RequiredShaderStageFlags = asset::IShader::E_SHADER_STAGE::ESS_FRAGMENT;
74+
75+
//! required, fill the info to instruct the backend about the required UI resources
76+
SBindingInfo texturesInfo, samplersInfo;
77+
78+
private:
79+
uint32_t texturesCount = {}, samplersCount = {};
80+
81+
friend class UI;
82+
};
83+
84+
struct SCachedCreationParams
85+
{
86+
//! required, you provide us information about your required UI binding resources which we validate at creation time
87+
SResourceParameters resources;
88+
89+
//! required
90+
core::smart_refctd_ptr<video::IUtilities> utilities;
91+
92+
//! optional, default MDI buffer allocated if not provided
93+
core::smart_refctd_ptr<typename SMdiBuffer::compose_t> streamingBuffer = nullptr;
94+
95+
//! optional, default single one
96+
uint32_t viewportCount = 1u;
97+
};
98+
99+
struct SCreationParameters : public SCachedCreationParams
100+
{
101+
//! required
102+
video::IQueue* transfer = nullptr;
103+
104+
//! required, must declare required UI resources such as textures (required font atlas + optional user defined textures) & samplers
105+
core::smart_refctd_ptr<video::IGPUPipelineLayout> pipelineLayout;
106+
107+
//! required
108+
core::smart_refctd_ptr<asset::IAssetManager> assetManager = nullptr;
109+
110+
//! required
111+
core::smart_refctd_ptr<video::IGPURenderpass> renderpass = nullptr;
112+
113+
//! optional, default value used if not provided
114+
uint32_t subpassIx = 0u;
115+
116+
//! optional, no cache used if not provided
117+
core::smart_refctd_ptr<video::IGPUPipelineCache> pipelineCache = nullptr;
63118
};
64119

65120
//! parameters which may change every frame, used with the .update call to interact with ImGuiIO; we require a very *required* minimum - if you need to cover more IO options simply get the IO with ImGui::GetIO() to customize them (they all have default values you can change before calling the .update)
66-
struct S_UPDATE_PARAMETERS
121+
struct SUpdateParameters
67122
{
68123
//! what we pass to ImGuiIO::AddMousePosEvent
69-
nbl::hlsl::float32_t2 mousePosition,
124+
hlsl::float32_t2 mousePosition,
70125

71126
//! main display size in pixels
72127
displaySize;
73128

74-
//! Nabla events you want to be handled with the backend
75-
struct S_EVENTS
76-
{
77-
core::SRange<const nbl::ui::SMouseEvent> mouse;
78-
core::SRange<const nbl::ui::SKeyboardEvent> keyboard;
79-
};
129+
//! Nabla mouse events you want to be handled with the backend
130+
std::span<const ui::SMouseEvent> mouseEvents = {};
80131

81-
S_EVENTS events;
132+
//! Nabla keyboard events you want to be handled with the backend
133+
std::span<const ui::SKeyboardEvent> keyboardEvents = {};
82134
};
83135

84-
UI(S_CREATION_PARAMETERS&& params);
136+
UI(SCreationParameters&& params);
85137
~UI() override;
86138

87-
//! Nabla ImGUI backend reserves this index for font atlas, any attempt to hook user defined texture within the index will result in undefined behaviour
88-
static constexpr auto NBL_FONT_ATLAS_TEX_ID = 0u;
89-
90139
//! updates ImGuiIO & records ImGUI *cpu* draw command lists, you have to call it before .render
91-
bool update(const S_UPDATE_PARAMETERS& params);
140+
bool update(const SUpdateParameters& params);
92141

93142
//! updates mapped mdi buffer & records *gpu* draw command, you are required to bind UI's graphics pipeline & descriptor sets before calling this function - use getPipeline() to get the pipeline & getCreationParameters() to get info about your set resources
94-
bool render(nbl::video::IGPUCommandBuffer* const commandBuffer, nbl::video::ISemaphore::SWaitInfo waitInfo, const std::span<const VkRect2D> scissors = {});
143+
bool render(video::IGPUCommandBuffer* const commandBuffer, video::ISemaphore::SWaitInfo waitInfo, const std::span<const VkRect2D> scissors = {});
95144

96-
//! registers lambda listener in which ImGUI calls should be recorded
145+
//! registers lambda listener in which ImGUI calls should be recorded, use the returned id to unregister the listener
97146
size_t registerListener(std::function<void()> const& listener);
147+
148+
//! unregisters listener with the given id
98149
std::optional<size_t> unregisterListener(size_t id);
99150

100151
//! sets ImGUI context, you are supposed to pass valid ImGuiContext* context
101152
void setContext(void* imguiContext);
102153

103-
//! creation parametrs
104-
inline const S_CREATION_PARAMETERS& getCreationParameters() const { return m_creationParams; }
154+
//! creates default pipeline layout for the UI resources, "texturesCount" argument is textures descriptor binding's array size. Samplers are immutable and part of the created layout, SResourceParameters::DefaultSamplerIx::COUNT is the size of the samplers descriptor binding's array
155+
static core::smart_refctd_ptr<video::IGPUPipelineLayout> createDefaultPipelineLayout(video::IUtilities* const utilities, const SResourceParameters::SBindingInfo texturesInfo, const SResourceParameters::SBindingInfo samplersInfo, uint32_t texturesCount = 0x45);
156+
157+
//! mounts the extension's archive to given system - useful if you want to create your own shaders with common header included
158+
static const core::smart_refctd_ptr<system::IFileArchive> mount(core::smart_refctd_ptr<system::ILogger> logger, system::ISystem* system, const std::string_view archiveAlias = "");
159+
160+
//! creation cached parametrs
161+
inline const SCachedCreationParams& getCreationParameters() const { return m_cachedCreationParams; }
105162

106163
//! ImGUI graphics pipeline
107-
inline nbl::video::IGPUGraphicsPipeline* getPipeline() { return pipeline.get(); }
164+
inline const video::IGPUGraphicsPipeline* getPipeline() const { return m_pipeline.get(); }
108165

109166
//! image view default font texture
110-
inline nbl::video::IGPUImageView* getFontAtlasView() { return m_fontAtlasTexture.get(); }
167+
//! TODO: we cannot expose immutable view of our default font texture because user MUST be able to write a descriptor,
168+
//! we can have mutable getter or we can decide to not create any default font texture at all and force users
169+
//! to do it externally (have a static helper to do it which gives you mutable view)
170+
inline video::IGPUImageView* getFontAtlasView() const { return m_fontAtlasTexture.get(); }
111171

112172
//! mdi streaming buffer
113-
inline typename MDI::COMPOSE_T* getStreamingBuffer() { return m_mdi.buffer.get(); }
173+
inline const typename SMdiBuffer::compose_t* getStreamingBuffer() const { return m_mdi.compose.get(); }
114174

115175
//! ImGUI context, you are supposed to cast it, eg. reinterpret_cast<ImGuiContext*>(this->getContext());
116176
void* getContext();
117177
private:
118-
void createPipeline();
119-
void createMDIBuffer();
120-
void handleMouseEvents(const S_UPDATE_PARAMETERS& params) const;
121-
void handleKeyEvents(const S_UPDATE_PARAMETERS& params) const;
122-
video::ISemaphore::future_t<video::IQueue::RESULT> createFontAtlasTexture(video::IGPUCommandBuffer* cmdBuffer);
178+
void createPipeline(SCreationParameters& creationParams);
179+
void createMDIBuffer(SCreationParameters& creationParams);
180+
void handleMouseEvents(const SUpdateParameters& params) const;
181+
void handleKeyEvents(const SUpdateParameters& params) const;
182+
video::ISemaphore::future_t<video::IQueue::RESULT> createFontAtlasTexture(video::IGPUCommandBuffer* cmdBuffer, SCreationParameters& creationParams);
123183

124-
S_CREATION_PARAMETERS m_creationParams;
184+
SCachedCreationParams m_cachedCreationParams;
125185

126-
core::smart_refctd_ptr<video::IGPUGraphicsPipeline> pipeline;
186+
core::smart_refctd_ptr<video::IGPUGraphicsPipeline> m_pipeline;
127187
core::smart_refctd_ptr<video::IGPUImageView> m_fontAtlasTexture;
128188

129-
MDI m_mdi;
189+
SMdiBuffer m_mdi;
130190
std::vector<std::function<void()>> m_subscribers {};
131191
};
132192
}

include/nbl/system/ISystem.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ class NBL_API2 ISystem : public core::IReferenceCounted
146146
}
147147

148148
void unmountBuiltins();
149+
bool areBuiltinsMounted() const;
149150

150151
//
151152
struct SystemInfo

src/nbl/ext/ImGui/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ get_filename_component(_OUTPUT_DIRECTORY_SOURCE_ "${CMAKE_CURRENT_BINARY_DIR}/sr
3232
get_filename_component(_OUTPUT_DIRECTORY_HEADER_ "${CMAKE_CURRENT_BINARY_DIR}/include" ABSOLUTE)
3333

3434
LIST_BUILTIN_RESOURCE(RESOURCES_TO_EMBED "common.hlsl")
35+
LIST_BUILTIN_RESOURCE(RESOURCES_TO_EMBED "psinput.hlsl")
3536
LIST_BUILTIN_RESOURCE(RESOURCES_TO_EMBED "vertex.hlsl") # (*) -> this we could precompile [no resources for which set/binding Ixs could be adjusted] but I'm not going to mix stuff
3637
LIST_BUILTIN_RESOURCE(RESOURCES_TO_EMBED "fragment.hlsl") # (*) -> but this we could not since we let users to provide external descriptor set layout + ImGUI textures & sampler state set/binding Ixs (for pipeline layout) at runtime
3738

0 commit comments

Comments
 (0)