From ca8612807ff4f025f9d923436c065699ec5a0002 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 1 Jul 2025 11:07:58 +0700 Subject: [PATCH 01/16] latest example --- examples_tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples_tests b/examples_tests index 5929be13ea..ac569917eb 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 5929be13ea1bfbb1d04bbe6a39321d519a3cbf92 +Subproject commit ac569917eb494b68e78133618bfc911bb04c3f47 From cd2ef9570b96b9184af85edb841a3d8ea5d2d068 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Fri, 4 Jul 2025 11:50:00 +0700 Subject: [PATCH 02/16] latest example --- examples_tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples_tests b/examples_tests index 00185f2822..da63edf598 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 00185f28224460b5de9fe1dcf6a2fa0176ab489a +Subproject commit da63edf598390448a2cb5835b61ecb38ec8393c4 From 98ccfb233f6056d6cf47d286446565594493c075 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 8 Jul 2025 15:44:23 +0700 Subject: [PATCH 03/16] added debug draw aabb extension, moved from ex --- examples_tests | 2 +- include/nbl/ext/DebugDraw/CDrawAABB.h | 84 ++++ .../builtin/hlsl/aabb_instances.fragment.hlsl | 13 + .../builtin/hlsl/aabb_instances.vertex.hlsl | 30 ++ .../ext/DebugDraw/builtin/hlsl/common.hlsl | 45 +++ src/nbl/ext/CMakeLists.txt | 13 + src/nbl/ext/DebugDraw/CDrawAABB.cpp | 360 ++++++++++++++++++ src/nbl/ext/DebugDraw/CMakeLists.txt | 42 ++ 8 files changed, 588 insertions(+), 1 deletion(-) create mode 100644 include/nbl/ext/DebugDraw/CDrawAABB.h create mode 100644 include/nbl/ext/DebugDraw/builtin/hlsl/aabb_instances.fragment.hlsl create mode 100644 include/nbl/ext/DebugDraw/builtin/hlsl/aabb_instances.vertex.hlsl create mode 100644 include/nbl/ext/DebugDraw/builtin/hlsl/common.hlsl create mode 100644 src/nbl/ext/DebugDraw/CDrawAABB.cpp create mode 100644 src/nbl/ext/DebugDraw/CMakeLists.txt diff --git a/examples_tests b/examples_tests index 7469300793..738269ede1 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 7469300793cafeebba1ba3b5c77a66fdbdc7744e +Subproject commit 738269ede1b9ee83cd5e44f86e290852ce6b0127 diff --git a/include/nbl/ext/DebugDraw/CDrawAABB.h b/include/nbl/ext/DebugDraw/CDrawAABB.h new file mode 100644 index 0000000000..6be529ecfa --- /dev/null +++ b/include/nbl/ext/DebugDraw/CDrawAABB.h @@ -0,0 +1,84 @@ +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h + +// TODO move this into nabla + +#ifndef _NBL_EXT_DRAW_AABB_H_ +#define _NBL_EXT_DRAW_AABB_H_ + +#include "nbl/video/declarations.h" +#include "nbl/builtin/hlsl/cpp_compat.hlsl" +#include "nbl/ext/DebugDraw/builtin/hlsl/common.hlsl" + +namespace nbl::ext::debugdraw +{ +class DrawAABB final : public core::IReferenceCounted +{ +public: + struct SCachedCreationParameters + { + using streaming_buffer_t = video::StreamingTransientDataBufferST>; + + static constexpr inline auto RequiredAllocateFlags = core::bitflag(video::IDeviceMemoryAllocation::EMAF_DEVICE_ADDRESS_BIT); + static constexpr inline auto RequiredUsageFlags = core::bitflag(asset::IBuffer::EUF_STORAGE_BUFFER_BIT) | asset::IBuffer::EUF_SHADER_DEVICE_ADDRESS_BIT; + + core::smart_refctd_ptr utilities; + + //! optional, default MDI buffer allocated if not provided + core::smart_refctd_ptr streamingBuffer = nullptr; + }; + + struct SCreationParameters : SCachedCreationParameters + { + core::smart_refctd_ptr assetManager = nullptr; + + core::smart_refctd_ptr pipelineLayout; + core::smart_refctd_ptr renderpass = nullptr; + }; + + // creates an instance that can draw one AABB via push constant or multiple using streaming buffer + static core::smart_refctd_ptr create(SCreationParameters&& params); + + // creates default pipeline layout for push constant version + static core::smart_refctd_ptr createDefaultPipelineLayout(video::ILogicalDevice* device, const asset::SPushConstantRange& pcRange); + + // creates default pipeline layout for streaming version + static core::smart_refctd_ptr createDefaultPipelineLayout(video::ILogicalDevice* device); + + static core::smart_refctd_ptr createDefaultPipeline(video::ILogicalDevice* device, video::IGPUPipelineLayout* layout, video::IGPURenderpass* renderpass, video::IGPUGraphicsPipeline::SShaderSpecInfo& vertex, video::IGPUGraphicsPipeline::SShaderSpecInfo& fragment); + + //! mounts the extension's archive to given system - useful if you want to create your own shaders with common header included + static const core::smart_refctd_ptr mount(core::smart_refctd_ptr logger, system::ISystem* system, const std::string_view archiveAlias = ""); + + inline const SCachedCreationParameters& getCreationParameters() const { return m_cachedCreationParams; } + + // records draw command for single AABB, user has to set pipeline outside + bool renderSingle(video::IGPUCommandBuffer* commandBuffer); + + bool render(video::IGPUCommandBuffer* commandBuffer, video::ISemaphore::SWaitInfo waitInfo, float* cameraMat3x4); + + static std::array getVerticesFromAABB(const core::aabbox3d& aabb); + + void addAABB(const core::aabbox3d& aabb, const hlsl::float32_t4& color = { 1,0,0,1 }); + + void clearAABBs(); + +protected: + DrawAABB(SCreationParameters&& _params, core::smart_refctd_ptr pipeline); + ~DrawAABB() override; + +private: + static core::smart_refctd_ptr createPipeline(SCreationParameters& params); + static bool createStreamingBuffer(SCreationParameters& params); + + std::vector m_instances; + std::array m_unitAABBVertices; + + SCachedCreationParameters m_cachedCreationParams; + + core::smart_refctd_ptr m_pipeline; +}; +} + +#endif diff --git a/include/nbl/ext/DebugDraw/builtin/hlsl/aabb_instances.fragment.hlsl b/include/nbl/ext/DebugDraw/builtin/hlsl/aabb_instances.fragment.hlsl new file mode 100644 index 0000000000..f17e028f91 --- /dev/null +++ b/include/nbl/ext/DebugDraw/builtin/hlsl/aabb_instances.fragment.hlsl @@ -0,0 +1,13 @@ +#pragma shader_stage(fragment) + +#include "common.hlsl" + +using namespace nbl::ext::debugdraw; + +[shader("pixel")] +float32_t4 main(PSInput input) : SV_TARGET +{ + float32_t4 outColor = input.color; + + return outColor; +} \ No newline at end of file diff --git a/include/nbl/ext/DebugDraw/builtin/hlsl/aabb_instances.vertex.hlsl b/include/nbl/ext/DebugDraw/builtin/hlsl/aabb_instances.vertex.hlsl new file mode 100644 index 0000000000..8a54d40c5a --- /dev/null +++ b/include/nbl/ext/DebugDraw/builtin/hlsl/aabb_instances.vertex.hlsl @@ -0,0 +1,30 @@ +#pragma shader_stage(vertex) + +#include "nbl/builtin/hlsl/glsl_compat/core.hlsl" +#include "nbl/builtin/hlsl/bda/__ptr.hlsl" +#include "common.hlsl" + +using namespace nbl::hlsl; +using namespace nbl::ext::debugdraw; + +[[vk::push_constant]] SPushConstants pc; + +[shader("vertex")] +PSInput main() +{ + PSInput output; + + float32_t3 vertex = (bda::__ptr::create(pc.pVertexBuffer) + glsl::gl_VertexIndex()).deref_restrict().load(); + InstanceData instance = vk::RawBufferLoad(pc.pInstanceBuffer + sizeof(InstanceData) * glsl::gl_InstanceIndex()); + + float32_t4x4 transform; + transform[0] = instance.transform[0]; + transform[1] = instance.transform[1]; + transform[2] = instance.transform[2]; + transform[3] = float32_t4(0, 0, 0, 1); + float32_t4 position = mul(transform, float32_t4(vertex, 1)); + output.position = mul(pc.MVP, position); + output.color = instance.color; + + return output; +} \ No newline at end of file diff --git a/include/nbl/ext/DebugDraw/builtin/hlsl/common.hlsl b/include/nbl/ext/DebugDraw/builtin/hlsl/common.hlsl new file mode 100644 index 0000000000..2bcd378e40 --- /dev/null +++ b/include/nbl/ext/DebugDraw/builtin/hlsl/common.hlsl @@ -0,0 +1,45 @@ +#ifndef _DRAW_AABB_COMMON_HLSL +#define _DRAW_AABB_COMMON_HLSL + +#include "nbl/builtin/hlsl/cpp_compat.hlsl" + +namespace nbl +{ +namespace ext +{ +namespace debugdraw +{ + +struct InstanceData +{ +#ifdef __HLSL_VERSION + float32_t3x4 transform; +#else + float transform[3*4]; +#endif + nbl::hlsl::float32_t4 color; +}; + +struct SPushConstants +{ +#ifdef __HLSL_VERSION + float32_t4x4 MVP; +#else + float MVP[4*4]; +#endif + uint64_t pVertexBuffer; + uint64_t pInstanceBuffer; +}; + +#ifdef __HLSL_VERSION +struct PSInput +{ + float32_t4 position : SV_Position; + float32_t4 color : TEXCOORD0; +}; +#endif + +} +} +} +#endif diff --git a/src/nbl/ext/CMakeLists.txt b/src/nbl/ext/CMakeLists.txt index 27f9464f3e..da7835a4df 100644 --- a/src/nbl/ext/CMakeLists.txt +++ b/src/nbl/ext/CMakeLists.txt @@ -6,6 +6,7 @@ start_tracking_variables_for_propagation_to_parent() # TODO: all of those options bellow should be defined here option(NBL_BUILD_TEXT_RENDERING "Enable Nabla Text Rendering extension building and integration?" OFF) +option(NBL_BUILD_DEBUG_DRAW "Enable Nabla Debug Draw extension building and integration?" OFF) # TODO: also all variables bellow should be killed from build system since we have logical # targets which properties (like include search directories or outputs) can be queried @@ -54,4 +55,16 @@ if(NBL_BUILD_TEXT_RENDERING) add_subdirectory(TextRendering) endif() +if(NBL_BUILD_DEBUG_DRAW) + add_subdirectory(DebugDraw) + set(NBL_EXT_DEBUG_DRAW_INCLUDE_DIRS + ${NBL_EXT_DEBUG_DRAW_INCLUDE_DIRS} + PARENT_SCOPE + ) + set(NBL_EXT_DEBUG_DRAW_LIB + ${NBL_EXT_DEBUG_DRAW_LIB} + PARENT_SCOPE + ) +endif() + propagate_changed_variables_to_parent_scope() \ No newline at end of file diff --git a/src/nbl/ext/DebugDraw/CDrawAABB.cpp b/src/nbl/ext/DebugDraw/CDrawAABB.cpp new file mode 100644 index 0000000000..3a17cf1b90 --- /dev/null +++ b/src/nbl/ext/DebugDraw/CDrawAABB.cpp @@ -0,0 +1,360 @@ +// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O. +// This file is part of the "Nabla Engine". +// For conditions of distribution and use, see copyright notice in nabla.h + +// TODO move this into nabla + +#include "nbl/ext/DebugDraw/CDrawAABB.h" + +using namespace nbl; +using namespace core; +using namespace video; +using namespace system; +using namespace asset; +using namespace hlsl; + +namespace nbl::ext::debugdraw +{ + +core::smart_refctd_ptr DrawAABB::create(SCreationParameters&& params) +{ + auto* const logger = params.utilities->getLogger(); + + auto pipeline = createPipeline(params); + if (!pipeline) + { + logger->log("Failed to create pipeline!", ILogger::ELL_ERROR); + return nullptr; + } + + if (!createStreamingBuffer(params)) + { + logger->log("Failed to create streaming buffer!", ILogger::ELL_ERROR); + return nullptr; + } + + return core::smart_refctd_ptr(new DrawAABB(std::move(params), pipeline)); +} + +DrawAABB::DrawAABB(SCreationParameters&& params, smart_refctd_ptr pipeline) + : m_cachedCreationParams(std::move(params)), m_pipeline(pipeline) +{ + const auto unitAABB = core::aabbox3d({ 0, 0, 0 }, { 1, 1, 1 }); + m_unitAABBVertices = getVerticesFromAABB(unitAABB); +} + +DrawAABB::~DrawAABB() +{ +} + +// note we use archive entry explicitly for temporary compiler include search path & asset cwd to use keys directly +constexpr std::string_view NBL_ARCHIVE_ENTRY = _ARCHIVE_ENTRY_KEY_; + +const smart_refctd_ptr DrawAABB::mount(smart_refctd_ptr logger, ISystem* system, const std::string_view archiveAlias) +{ + assert(system); + + if (!system) + return nullptr; + + // extension should mount everything for you, regardless if content goes from virtual filesystem + // or disk directly - and you should never rely on application framework to expose extension data + +#ifdef NBL_EMBED_BUILTIN_RESOURCES + auto archive = make_smart_refctd_ptr(smart_refctd_ptr(logger)); + system->mount(smart_refctd_ptr(archive), archiveAlias.data()); +#else + auto NBL_EXTENSION_MOUNT_DIRECTORY_ENTRY = (path(_ARCHIVE_ABSOLUTE_ENTRY_PATH_) / NBL_ARCHIVE_ENTRY).make_preferred(); + auto archive = make_smart_refctd_ptr(std::move(NBL_EXTENSION_MOUNT_DIRECTORY_ENTRY), smart_refctd_ptr(logger), system); + system->mount(smart_refctd_ptr(archive), archiveAlias.data()); +#endif + + return smart_refctd_ptr(archive); +} + +smart_refctd_ptr DrawAABB::createPipeline(SCreationParameters& params) +{ + auto system = smart_refctd_ptr(params.assetManager->getSystem()); + auto* set = params.assetManager->getCompilerSet(); + auto compiler = set->getShaderCompiler(IShader::E_CONTENT_TYPE::ECT_HLSL); + auto includeFinder = make_smart_refctd_ptr(smart_refctd_ptr(system)); + auto includeLoader = includeFinder->getDefaultFileSystemLoader(); + includeFinder->addSearchPath(NBL_ARCHIVE_ENTRY.data(), includeLoader); + + auto compileShader = [&](const std::string& filePath, IShader::E_SHADER_STAGE stage) -> smart_refctd_ptr + { + IAssetLoader::SAssetLoadParams lparams = {}; + lparams.logger = params.utilities->getLogger(); + lparams.workingDirectory = NBL_ARCHIVE_ENTRY.data(); + auto bundle = params.assetManager->getAsset(filePath, lparams); + if (bundle.getContents().empty() || bundle.getAssetType() != IAsset::ET_SHADER) + { + params.utilities->getLogger()->log("Shader %s not found!", ILogger::ELL_ERROR, filePath.c_str()); + exit(-1); + } + + const auto assets = bundle.getContents(); + assert(assets.size() == 1); + smart_refctd_ptr shaderSrc = IAsset::castDown(assets[0]); + if (!shaderSrc) + return nullptr; + + CHLSLCompiler::SOptions options = {}; + options.stage = stage; + options.preprocessorOptions.sourceIdentifier = filePath; + options.preprocessorOptions.logger = params.utilities->getLogger(); + options.preprocessorOptions.includeFinder = includeFinder.get(); + shaderSrc = compiler->compileToSPIRV((const char*)shaderSrc->getContent()->getPointer(), options); + + return params.utilities->getLogicalDevice()->compileShader({ shaderSrc.get() }); + }; + + if (!system->isDirectory(path(NBL_ARCHIVE_ENTRY.data()))) + mount(smart_refctd_ptr(params.utilities->getLogger()), system.get(), NBL_ARCHIVE_ENTRY); + + auto vertexShader = compileShader("aabb_instances.vertex.hlsl", IShader::E_SHADER_STAGE::ESS_VERTEX); + auto fragmentShader = compileShader("aabb_instances.fragment.hlsl", IShader::E_SHADER_STAGE::ESS_FRAGMENT); + + video::IGPUGraphicsPipeline::SCreationParams pipelineParams[1] = {}; + pipelineParams[0].layout = params.pipelineLayout.get(); + pipelineParams[0].vertexShader = { .shader = vertexShader.get(), .entryPoint = "main" }; + pipelineParams[0].fragmentShader = { .shader = fragmentShader.get(), .entryPoint = "main" }; + pipelineParams[0].cached = { + .primitiveAssembly = { + .primitiveType = asset::E_PRIMITIVE_TOPOLOGY::EPT_LINE_LIST, + } + }; + pipelineParams[0].renderpass = params.renderpass.get(); + + smart_refctd_ptr pipeline; + params.utilities->getLogicalDevice()->createGraphicsPipelines(nullptr, pipelineParams, &pipeline); + if (!pipeline) + { + params.utilities->getLogger()->log("Could not create streaming pipeline!", ILogger::ELL_ERROR); + return nullptr; + } + + return pipeline; +} + +bool DrawAABB::createStreamingBuffer(SCreationParameters& params) +{ + const uint32_t minStreamingBufferAllocationSize = 128u, maxStreamingBufferAllocationAlignment = 4096u, mdiBufferDefaultSize = /* 2MB */ 1024u * 1024u * 2u; + + auto getRequiredAccessFlags = [&](const bitflag& properties) + { + bitflag flags(IDeviceMemoryAllocation::EMCAF_NO_MAPPING_ACCESS); + + if (properties.hasFlags(IDeviceMemoryAllocation::EMPF_HOST_READABLE_BIT)) + flags |= IDeviceMemoryAllocation::EMCAF_READ; + if (properties.hasFlags(IDeviceMemoryAllocation::EMPF_HOST_WRITABLE_BIT)) + flags |= IDeviceMemoryAllocation::EMCAF_WRITE; + + return flags; + }; + + if (!params.streamingBuffer) + { + IGPUBuffer::SCreationParams mdiCreationParams = {}; + mdiCreationParams.usage = SCachedCreationParameters::RequiredUsageFlags; + mdiCreationParams.size = mdiBufferDefaultSize; + + auto buffer = params.utilities->getLogicalDevice()->createBuffer(std::move(mdiCreationParams)); + buffer->setObjectDebugName("AABB Streaming Buffer"); + + auto memoryReqs = buffer->getMemoryReqs(); + memoryReqs.memoryTypeBits &= params.utilities->getLogicalDevice()->getPhysicalDevice()->getUpStreamingMemoryTypeBits(); + + auto allocation = params.utilities->getLogicalDevice()->allocate(memoryReqs, buffer.get(), SCachedCreationParameters::RequiredAllocateFlags); + { + const bool allocated = allocation.isValid(); + assert(allocated); + } + auto memory = allocation.memory; + + if (!memory->map({ 0ull, memoryReqs.size }, getRequiredAccessFlags(memory->getMemoryPropertyFlags()))) + params.utilities->getLogger()->log("Could not map device memory!", ILogger::ELL_ERROR); + + params.streamingBuffer = make_smart_refctd_ptr(SBufferRange{0ull, mdiCreationParams.size, std::move(buffer)}, maxStreamingBufferAllocationAlignment, minStreamingBufferAllocationSize); + } + + auto buffer = params.streamingBuffer->getBuffer(); + auto binding = buffer->getBoundMemory(); + + const auto validation = std::to_array + ({ + std::make_pair(buffer->getCreationParams().usage.hasFlags(SCachedCreationParameters::RequiredUsageFlags), "Streaming buffer must be created with IBuffer::EUF_STORAGE_BUFFER_BIT | IBuffer::EUF_SHADER_DEVICE_ADDRESS_BIT enabled!"), + std::make_pair(bool(buffer->getMemoryReqs().memoryTypeBits & params.utilities->getLogicalDevice()->getPhysicalDevice()->getUpStreamingMemoryTypeBits()), "Streaming buffer must have up-streaming memory type bits enabled!"), + std::make_pair(binding.memory->getAllocateFlags().hasFlags(SCachedCreationParameters::RequiredAllocateFlags), "Streaming buffer's memory must be allocated with IDeviceMemoryAllocation::EMAF_DEVICE_ADDRESS_BIT enabled!"), + std::make_pair(binding.memory->isCurrentlyMapped(), "Streaming 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) + std::make_pair(binding.memory->getCurrentMappingAccess().hasFlags(getRequiredAccessFlags(binding.memory->getMemoryPropertyFlags())), "Streaming buffer's memory current mapping access flags don't meet requirements!") + }); + + for (const auto& [ok, error] : validation) + if (!ok) + { + params.utilities->getLogger()->log(error, ILogger::ELL_ERROR); + return false; + } + + return true; +} + +core::smart_refctd_ptr DrawAABB::createDefaultPipelineLayout(video::ILogicalDevice* device, const asset::SPushConstantRange& pcRange) +{ + return device->createPipelineLayout({ &pcRange , 1 }, nullptr, nullptr, nullptr, nullptr); +} + +core::smart_refctd_ptr DrawAABB::createDefaultPipelineLayout(video::ILogicalDevice* device) +{ + SPushConstantRange pcRange = { + .stageFlags = IShader::E_SHADER_STAGE::ESS_VERTEX, + .offset = 0, + .size = sizeof(SPushConstants) + }; + return device->createPipelineLayout({ &pcRange , 1 }, nullptr, nullptr, nullptr, nullptr); +} + +smart_refctd_ptr DrawAABB::createDefaultPipeline(video::ILogicalDevice* device, video::IGPUPipelineLayout* layout, video::IGPURenderpass* renderpass, video::IGPUGraphicsPipeline::SShaderSpecInfo& vertex, video::IGPUGraphicsPipeline::SShaderSpecInfo& fragment) +{ + smart_refctd_ptr pipeline; + + video::IGPUGraphicsPipeline::SCreationParams params[1] = {}; + params[0].layout = layout; + params[0].vertexShader = vertex; + params[0].fragmentShader = fragment; + params[0].cached = { + .primitiveAssembly = { + .primitiveType = asset::E_PRIMITIVE_TOPOLOGY::EPT_LINE_LIST, + } + }; + params[0].renderpass = renderpass; + + device->createGraphicsPipelines(nullptr, params, &pipeline); + + return pipeline; +} + +bool DrawAABB::renderSingle(IGPUCommandBuffer* commandBuffer) +{ + commandBuffer->setLineWidth(1.f); + commandBuffer->draw(24, 1, 0, 0); + + return true; +} + +bool DrawAABB::render(IGPUCommandBuffer* commandBuffer, ISemaphore::SWaitInfo waitInfo, float* cameraMat3x4) +{ + using offset_t = SCachedCreationParameters::streaming_buffer_t::size_type; + constexpr auto MdiSizes = std::to_array({ sizeof(float32_t3), sizeof(InstanceData) }); + // shared nPoT alignment needs to be divisible by all smaller ones to satisfy an allocation from all + constexpr offset_t MaxAlignment = std::reduce(MdiSizes.begin(), MdiSizes.end(), 1, [](const offset_t a, const offset_t b)->offset_t {return std::lcm(a, b); }); + // allocator initialization needs us to round up to PoT + const auto MaxPOTAlignment = roundUpToPoT(MaxAlignment); + + auto* streaming = m_cachedCreationParams.streamingBuffer.get(); + + auto* const streamingPtr = reinterpret_cast(streaming->getBufferPointer()); + assert(streamingPtr); + + commandBuffer->bindGraphicsPipeline(m_pipeline.get()); // move outside of loop, only bind once + + auto instancesIt = m_instances.begin(); + const uint32_t verticesByteSize = sizeof(float32_t3) * m_unitAABBVertices.size(); + const uint32_t availableInstancesByteSize = streaming->getBuffer()->getSize() - verticesByteSize; + const uint32_t instancesPerIter = availableInstancesByteSize / sizeof(InstanceData); + using suballocator_t = core::LinearAddressAllocatorST; + while (instancesIt != m_instances.end()) + { + const uint32_t instanceCount = min(instancesPerIter, m_instances.size()); + offset_t inputOffset = 0u; + offset_t ImaginarySizeUpperBound = 0x1 << 30; + suballocator_t imaginaryChunk(nullptr, inputOffset, 0, roundUpToPoT(MaxAlignment), ImaginarySizeUpperBound); + uint32_t vertexByteOffset = imaginaryChunk.alloc_addr(verticesByteSize, sizeof(float32_t3)); + uint32_t instancesByteOffset = imaginaryChunk.alloc_addr(sizeof(InstanceData) * instanceCount, sizeof(InstanceData)); + const uint32_t totalSize = imaginaryChunk.get_allocated_size(); + + inputOffset = SCachedCreationParameters::streaming_buffer_t::invalid_value; + std::chrono::steady_clock::time_point waitTill = std::chrono::steady_clock::now() + std::chrono::milliseconds(1u); + streaming->multi_allocate(waitTill, 1, &inputOffset, &totalSize, &MaxAlignment); + + memcpy(streamingPtr + vertexByteOffset, m_unitAABBVertices.data(), sizeof(m_unitAABBVertices[0]) * m_unitAABBVertices.size()); + memcpy(streamingPtr + instancesByteOffset, std::addressof(*instancesIt), sizeof(InstanceData) * instanceCount); + instancesIt += instanceCount; + + assert(!streaming->needsManualFlushOrInvalidate()); + + SPushConstants pc; + memcpy(pc.MVP, cameraMat3x4, sizeof(pc.MVP)); + pc.pVertexBuffer = m_cachedCreationParams.streamingBuffer->getBuffer()->getDeviceAddress() + vertexByteOffset; + pc.pInstanceBuffer = m_cachedCreationParams.streamingBuffer->getBuffer()->getDeviceAddress() + instancesByteOffset; + + commandBuffer->pushConstants(m_pipeline->getLayout(), ESS_VERTEX, 0, sizeof(SPushConstants), &pc); + commandBuffer->draw(m_unitAABBVertices.size(), instanceCount, 0, 0); + + streaming->multi_deallocate(1, &inputOffset, &totalSize, waitInfo); + } + // end loop + + return true; +} + +std::array DrawAABB::getVerticesFromAABB(const core::aabbox3d& aabb) +{ + const auto& pMin = aabb.MinEdge; + const auto& pMax = aabb.MaxEdge; + + std::array vertices; + vertices[0] = float32_t3(pMin.X, pMin.Y, pMin.Z); + vertices[1] = float32_t3(pMax.X, pMin.Y, pMin.Z); + vertices[2] = float32_t3(pMin.X, pMin.Y, pMin.Z); + vertices[3] = float32_t3(pMin.X, pMin.Y, pMax.Z); + + vertices[4] = float32_t3(pMax.X, pMin.Y, pMax.Z); + vertices[5] = float32_t3(pMax.X, pMin.Y, pMin.Z); + vertices[6] = float32_t3(pMax.X, pMin.Y, pMax.Z); + vertices[7] = float32_t3(pMin.X, pMin.Y, pMax.Z); + + vertices[8] = float32_t3(pMin.X, pMax.Y, pMin.Z); + vertices[9] = float32_t3(pMax.X, pMax.Y, pMin.Z); + vertices[10] = float32_t3(pMin.X, pMax.Y, pMin.Z); + vertices[11] = float32_t3(pMin.X, pMax.Y, pMax.Z); + + vertices[12] = float32_t3(pMax.X, pMax.Y, pMax.Z); + vertices[13] = float32_t3(pMax.X, pMax.Y, pMin.Z); + vertices[14] = float32_t3(pMax.X, pMax.Y, pMax.Z); + vertices[15] = float32_t3(pMin.X, pMax.Y, pMax.Z); + + vertices[16] = float32_t3(pMin.X, pMin.Y, pMin.Z); + vertices[17] = float32_t3(pMin.X, pMax.Y, pMin.Z); + vertices[18] = float32_t3(pMax.X, pMin.Y, pMin.Z); + vertices[19] = float32_t3(pMax.X, pMax.Y, pMin.Z); + + vertices[20] = float32_t3(pMin.X, pMin.Y, pMax.Z); + vertices[21] = float32_t3(pMin.X, pMax.Y, pMax.Z); + vertices[22] = float32_t3(pMax.X, pMin.Y, pMax.Z); + vertices[23] = float32_t3(pMax.X, pMax.Y, pMax.Z); + + return vertices; +} + +void DrawAABB::addAABB(const core::aabbox3d& aabb, const hlsl::float32_t4& color) +{ + InstanceData instance; + instance.color = color; + + core::matrix3x4SIMD instanceTransform; + instanceTransform.setTranslation(core::vectorSIMDf(aabb.MinEdge.X, aabb.MinEdge.Y, aabb.MinEdge.Z, 0)); + const auto diagonal = aabb.MaxEdge - aabb.MinEdge; + instanceTransform.setScale(core::vectorSIMDf(diagonal.X, diagonal.Y, diagonal.Z)); + memcpy(instance.transform, instanceTransform.pointer(), sizeof(core::matrix3x4SIMD)); + + m_instances.push_back(instance); +} + +void DrawAABB::clearAABBs() +{ + m_instances.clear(); +} + +} diff --git a/src/nbl/ext/DebugDraw/CMakeLists.txt b/src/nbl/ext/DebugDraw/CMakeLists.txt new file mode 100644 index 0000000000..3011fe5b4c --- /dev/null +++ b/src/nbl/ext/DebugDraw/CMakeLists.txt @@ -0,0 +1,42 @@ +include(${NBL_ROOT_PATH}/cmake/common.cmake) + +set(NBL_EXT_INTERNAL_INCLUDE_DIR "${NBL_ROOT_PATH}/include") + +set(NBL_EXT_DEBUG_DRAW_H + ${NBL_EXT_INTERNAL_INCLUDE_DIR}/nbl/ext/DebugDraw/CDrawAABB.h +) + +set(NBL_EXT_DEBUG_DRAW_SRC + "${CMAKE_CURRENT_SOURCE_DIR}/CDrawAABB.cpp" +) + +nbl_create_ext_library_project( + DEBUG_DRAW + "${NBL_EXT_DEBUG_DRAW_H}" + "${NBL_EXT_DEBUG_DRAW_SRC}" + "${NBL_EXT_DEBUG_DRAW_EXTERNAL_INCLUDE}" + "" + "" +) + +# this should be standard for all extensions +set(_ARCHIVE_ENTRY_KEY_ "DebugDraw/builtin/hlsl") # then each one has unique archive key +get_filename_component(_ARCHIVE_ABSOLUTE_ENTRY_PATH_ "${NBL_EXT_INTERNAL_INCLUDE_DIR}/nbl/ext" ABSOLUTE) +get_filename_component(_OUTPUT_DIRECTORY_SOURCE_ "${CMAKE_CURRENT_BINARY_DIR}/src" ABSOLUTE) +get_filename_component(_OUTPUT_DIRECTORY_HEADER_ "${CMAKE_CURRENT_BINARY_DIR}/include" ABSOLUTE) + +target_compile_definitions(${LIB_NAME} PRIVATE _ARCHIVE_ABSOLUTE_ENTRY_PATH_="${_ARCHIVE_ABSOLUTE_ENTRY_PATH_}") +target_compile_definitions(${LIB_NAME} PRIVATE _ARCHIVE_ENTRY_KEY_="${_ARCHIVE_ENTRY_KEY_}") + +if(NBL_EMBED_BUILTIN_RESOURCES) + set(_BR_TARGET_ extDebugDrawbuiltinResourceData) + + LIST_BUILTIN_RESOURCE(RESOURCES_TO_EMBED "common.hlsl") + LIST_BUILTIN_RESOURCE(RESOURCES_TO_EMBED "aabb_instances.vertex.hlsl") # (*) + LIST_BUILTIN_RESOURCE(RESOURCES_TO_EMBED "aabb_instances.fragment.hlsl") # (*) + + ADD_CUSTOM_BUILTIN_RESOURCES(${_BR_TARGET_} RESOURCES_TO_EMBED "${_ARCHIVE_ABSOLUTE_ENTRY_PATH_}" "${_ARCHIVE_ENTRY_KEY_}" "nbl::ext::debugdraw::builtin" "${_OUTPUT_DIRECTORY_HEADER_}" "${_OUTPUT_DIRECTORY_SOURCE_}") + LINK_BUILTIN_RESOURCES_TO_TARGET(${LIB_NAME} ${_BR_TARGET_}) +endif() + +set(NBL_EXT_DEBUG_DRAW_TARGET ${LIB_NAME} CACHE INTERNAL "Nabla's Debug Draw logical target name") From a755514bf184f0ddb112637d3fad972d5be35f68 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 8 Jul 2025 15:49:14 +0700 Subject: [PATCH 04/16] removed todos --- include/nbl/ext/DebugDraw/CDrawAABB.h | 2 -- src/nbl/ext/DebugDraw/CDrawAABB.cpp | 3 --- 2 files changed, 5 deletions(-) diff --git a/include/nbl/ext/DebugDraw/CDrawAABB.h b/include/nbl/ext/DebugDraw/CDrawAABB.h index 6be529ecfa..13ca3a1ece 100644 --- a/include/nbl/ext/DebugDraw/CDrawAABB.h +++ b/include/nbl/ext/DebugDraw/CDrawAABB.h @@ -2,8 +2,6 @@ // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h -// TODO move this into nabla - #ifndef _NBL_EXT_DRAW_AABB_H_ #define _NBL_EXT_DRAW_AABB_H_ diff --git a/src/nbl/ext/DebugDraw/CDrawAABB.cpp b/src/nbl/ext/DebugDraw/CDrawAABB.cpp index 3a17cf1b90..b77630a2c2 100644 --- a/src/nbl/ext/DebugDraw/CDrawAABB.cpp +++ b/src/nbl/ext/DebugDraw/CDrawAABB.cpp @@ -2,8 +2,6 @@ // This file is part of the "Nabla Engine". // For conditions of distribution and use, see copyright notice in nabla.h -// TODO move this into nabla - #include "nbl/ext/DebugDraw/CDrawAABB.h" using namespace nbl; @@ -294,7 +292,6 @@ bool DrawAABB::render(IGPUCommandBuffer* commandBuffer, ISemaphore::SWaitInfo wa streaming->multi_deallocate(1, &inputOffset, &totalSize, waitInfo); } - // end loop return true; } From 473592b00651360d8694921757bf5ecf1d9caa8e Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 9 Jul 2025 15:19:50 +0700 Subject: [PATCH 05/16] support hlsl AABBs, also OBBs with transform --- CMakeLists.txt | 1 + examples_tests | 2 +- include/nbl/config/BuildConfigOptions.h.in | 2 ++ include/nbl/ext/DebugDraw/CDrawAABB.h | 4 ++++ src/nbl/ext/CMakeLists.txt | 1 - src/nbl/ext/DebugDraw/CDrawAABB.cpp | 23 +++++++++++++++++++--- 6 files changed, 28 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4e29839399..ad8ceffba8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -182,6 +182,7 @@ option(NBL_FAST_MATH "Enable fast low-precision math" ON) option(NBL_BUILD_EXAMPLES "Enable building examples" ON) option(NBL_BUILD_MITSUBA_LOADER "Enable nbl::ext::MitsubaLoader?" OFF) # TODO: once it compies turn this ON by default! option(NBL_BUILD_IMGUI "Enable nbl::ext::ImGui?" ON) +option(NBL_BUILD_DEBUG_DRAW "Enable Nabla Debug Draw extension?" OFF) option(NBL_BUILD_OPTIX "Enable nbl::ext::OptiX?" OFF) if(NBL_COMPILE_WITH_CUDA) diff --git a/examples_tests b/examples_tests index 738269ede1..4f1fabdb78 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 738269ede1b9ee83cd5e44f86e290852ce6b0127 +Subproject commit 4f1fabdb786b87e4609649a36059c33cd54ae843 diff --git a/include/nbl/config/BuildConfigOptions.h.in b/include/nbl/config/BuildConfigOptions.h.in index 61b980f71e..578796d384 100644 --- a/include/nbl/config/BuildConfigOptions.h.in +++ b/include/nbl/config/BuildConfigOptions.h.in @@ -65,6 +65,8 @@ #cmakedefine _NBL_BUILD_DPL_ +#cmakedefine NBL_BUILD_DEBUG_DRAW + // TODO: This has to disapppear from the main header and go to the OptiX extension header + config #cmakedefine OPTIX_INCLUDE_DIR "@OPTIX_INCLUDE_DIR@" diff --git a/include/nbl/ext/DebugDraw/CDrawAABB.h b/include/nbl/ext/DebugDraw/CDrawAABB.h index 13ca3a1ece..08b3cf5a3c 100644 --- a/include/nbl/ext/DebugDraw/CDrawAABB.h +++ b/include/nbl/ext/DebugDraw/CDrawAABB.h @@ -7,6 +7,7 @@ #include "nbl/video/declarations.h" #include "nbl/builtin/hlsl/cpp_compat.hlsl" +#include "nbl/builtin/hlsl/shapes/aabb.hlsl" #include "nbl/ext/DebugDraw/builtin/hlsl/common.hlsl" namespace nbl::ext::debugdraw @@ -59,6 +60,9 @@ class DrawAABB final : public core::IReferenceCounted static std::array getVerticesFromAABB(const core::aabbox3d& aabb); void addAABB(const core::aabbox3d& aabb, const hlsl::float32_t4& color = { 1,0,0,1 }); + void addAABB(const hlsl::shapes::AABB<3,float>& aabb, const hlsl::float32_t4& color = { 1,0,0,1 }); + + void addOBB(const hlsl::shapes::AABB<3, float>& aabb, const hlsl::float32_t3x4 transform, const hlsl::float32_t4& color = { 1,0,0,1 }); void clearAABBs(); diff --git a/src/nbl/ext/CMakeLists.txt b/src/nbl/ext/CMakeLists.txt index da7835a4df..6271e912b9 100644 --- a/src/nbl/ext/CMakeLists.txt +++ b/src/nbl/ext/CMakeLists.txt @@ -6,7 +6,6 @@ start_tracking_variables_for_propagation_to_parent() # TODO: all of those options bellow should be defined here option(NBL_BUILD_TEXT_RENDERING "Enable Nabla Text Rendering extension building and integration?" OFF) -option(NBL_BUILD_DEBUG_DRAW "Enable Nabla Debug Draw extension building and integration?" OFF) # TODO: also all variables bellow should be killed from build system since we have logical # targets which properties (like include search directories or outputs) can be queried diff --git a/src/nbl/ext/DebugDraw/CDrawAABB.cpp b/src/nbl/ext/DebugDraw/CDrawAABB.cpp index b77630a2c2..6cb2f365ec 100644 --- a/src/nbl/ext/DebugDraw/CDrawAABB.cpp +++ b/src/nbl/ext/DebugDraw/CDrawAABB.cpp @@ -256,6 +256,7 @@ bool DrawAABB::render(IGPUCommandBuffer* commandBuffer, ISemaphore::SWaitInfo wa assert(streamingPtr); commandBuffer->bindGraphicsPipeline(m_pipeline.get()); // move outside of loop, only bind once + commandBuffer->setLineWidth(1.f); auto instancesIt = m_instances.begin(); const uint32_t verticesByteSize = sizeof(float32_t3) * m_unitAABBVertices.size(); @@ -336,14 +337,30 @@ std::array DrawAABB::getVerticesFromAABB(const core::aabbox3d& aabb, const hlsl::float32_t4& color) +{ + addAABB(shapes::AABB<3, float>{{aabb.MinEdge.X, aabb.MinEdge.Y, aabb.MinEdge.Z}, { aabb.MaxEdge.X, aabb.MaxEdge.Y, aabb.MaxEdge.Z }}, color); +} + +void DrawAABB::addAABB(const hlsl::shapes::AABB<3,float>& aabb, const hlsl::float32_t4& color) +{ + const auto transform = hlsl::float32_t3x4(1); + addOBB(aabb, transform, color); +} + +void DrawAABB::addOBB(const hlsl::shapes::AABB<3, float>& aabb, const hlsl::float32_t3x4 transform, const hlsl::float32_t4& color) { InstanceData instance; instance.color = color; core::matrix3x4SIMD instanceTransform; - instanceTransform.setTranslation(core::vectorSIMDf(aabb.MinEdge.X, aabb.MinEdge.Y, aabb.MinEdge.Z, 0)); - const auto diagonal = aabb.MaxEdge - aabb.MinEdge; - instanceTransform.setScale(core::vectorSIMDf(diagonal.X, diagonal.Y, diagonal.Z)); + instanceTransform.setTranslation(core::vectorSIMDf(aabb.minVx.x, aabb.minVx.y, aabb.minVx.z, 0)); + const auto diagonal = aabb.getExtent(); + instanceTransform.setScale(core::vectorSIMDf(diagonal.x, diagonal.y, diagonal.z)); + + core::matrix3x4SIMD worldTransform; + memcpy(worldTransform.pointer(), &transform, sizeof(transform)); + + instanceTransform = core::concatenateBFollowedByA(worldTransform, instanceTransform); memcpy(instance.transform, instanceTransform.pointer(), sizeof(core::matrix3x4SIMD)); m_instances.push_back(instance); From daf34e0697a30cb970adeca4ef8dbddda1515f2c Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 18 Aug 2025 16:47:58 +0700 Subject: [PATCH 06/16] minor syntax changes --- include/nbl/ext/DebugDraw/CDrawAABB.h | 92 +++++++++---------- .../builtin/hlsl/aabb_instances.fragment.hlsl | 2 +- .../builtin/hlsl/aabb_instances.vertex.hlsl | 7 +- .../ext/DebugDraw/builtin/hlsl/common.hlsl | 6 +- src/nbl/ext/DebugDraw/CDrawAABB.cpp | 8 +- src/nbl/ext/DebugDraw/CMakeLists.txt | 2 +- 6 files changed, 62 insertions(+), 55 deletions(-) diff --git a/include/nbl/ext/DebugDraw/CDrawAABB.h b/include/nbl/ext/DebugDraw/CDrawAABB.h index 08b3cf5a3c..034a0321bf 100644 --- a/include/nbl/ext/DebugDraw/CDrawAABB.h +++ b/include/nbl/ext/DebugDraw/CDrawAABB.h @@ -10,76 +10,76 @@ #include "nbl/builtin/hlsl/shapes/aabb.hlsl" #include "nbl/ext/DebugDraw/builtin/hlsl/common.hlsl" -namespace nbl::ext::debugdraw +namespace nbl::ext::debug_draw { class DrawAABB final : public core::IReferenceCounted { -public: - struct SCachedCreationParameters - { - using streaming_buffer_t = video::StreamingTransientDataBufferST>; + public: + struct SCachedCreationParameters + { + using streaming_buffer_t = video::StreamingTransientDataBufferST>; - static constexpr inline auto RequiredAllocateFlags = core::bitflag(video::IDeviceMemoryAllocation::EMAF_DEVICE_ADDRESS_BIT); - static constexpr inline auto RequiredUsageFlags = core::bitflag(asset::IBuffer::EUF_STORAGE_BUFFER_BIT) | asset::IBuffer::EUF_SHADER_DEVICE_ADDRESS_BIT; + static constexpr inline auto RequiredAllocateFlags = core::bitflag(video::IDeviceMemoryAllocation::EMAF_DEVICE_ADDRESS_BIT); + static constexpr inline auto RequiredUsageFlags = core::bitflag(asset::IBuffer::EUF_STORAGE_BUFFER_BIT) | asset::IBuffer::EUF_SHADER_DEVICE_ADDRESS_BIT; - core::smart_refctd_ptr utilities; + core::smart_refctd_ptr utilities; - //! optional, default MDI buffer allocated if not provided - core::smart_refctd_ptr streamingBuffer = nullptr; - }; - - struct SCreationParameters : SCachedCreationParameters - { - core::smart_refctd_ptr assetManager = nullptr; + //! optional, default MDI buffer allocated if not provided + core::smart_refctd_ptr streamingBuffer = nullptr; + }; + + struct SCreationParameters : SCachedCreationParameters + { + core::smart_refctd_ptr assetManager = nullptr; - core::smart_refctd_ptr pipelineLayout; - core::smart_refctd_ptr renderpass = nullptr; - }; + core::smart_refctd_ptr pipelineLayout; + core::smart_refctd_ptr renderpass = nullptr; + }; - // creates an instance that can draw one AABB via push constant or multiple using streaming buffer - static core::smart_refctd_ptr create(SCreationParameters&& params); + // creates an instance that can draw one AABB via push constant or multiple using streaming buffer + static core::smart_refctd_ptr create(SCreationParameters&& params); - // creates default pipeline layout for push constant version - static core::smart_refctd_ptr createDefaultPipelineLayout(video::ILogicalDevice* device, const asset::SPushConstantRange& pcRange); + // creates default pipeline layout for push constant version + static core::smart_refctd_ptr createDefaultPipelineLayout(video::ILogicalDevice* device, const asset::SPushConstantRange& pcRange); - // creates default pipeline layout for streaming version - static core::smart_refctd_ptr createDefaultPipelineLayout(video::ILogicalDevice* device); + // creates default pipeline layout for streaming version + static core::smart_refctd_ptr createDefaultPipelineLayout(video::ILogicalDevice* device); - static core::smart_refctd_ptr createDefaultPipeline(video::ILogicalDevice* device, video::IGPUPipelineLayout* layout, video::IGPURenderpass* renderpass, video::IGPUGraphicsPipeline::SShaderSpecInfo& vertex, video::IGPUGraphicsPipeline::SShaderSpecInfo& fragment); + static core::smart_refctd_ptr createDefaultPipeline(video::ILogicalDevice* device, video::IGPUPipelineLayout* layout, video::IGPURenderpass* renderpass, video::IGPUGraphicsPipeline::SShaderSpecInfo& vertex, video::IGPUGraphicsPipeline::SShaderSpecInfo& fragment); - //! mounts the extension's archive to given system - useful if you want to create your own shaders with common header included - static const core::smart_refctd_ptr mount(core::smart_refctd_ptr logger, system::ISystem* system, const std::string_view archiveAlias = ""); + //! mounts the extension's archive to given system - useful if you want to create your own shaders with common header included + static const core::smart_refctd_ptr mount(core::smart_refctd_ptr logger, system::ISystem* system, const std::string_view archiveAlias = ""); - inline const SCachedCreationParameters& getCreationParameters() const { return m_cachedCreationParams; } + inline const SCachedCreationParameters& getCreationParameters() const { return m_cachedCreationParams; } - // records draw command for single AABB, user has to set pipeline outside - bool renderSingle(video::IGPUCommandBuffer* commandBuffer); + // records draw command for single AABB, user has to set pipeline outside + bool renderSingle(video::IGPUCommandBuffer* commandBuffer); - bool render(video::IGPUCommandBuffer* commandBuffer, video::ISemaphore::SWaitInfo waitInfo, float* cameraMat3x4); + bool render(video::IGPUCommandBuffer* commandBuffer, video::ISemaphore::SWaitInfo waitInfo, float* cameraMat3x4); - static std::array getVerticesFromAABB(const core::aabbox3d& aabb); + static std::array getVerticesFromAABB(const core::aabbox3d& aabb); - void addAABB(const core::aabbox3d& aabb, const hlsl::float32_t4& color = { 1,0,0,1 }); - void addAABB(const hlsl::shapes::AABB<3,float>& aabb, const hlsl::float32_t4& color = { 1,0,0,1 }); + void addAABB(const core::aabbox3d& aabb, const hlsl::float32_t4& color = { 1,0,0,1 }); + void addAABB(const hlsl::shapes::AABB<3,float>& aabb, const hlsl::float32_t4& color = { 1,0,0,1 }); - void addOBB(const hlsl::shapes::AABB<3, float>& aabb, const hlsl::float32_t3x4 transform, const hlsl::float32_t4& color = { 1,0,0,1 }); + void addOBB(const hlsl::shapes::AABB<3, float>& aabb, const hlsl::float32_t3x4 transform, const hlsl::float32_t4& color = { 1,0,0,1 }); - void clearAABBs(); + void clearAABBs(); -protected: - DrawAABB(SCreationParameters&& _params, core::smart_refctd_ptr pipeline); - ~DrawAABB() override; + protected: + DrawAABB(SCreationParameters&& _params, core::smart_refctd_ptr pipeline); + ~DrawAABB() override; -private: - static core::smart_refctd_ptr createPipeline(SCreationParameters& params); - static bool createStreamingBuffer(SCreationParameters& params); + private: + static core::smart_refctd_ptr createPipeline(SCreationParameters& params); + static bool createStreamingBuffer(SCreationParameters& params); - std::vector m_instances; - std::array m_unitAABBVertices; + std::vector m_instances; + std::array m_unitAABBVertices; - SCachedCreationParameters m_cachedCreationParams; + SCachedCreationParameters m_cachedCreationParams; - core::smart_refctd_ptr m_pipeline; + core::smart_refctd_ptr m_pipeline; }; } diff --git a/include/nbl/ext/DebugDraw/builtin/hlsl/aabb_instances.fragment.hlsl b/include/nbl/ext/DebugDraw/builtin/hlsl/aabb_instances.fragment.hlsl index f17e028f91..686e8934db 100644 --- a/include/nbl/ext/DebugDraw/builtin/hlsl/aabb_instances.fragment.hlsl +++ b/include/nbl/ext/DebugDraw/builtin/hlsl/aabb_instances.fragment.hlsl @@ -2,7 +2,7 @@ #include "common.hlsl" -using namespace nbl::ext::debugdraw; +using namespace nbl::ext::debug_draw; [shader("pixel")] float32_t4 main(PSInput input) : SV_TARGET diff --git a/include/nbl/ext/DebugDraw/builtin/hlsl/aabb_instances.vertex.hlsl b/include/nbl/ext/DebugDraw/builtin/hlsl/aabb_instances.vertex.hlsl index 8a54d40c5a..ff993f8541 100644 --- a/include/nbl/ext/DebugDraw/builtin/hlsl/aabb_instances.vertex.hlsl +++ b/include/nbl/ext/DebugDraw/builtin/hlsl/aabb_instances.vertex.hlsl @@ -1,11 +1,12 @@ #pragma shader_stage(vertex) +#include "nbl/builtin/hlsl/math/linalg/fast_affine.hlsl" #include "nbl/builtin/hlsl/glsl_compat/core.hlsl" #include "nbl/builtin/hlsl/bda/__ptr.hlsl" #include "common.hlsl" using namespace nbl::hlsl; -using namespace nbl::ext::debugdraw; +using namespace nbl::ext::debug_draw; [[vk::push_constant]] SPushConstants pc; @@ -15,14 +16,14 @@ PSInput main() PSInput output; float32_t3 vertex = (bda::__ptr::create(pc.pVertexBuffer) + glsl::gl_VertexIndex()).deref_restrict().load(); - InstanceData instance = vk::RawBufferLoad(pc.pInstanceBuffer + sizeof(InstanceData) * glsl::gl_InstanceIndex()); + InstanceData instance = vk::BufferPointer(pc.pInstanceBuffer + sizeof(InstanceData) * glsl::gl_InstanceIndex()).Get(); float32_t4x4 transform; transform[0] = instance.transform[0]; transform[1] = instance.transform[1]; transform[2] = instance.transform[2]; transform[3] = float32_t4(0, 0, 0, 1); - float32_t4 position = mul(transform, float32_t4(vertex, 1)); + float32_t4 position = math::linalg::promoted_mul(transform, vertex); output.position = mul(pc.MVP, position); output.color = instance.color; diff --git a/include/nbl/ext/DebugDraw/builtin/hlsl/common.hlsl b/include/nbl/ext/DebugDraw/builtin/hlsl/common.hlsl index 2bcd378e40..ec05d5c73b 100644 --- a/include/nbl/ext/DebugDraw/builtin/hlsl/common.hlsl +++ b/include/nbl/ext/DebugDraw/builtin/hlsl/common.hlsl @@ -1,5 +1,5 @@ -#ifndef _DRAW_AABB_COMMON_HLSL -#define _DRAW_AABB_COMMON_HLSL +#ifndef _NBL_DEBUG_DRAW_EXT_COMMON_HLSL +#define _NBL_DEBUG_DRAW_EXT_COMMON_HLSL #include "nbl/builtin/hlsl/cpp_compat.hlsl" @@ -7,7 +7,7 @@ namespace nbl { namespace ext { -namespace debugdraw +namespace debug_draw { struct InstanceData diff --git a/src/nbl/ext/DebugDraw/CDrawAABB.cpp b/src/nbl/ext/DebugDraw/CDrawAABB.cpp index 6cb2f365ec..2a6f6f67ea 100644 --- a/src/nbl/ext/DebugDraw/CDrawAABB.cpp +++ b/src/nbl/ext/DebugDraw/CDrawAABB.cpp @@ -11,7 +11,7 @@ using namespace system; using namespace asset; using namespace hlsl; -namespace nbl::ext::debugdraw +namespace nbl::ext::debug_draw { core::smart_refctd_ptr DrawAABB::create(SCreationParameters&& params) @@ -113,6 +113,12 @@ smart_refctd_ptr DrawAABB::createPipeline(SCreationParamet auto vertexShader = compileShader("aabb_instances.vertex.hlsl", IShader::E_SHADER_STAGE::ESS_VERTEX); auto fragmentShader = compileShader("aabb_instances.fragment.hlsl", IShader::E_SHADER_STAGE::ESS_FRAGMENT); + if (!vertexShader || !fragmentShader) + { + params.utilities->getLogger()->log("Could not compile shaders!", ILogger::ELL_ERROR); + return nullptr; + } + video::IGPUGraphicsPipeline::SCreationParams pipelineParams[1] = {}; pipelineParams[0].layout = params.pipelineLayout.get(); pipelineParams[0].vertexShader = { .shader = vertexShader.get(), .entryPoint = "main" }; diff --git a/src/nbl/ext/DebugDraw/CMakeLists.txt b/src/nbl/ext/DebugDraw/CMakeLists.txt index 3011fe5b4c..7e97cb74a4 100644 --- a/src/nbl/ext/DebugDraw/CMakeLists.txt +++ b/src/nbl/ext/DebugDraw/CMakeLists.txt @@ -35,7 +35,7 @@ if(NBL_EMBED_BUILTIN_RESOURCES) LIST_BUILTIN_RESOURCE(RESOURCES_TO_EMBED "aabb_instances.vertex.hlsl") # (*) LIST_BUILTIN_RESOURCE(RESOURCES_TO_EMBED "aabb_instances.fragment.hlsl") # (*) - ADD_CUSTOM_BUILTIN_RESOURCES(${_BR_TARGET_} RESOURCES_TO_EMBED "${_ARCHIVE_ABSOLUTE_ENTRY_PATH_}" "${_ARCHIVE_ENTRY_KEY_}" "nbl::ext::debugdraw::builtin" "${_OUTPUT_DIRECTORY_HEADER_}" "${_OUTPUT_DIRECTORY_SOURCE_}") + ADD_CUSTOM_BUILTIN_RESOURCES(${_BR_TARGET_} RESOURCES_TO_EMBED "${_ARCHIVE_ABSOLUTE_ENTRY_PATH_}" "${_ARCHIVE_ENTRY_KEY_}" "nbl::ext::debug_draw::builtin" "${_OUTPUT_DIRECTORY_HEADER_}" "${_OUTPUT_DIRECTORY_SOURCE_}") LINK_BUILTIN_RESOURCES_TO_TARGET(${LIB_NAME} ${_BR_TARGET_}) endif() From 33692fd374fa03fcee7a04b348e32ff419401bc1 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 19 Aug 2025 11:31:33 +0700 Subject: [PATCH 07/16] use hlsl cpp compat matrices, aabb --- examples_tests | 2 +- include/nbl/ext/DebugDraw/CDrawAABB.h | 7 +-- .../builtin/hlsl/aabb_instances.vertex.hlsl | 8 +--- .../ext/DebugDraw/builtin/hlsl/common.hlsl | 13 +----- src/nbl/ext/DebugDraw/CDrawAABB.cpp | 45 ++++++++++--------- 5 files changed, 29 insertions(+), 46 deletions(-) diff --git a/examples_tests b/examples_tests index b31cfbae4f..8518c2b342 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit b31cfbae4f6801c592593d39c3045dd62b6c83da +Subproject commit 8518c2b342217548d0c6797b26b5c5e20bc4df60 diff --git a/include/nbl/ext/DebugDraw/CDrawAABB.h b/include/nbl/ext/DebugDraw/CDrawAABB.h index 034a0321bf..721f39b796 100644 --- a/include/nbl/ext/DebugDraw/CDrawAABB.h +++ b/include/nbl/ext/DebugDraw/CDrawAABB.h @@ -55,15 +55,12 @@ class DrawAABB final : public core::IReferenceCounted // records draw command for single AABB, user has to set pipeline outside bool renderSingle(video::IGPUCommandBuffer* commandBuffer); - bool render(video::IGPUCommandBuffer* commandBuffer, video::ISemaphore::SWaitInfo waitInfo, float* cameraMat3x4); + bool render(video::IGPUCommandBuffer* commandBuffer, video::ISemaphore::SWaitInfo waitInfo, const hlsl::float32_t4x4& cameraMat); static std::array getVerticesFromAABB(const core::aabbox3d& aabb); - void addAABB(const core::aabbox3d& aabb, const hlsl::float32_t4& color = { 1,0,0,1 }); void addAABB(const hlsl::shapes::AABB<3,float>& aabb, const hlsl::float32_t4& color = { 1,0,0,1 }); - - void addOBB(const hlsl::shapes::AABB<3, float>& aabb, const hlsl::float32_t3x4 transform, const hlsl::float32_t4& color = { 1,0,0,1 }); - + void addOBB(const hlsl::shapes::AABB<3, float>& aabb, const hlsl::float32_t4x4& transform, const hlsl::float32_t4& color = { 1,0,0,1 }); void clearAABBs(); protected: diff --git a/include/nbl/ext/DebugDraw/builtin/hlsl/aabb_instances.vertex.hlsl b/include/nbl/ext/DebugDraw/builtin/hlsl/aabb_instances.vertex.hlsl index ff993f8541..929ff2e60d 100644 --- a/include/nbl/ext/DebugDraw/builtin/hlsl/aabb_instances.vertex.hlsl +++ b/include/nbl/ext/DebugDraw/builtin/hlsl/aabb_instances.vertex.hlsl @@ -18,13 +18,7 @@ PSInput main() float32_t3 vertex = (bda::__ptr::create(pc.pVertexBuffer) + glsl::gl_VertexIndex()).deref_restrict().load(); InstanceData instance = vk::BufferPointer(pc.pInstanceBuffer + sizeof(InstanceData) * glsl::gl_InstanceIndex()).Get(); - float32_t4x4 transform; - transform[0] = instance.transform[0]; - transform[1] = instance.transform[1]; - transform[2] = instance.transform[2]; - transform[3] = float32_t4(0, 0, 0, 1); - float32_t4 position = math::linalg::promoted_mul(transform, vertex); - output.position = mul(pc.MVP, position); + output.position = math::linalg::promoted_mul(instance.transform, vertex); output.color = instance.color; return output; diff --git a/include/nbl/ext/DebugDraw/builtin/hlsl/common.hlsl b/include/nbl/ext/DebugDraw/builtin/hlsl/common.hlsl index ec05d5c73b..4502b04aa0 100644 --- a/include/nbl/ext/DebugDraw/builtin/hlsl/common.hlsl +++ b/include/nbl/ext/DebugDraw/builtin/hlsl/common.hlsl @@ -12,21 +12,12 @@ namespace debug_draw struct InstanceData { -#ifdef __HLSL_VERSION - float32_t3x4 transform; -#else - float transform[3*4]; -#endif - nbl::hlsl::float32_t4 color; + hlsl::float32_t4x4 transform; + hlsl::float32_t4 color; }; struct SPushConstants { -#ifdef __HLSL_VERSION - float32_t4x4 MVP; -#else - float MVP[4*4]; -#endif uint64_t pVertexBuffer; uint64_t pInstanceBuffer; }; diff --git a/src/nbl/ext/DebugDraw/CDrawAABB.cpp b/src/nbl/ext/DebugDraw/CDrawAABB.cpp index 2a6f6f67ea..799c9f2c9e 100644 --- a/src/nbl/ext/DebugDraw/CDrawAABB.cpp +++ b/src/nbl/ext/DebugDraw/CDrawAABB.cpp @@ -3,6 +3,7 @@ // For conditions of distribution and use, see copyright notice in nabla.h #include "nbl/ext/DebugDraw/CDrawAABB.h" +#include "nbl/builtin/hlsl/math/linalg/fast_affine.hlsl" using namespace nbl; using namespace core; @@ -247,7 +248,7 @@ bool DrawAABB::renderSingle(IGPUCommandBuffer* commandBuffer) return true; } -bool DrawAABB::render(IGPUCommandBuffer* commandBuffer, ISemaphore::SWaitInfo waitInfo, float* cameraMat3x4) +bool DrawAABB::render(IGPUCommandBuffer* commandBuffer, ISemaphore::SWaitInfo waitInfo, const hlsl::float32_t4x4& cameraMat) { using offset_t = SCachedCreationParameters::streaming_buffer_t::size_type; constexpr auto MdiSizes = std::to_array({ sizeof(float32_t3), sizeof(InstanceData) }); @@ -261,17 +262,23 @@ bool DrawAABB::render(IGPUCommandBuffer* commandBuffer, ISemaphore::SWaitInfo wa auto* const streamingPtr = reinterpret_cast(streaming->getBufferPointer()); assert(streamingPtr); - commandBuffer->bindGraphicsPipeline(m_pipeline.get()); // move outside of loop, only bind once + commandBuffer->bindGraphicsPipeline(m_pipeline.get()); commandBuffer->setLineWidth(1.f); - auto instancesIt = m_instances.begin(); + auto instances = m_instances; + for (auto& inst : instances) + { + inst.transform = hlsl::mul(cameraMat, inst.transform); + } + + auto instancesIt = instances.begin(); const uint32_t verticesByteSize = sizeof(float32_t3) * m_unitAABBVertices.size(); const uint32_t availableInstancesByteSize = streaming->getBuffer()->getSize() - verticesByteSize; const uint32_t instancesPerIter = availableInstancesByteSize / sizeof(InstanceData); using suballocator_t = core::LinearAddressAllocatorST; - while (instancesIt != m_instances.end()) + while (instancesIt != instances.end()) { - const uint32_t instanceCount = min(instancesPerIter, m_instances.size()); + const uint32_t instanceCount = min(instancesPerIter, instances.size()); offset_t inputOffset = 0u; offset_t ImaginarySizeUpperBound = 0x1 << 30; suballocator_t imaginaryChunk(nullptr, inputOffset, 0, roundUpToPoT(MaxAlignment), ImaginarySizeUpperBound); @@ -290,7 +297,6 @@ bool DrawAABB::render(IGPUCommandBuffer* commandBuffer, ISemaphore::SWaitInfo wa assert(!streaming->needsManualFlushOrInvalidate()); SPushConstants pc; - memcpy(pc.MVP, cameraMat3x4, sizeof(pc.MVP)); pc.pVertexBuffer = m_cachedCreationParams.streamingBuffer->getBuffer()->getDeviceAddress() + vertexByteOffset; pc.pInstanceBuffer = m_cachedCreationParams.streamingBuffer->getBuffer()->getDeviceAddress() + instancesByteOffset; @@ -342,33 +348,28 @@ std::array DrawAABB::getVerticesFromAABB(const core::aabbox3d& aabb, const hlsl::float32_t4& color) -{ - addAABB(shapes::AABB<3, float>{{aabb.MinEdge.X, aabb.MinEdge.Y, aabb.MinEdge.Z}, { aabb.MaxEdge.X, aabb.MaxEdge.Y, aabb.MaxEdge.Z }}, color); -} - void DrawAABB::addAABB(const hlsl::shapes::AABB<3,float>& aabb, const hlsl::float32_t4& color) { - const auto transform = hlsl::float32_t3x4(1); + const auto transform = hlsl::float32_t4x4(1); addOBB(aabb, transform, color); } -void DrawAABB::addOBB(const hlsl::shapes::AABB<3, float>& aabb, const hlsl::float32_t3x4 transform, const hlsl::float32_t4& color) +void DrawAABB::addOBB(const hlsl::shapes::AABB<3, float>& aabb, const hlsl::float32_t4x4& transform, const hlsl::float32_t4& color) { InstanceData instance; instance.color = color; - - core::matrix3x4SIMD instanceTransform; - instanceTransform.setTranslation(core::vectorSIMDf(aabb.minVx.x, aabb.minVx.y, aabb.minVx.z, 0)); const auto diagonal = aabb.getExtent(); - instanceTransform.setScale(core::vectorSIMDf(diagonal.x, diagonal.y, diagonal.z)); - - core::matrix3x4SIMD worldTransform; - memcpy(worldTransform.pointer(), &transform, sizeof(transform)); - instanceTransform = core::concatenateBFollowedByA(worldTransform, instanceTransform); - memcpy(instance.transform, instanceTransform.pointer(), sizeof(core::matrix3x4SIMD)); + hlsl::float32_t4x4 instanceTransform; + instanceTransform[0][3] = aabb.minVx.x; + instanceTransform[1][3] = aabb.minVx.y; + instanceTransform[2][3] = aabb.minVx.z; + instanceTransform[3][3] = 1.f; + instanceTransform[0][0] = diagonal.x; + instanceTransform[1][1] = diagonal.y; + instanceTransform[2][2] = diagonal.z; + instance.transform = math::linalg::promoted_mul(transform, instanceTransform); m_instances.push_back(instance); } From 72e35698ec59a141aaca94085116868a01ad1c0e Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 19 Aug 2025 15:30:43 +0700 Subject: [PATCH 08/16] change batch render to use indexed draw --- include/nbl/ext/DebugDraw/CDrawAABB.h | 11 +- src/nbl/ext/DebugDraw/CDrawAABB.cpp | 152 ++++++++++++++++++-------- 2 files changed, 117 insertions(+), 46 deletions(-) diff --git a/include/nbl/ext/DebugDraw/CDrawAABB.h b/include/nbl/ext/DebugDraw/CDrawAABB.h index 721f39b796..78b32638e2 100644 --- a/include/nbl/ext/DebugDraw/CDrawAABB.h +++ b/include/nbl/ext/DebugDraw/CDrawAABB.h @@ -15,6 +15,8 @@ namespace nbl::ext::debug_draw class DrawAABB final : public core::IReferenceCounted { public: + static constexpr inline uint32_t IndicesCount = 24u; + struct SCachedCreationParameters { using streaming_buffer_t = video::StreamingTransientDataBufferST>; @@ -30,6 +32,7 @@ class DrawAABB final : public core::IReferenceCounted struct SCreationParameters : SCachedCreationParameters { + video::IQueue* transfer = nullptr; core::smart_refctd_ptr assetManager = nullptr; core::smart_refctd_ptr pipelineLayout; @@ -57,22 +60,24 @@ class DrawAABB final : public core::IReferenceCounted bool render(video::IGPUCommandBuffer* commandBuffer, video::ISemaphore::SWaitInfo waitInfo, const hlsl::float32_t4x4& cameraMat); - static std::array getVerticesFromAABB(const core::aabbox3d& aabb); + //static std::array getVerticesFromAABB(const core::aabbox3d& aabb); void addAABB(const hlsl::shapes::AABB<3,float>& aabb, const hlsl::float32_t4& color = { 1,0,0,1 }); void addOBB(const hlsl::shapes::AABB<3, float>& aabb, const hlsl::float32_t4x4& transform, const hlsl::float32_t4& color = { 1,0,0,1 }); void clearAABBs(); protected: - DrawAABB(SCreationParameters&& _params, core::smart_refctd_ptr pipeline); + DrawAABB(SCreationParameters&& _params, core::smart_refctd_ptr pipeline, core::smart_refctd_ptr indicesBuffer); ~DrawAABB() override; private: static core::smart_refctd_ptr createPipeline(SCreationParameters& params); static bool createStreamingBuffer(SCreationParameters& params); + static core::smart_refctd_ptr createIndicesBuffer(SCreationParameters& params); std::vector m_instances; - std::array m_unitAABBVertices; + std::array m_unitAABBVertices; + core::smart_refctd_ptr m_indicesBuffer; SCachedCreationParameters m_cachedCreationParams; diff --git a/src/nbl/ext/DebugDraw/CDrawAABB.cpp b/src/nbl/ext/DebugDraw/CDrawAABB.cpp index 799c9f2c9e..676f8eafa2 100644 --- a/src/nbl/ext/DebugDraw/CDrawAABB.cpp +++ b/src/nbl/ext/DebugDraw/CDrawAABB.cpp @@ -32,14 +32,31 @@ core::smart_refctd_ptr DrawAABB::create(SCreationParameters&& params) return nullptr; } - return core::smart_refctd_ptr(new DrawAABB(std::move(params), pipeline)); + auto indicesBuffer = createIndicesBuffer(params); + if (!indicesBuffer) + { + logger->log("Failed to create indices buffer!", ILogger::ELL_ERROR); + return nullptr; + } + + return core::smart_refctd_ptr(new DrawAABB(std::move(params), pipeline, indicesBuffer)); } -DrawAABB::DrawAABB(SCreationParameters&& params, smart_refctd_ptr pipeline) - : m_cachedCreationParams(std::move(params)), m_pipeline(pipeline) +DrawAABB::DrawAABB(SCreationParameters&& params, smart_refctd_ptr pipeline, smart_refctd_ptr indicesBuffer) + : m_cachedCreationParams(std::move(params)), m_pipeline(std::move(pipeline)), m_indicesBuffer(std::move(indicesBuffer)) { const auto unitAABB = core::aabbox3d({ 0, 0, 0 }, { 1, 1, 1 }); - m_unitAABBVertices = getVerticesFromAABB(unitAABB); + float32_t3 pMin = { 0, 0, 0 }; + float32_t3 pMax = { 1, 1, 1 }; + + m_unitAABBVertices[0] = float32_t3(pMin.x, pMin.y, pMin.z); + m_unitAABBVertices[1] = float32_t3(pMax.x, pMin.y, pMin.z); + m_unitAABBVertices[2] = float32_t3(pMin.x, pMin.y, pMax.z); + m_unitAABBVertices[3] = float32_t3(pMax.x, pMin.y, pMax.z); + m_unitAABBVertices[4] = float32_t3(pMin.x, pMax.y, pMin.z); + m_unitAABBVertices[5] = float32_t3(pMax.x, pMax.y, pMin.z); + m_unitAABBVertices[6] = float32_t3(pMin.x, pMax.y, pMax.z); + m_unitAABBVertices[7] = float32_t3(pMax.x, pMax.y, pMax.z); } DrawAABB::~DrawAABB() @@ -205,6 +222,53 @@ bool DrawAABB::createStreamingBuffer(SCreationParameters& params) return true; } +smart_refctd_ptr DrawAABB::createIndicesBuffer(SCreationParameters& params) +{ + std::array unitAABBIndices; + unitAABBIndices[0] = 0; + unitAABBIndices[1] = 1; + unitAABBIndices[2] = 0; + unitAABBIndices[3] = 2; + + unitAABBIndices[4] = 3; + unitAABBIndices[5] = 1; + unitAABBIndices[6] = 3; + unitAABBIndices[7] = 2; + + unitAABBIndices[8] = 4; + unitAABBIndices[9] = 5; + unitAABBIndices[10] = 4; + unitAABBIndices[11] = 6; + + unitAABBIndices[12] = 7; + unitAABBIndices[13] = 5; + unitAABBIndices[14] = 7; + unitAABBIndices[15] = 6; + + unitAABBIndices[16] = 0; + unitAABBIndices[17] = 4; + unitAABBIndices[18] = 1; + unitAABBIndices[19] = 5; + + unitAABBIndices[20] = 2; + unitAABBIndices[21] = 6; + unitAABBIndices[22] = 3; + unitAABBIndices[23] = 7; + + IGPUBuffer::SCreationParams bufparams; + bufparams.size = sizeof(uint32_t) * unitAABBIndices.size(); + bufparams.usage = IGPUBuffer::EUF_INDEX_BUFFER_BIT | IGPUBuffer::EUF_TRANSFER_DST_BIT; + + smart_refctd_ptr indicesBuffer; + params.utilities->createFilledDeviceLocalBufferOnDedMem( + SIntendedSubmitInfo{ .queue = params.transfer }, + std::move(bufparams), + unitAABBIndices.data() + ).move_into(indicesBuffer); + + return indicesBuffer; +} + core::smart_refctd_ptr DrawAABB::createDefaultPipelineLayout(video::ILogicalDevice* device, const asset::SPushConstantRange& pcRange) { return device->createPipelineLayout({ &pcRange , 1 }, nullptr, nullptr, nullptr, nullptr); @@ -264,6 +328,8 @@ bool DrawAABB::render(IGPUCommandBuffer* commandBuffer, ISemaphore::SWaitInfo wa commandBuffer->bindGraphicsPipeline(m_pipeline.get()); commandBuffer->setLineWidth(1.f); + asset::SBufferBinding indexBinding = { .offset = 0, .buffer = m_indicesBuffer }; + commandBuffer->bindIndexBuffer(indexBinding, asset::EIT_32BIT); auto instances = m_instances; for (auto& inst : instances) @@ -301,7 +367,7 @@ bool DrawAABB::render(IGPUCommandBuffer* commandBuffer, ISemaphore::SWaitInfo wa pc.pInstanceBuffer = m_cachedCreationParams.streamingBuffer->getBuffer()->getDeviceAddress() + instancesByteOffset; commandBuffer->pushConstants(m_pipeline->getLayout(), ESS_VERTEX, 0, sizeof(SPushConstants), &pc); - commandBuffer->draw(m_unitAABBVertices.size(), instanceCount, 0, 0); + commandBuffer->drawIndexed(IndicesCount, instanceCount, 0, 0, 0); streaming->multi_deallocate(1, &inputOffset, &totalSize, waitInfo); } @@ -309,44 +375,44 @@ bool DrawAABB::render(IGPUCommandBuffer* commandBuffer, ISemaphore::SWaitInfo wa return true; } -std::array DrawAABB::getVerticesFromAABB(const core::aabbox3d& aabb) -{ - const auto& pMin = aabb.MinEdge; - const auto& pMax = aabb.MaxEdge; - - std::array vertices; - vertices[0] = float32_t3(pMin.X, pMin.Y, pMin.Z); - vertices[1] = float32_t3(pMax.X, pMin.Y, pMin.Z); - vertices[2] = float32_t3(pMin.X, pMin.Y, pMin.Z); - vertices[3] = float32_t3(pMin.X, pMin.Y, pMax.Z); - - vertices[4] = float32_t3(pMax.X, pMin.Y, pMax.Z); - vertices[5] = float32_t3(pMax.X, pMin.Y, pMin.Z); - vertices[6] = float32_t3(pMax.X, pMin.Y, pMax.Z); - vertices[7] = float32_t3(pMin.X, pMin.Y, pMax.Z); - - vertices[8] = float32_t3(pMin.X, pMax.Y, pMin.Z); - vertices[9] = float32_t3(pMax.X, pMax.Y, pMin.Z); - vertices[10] = float32_t3(pMin.X, pMax.Y, pMin.Z); - vertices[11] = float32_t3(pMin.X, pMax.Y, pMax.Z); - - vertices[12] = float32_t3(pMax.X, pMax.Y, pMax.Z); - vertices[13] = float32_t3(pMax.X, pMax.Y, pMin.Z); - vertices[14] = float32_t3(pMax.X, pMax.Y, pMax.Z); - vertices[15] = float32_t3(pMin.X, pMax.Y, pMax.Z); - - vertices[16] = float32_t3(pMin.X, pMin.Y, pMin.Z); - vertices[17] = float32_t3(pMin.X, pMax.Y, pMin.Z); - vertices[18] = float32_t3(pMax.X, pMin.Y, pMin.Z); - vertices[19] = float32_t3(pMax.X, pMax.Y, pMin.Z); - - vertices[20] = float32_t3(pMin.X, pMin.Y, pMax.Z); - vertices[21] = float32_t3(pMin.X, pMax.Y, pMax.Z); - vertices[22] = float32_t3(pMax.X, pMin.Y, pMax.Z); - vertices[23] = float32_t3(pMax.X, pMax.Y, pMax.Z); - - return vertices; -} +//std::array DrawAABB::getVerticesFromAABB(const core::aabbox3d& aabb) +//{ +// const auto& pMin = aabb.MinEdge; +// const auto& pMax = aabb.MaxEdge; +// +// std::array vertices; +// vertices[0] = float32_t3(pMin.X, pMin.Y, pMin.Z); // 0 +// vertices[1] = float32_t3(pMax.X, pMin.Y, pMin.Z); // 1 +// vertices[2] = float32_t3(pMin.X, pMin.Y, pMin.Z); // 0 +// vertices[3] = float32_t3(pMin.X, pMin.Y, pMax.Z); // 2 +// +// vertices[4] = float32_t3(pMax.X, pMin.Y, pMax.Z); // 3 +// vertices[5] = float32_t3(pMax.X, pMin.Y, pMin.Z); // 1 +// vertices[6] = float32_t3(pMax.X, pMin.Y, pMax.Z); // 3 +// vertices[7] = float32_t3(pMin.X, pMin.Y, pMax.Z); // 2 +// +// vertices[8] = float32_t3(pMin.X, pMax.Y, pMin.Z); // 4 +// vertices[9] = float32_t3(pMax.X, pMax.Y, pMin.Z); // 5 +// vertices[10] = float32_t3(pMin.X, pMax.Y, pMin.Z); // 4 +// vertices[11] = float32_t3(pMin.X, pMax.Y, pMax.Z); // 6 +// +// vertices[12] = float32_t3(pMax.X, pMax.Y, pMax.Z); // 7 +// vertices[13] = float32_t3(pMax.X, pMax.Y, pMin.Z); // 5 +// vertices[14] = float32_t3(pMax.X, pMax.Y, pMax.Z); // 7 +// vertices[15] = float32_t3(pMin.X, pMax.Y, pMax.Z); // 6 +// +// vertices[16] = float32_t3(pMin.X, pMin.Y, pMin.Z); // 0 +// vertices[17] = float32_t3(pMin.X, pMax.Y, pMin.Z); // 4 +// vertices[18] = float32_t3(pMax.X, pMin.Y, pMin.Z); // 1 +// vertices[19] = float32_t3(pMax.X, pMax.Y, pMin.Z); // 5 +// +// vertices[20] = float32_t3(pMin.X, pMin.Y, pMax.Z); // 2 +// vertices[21] = float32_t3(pMin.X, pMax.Y, pMax.Z); // 6 +// vertices[22] = float32_t3(pMax.X, pMin.Y, pMax.Z); // 3 +// vertices[23] = float32_t3(pMax.X, pMax.Y, pMax.Z); // 7 +// +// return vertices; +//} void DrawAABB::addAABB(const hlsl::shapes::AABB<3,float>& aabb, const hlsl::float32_t4& color) { From 5285e78b92a907c39f067696564110757e904a67 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 20 Aug 2025 10:22:49 +0700 Subject: [PATCH 09/16] simplified single AABB draw --- include/nbl/ext/DebugDraw/CDrawAABB.h | 25 +-- .../ext/DebugDraw/builtin/hlsl/common.hlsl | 6 + .../DebugDraw/builtin/hlsl/single.vertex.hlsl | 23 +++ src/nbl/ext/DebugDraw/CDrawAABB.cpp | 184 ++++++++---------- src/nbl/ext/DebugDraw/CMakeLists.txt | 1 + 5 files changed, 129 insertions(+), 110 deletions(-) create mode 100644 include/nbl/ext/DebugDraw/builtin/hlsl/single.vertex.hlsl diff --git a/include/nbl/ext/DebugDraw/CDrawAABB.h b/include/nbl/ext/DebugDraw/CDrawAABB.h index 78b32638e2..dad33bea27 100644 --- a/include/nbl/ext/DebugDraw/CDrawAABB.h +++ b/include/nbl/ext/DebugDraw/CDrawAABB.h @@ -16,6 +16,7 @@ class DrawAABB final : public core::IReferenceCounted { public: static constexpr inline uint32_t IndicesCount = 24u; + static constexpr inline uint32_t VerticesCount = 8u; struct SCachedCreationParameters { @@ -35,53 +36,55 @@ class DrawAABB final : public core::IReferenceCounted video::IQueue* transfer = nullptr; core::smart_refctd_ptr assetManager = nullptr; - core::smart_refctd_ptr pipelineLayout; + core::smart_refctd_ptr singlePipelineLayout; + core::smart_refctd_ptr batchPipelineLayout; core::smart_refctd_ptr renderpass = nullptr; }; // creates an instance that can draw one AABB via push constant or multiple using streaming buffer static core::smart_refctd_ptr create(SCreationParameters&& params); - // creates default pipeline layout for push constant version - static core::smart_refctd_ptr createDefaultPipelineLayout(video::ILogicalDevice* device, const asset::SPushConstantRange& pcRange); + // creates pipeline layout from push constant range + static core::smart_refctd_ptr createPipelineLayoutFromPCRange(video::ILogicalDevice* device, const asset::SPushConstantRange& pcRange); // creates default pipeline layout for streaming version static core::smart_refctd_ptr createDefaultPipelineLayout(video::ILogicalDevice* device); - static core::smart_refctd_ptr createDefaultPipeline(video::ILogicalDevice* device, video::IGPUPipelineLayout* layout, video::IGPURenderpass* renderpass, video::IGPUGraphicsPipeline::SShaderSpecInfo& vertex, video::IGPUGraphicsPipeline::SShaderSpecInfo& fragment); - //! mounts the extension's archive to given system - useful if you want to create your own shaders with common header included static const core::smart_refctd_ptr mount(core::smart_refctd_ptr logger, system::ISystem* system, const std::string_view archiveAlias = ""); inline const SCachedCreationParameters& getCreationParameters() const { return m_cachedCreationParams; } // records draw command for single AABB, user has to set pipeline outside - bool renderSingle(video::IGPUCommandBuffer* commandBuffer); + bool renderSingle(video::IGPUCommandBuffer* commandBuffer, const hlsl::shapes::AABB<3, float>& aabb, const hlsl::float32_t4& color, const hlsl::float32_t4x4& cameraMat); bool render(video::IGPUCommandBuffer* commandBuffer, video::ISemaphore::SWaitInfo waitInfo, const hlsl::float32_t4x4& cameraMat); - //static std::array getVerticesFromAABB(const core::aabbox3d& aabb); + static hlsl::float32_t4x4 getTransformFromAABB(const hlsl::shapes::AABB<3, float>& aabb); void addAABB(const hlsl::shapes::AABB<3,float>& aabb, const hlsl::float32_t4& color = { 1,0,0,1 }); void addOBB(const hlsl::shapes::AABB<3, float>& aabb, const hlsl::float32_t4x4& transform, const hlsl::float32_t4& color = { 1,0,0,1 }); void clearAABBs(); protected: - DrawAABB(SCreationParameters&& _params, core::smart_refctd_ptr pipeline, core::smart_refctd_ptr indicesBuffer); + DrawAABB(SCreationParameters&& _params, core::smart_refctd_ptr singlePipeline, core::smart_refctd_ptr batchPipeline, + core::smart_refctd_ptr indicesBuffer, core::smart_refctd_ptr verticesBuffer); ~DrawAABB() override; private: - static core::smart_refctd_ptr createPipeline(SCreationParameters& params); + static core::smart_refctd_ptr createPipeline(SCreationParameters& params, const video::IGPUPipelineLayout* pipelineLayout, const std::string& vsPath, const std::string& fsPath); static bool createStreamingBuffer(SCreationParameters& params); static core::smart_refctd_ptr createIndicesBuffer(SCreationParameters& params); + static core::smart_refctd_ptr createVerticesBuffer(SCreationParameters& params); std::vector m_instances; - std::array m_unitAABBVertices; core::smart_refctd_ptr m_indicesBuffer; + core::smart_refctd_ptr m_verticesBuffer; SCachedCreationParameters m_cachedCreationParams; - core::smart_refctd_ptr m_pipeline; + core::smart_refctd_ptr m_singlePipeline; + core::smart_refctd_ptr m_batchPipeline; }; } diff --git a/include/nbl/ext/DebugDraw/builtin/hlsl/common.hlsl b/include/nbl/ext/DebugDraw/builtin/hlsl/common.hlsl index 4502b04aa0..03a3bbfa49 100644 --- a/include/nbl/ext/DebugDraw/builtin/hlsl/common.hlsl +++ b/include/nbl/ext/DebugDraw/builtin/hlsl/common.hlsl @@ -16,6 +16,12 @@ struct InstanceData hlsl::float32_t4 color; }; +struct SSinglePushConstants +{ + uint64_t pVertexBuffer; + InstanceData instance; +}; + struct SPushConstants { uint64_t pVertexBuffer; diff --git a/include/nbl/ext/DebugDraw/builtin/hlsl/single.vertex.hlsl b/include/nbl/ext/DebugDraw/builtin/hlsl/single.vertex.hlsl new file mode 100644 index 0000000000..e9b68a811c --- /dev/null +++ b/include/nbl/ext/DebugDraw/builtin/hlsl/single.vertex.hlsl @@ -0,0 +1,23 @@ +#pragma shader_stage(vertex) + +#include "nbl/builtin/hlsl/math/linalg/fast_affine.hlsl" +#include "nbl/builtin/hlsl/glsl_compat/core.hlsl" +#include "nbl/builtin/hlsl/bda/__ptr.hlsl" +#include "common.hlsl" + +using namespace nbl::hlsl; +using namespace nbl::ext::debug_draw; + +[[vk::push_constant]] SSinglePushConstants pc; + +[shader("vertex")] +PSInput main() +{ + PSInput output; + float32_t3 vertex = (bda::__ptr::create(pc.pVertexBuffer) + glsl::gl_VertexIndex()).deref_restrict().load(); + + output.position = math::linalg::promoted_mul(pc.instance.transform, vertex); + output.color = pc.instance.color; + + return output; +} \ No newline at end of file diff --git a/src/nbl/ext/DebugDraw/CDrawAABB.cpp b/src/nbl/ext/DebugDraw/CDrawAABB.cpp index 676f8eafa2..53a6e3cebb 100644 --- a/src/nbl/ext/DebugDraw/CDrawAABB.cpp +++ b/src/nbl/ext/DebugDraw/CDrawAABB.cpp @@ -19,8 +19,14 @@ core::smart_refctd_ptr DrawAABB::create(SCreationParameters&& params) { auto* const logger = params.utilities->getLogger(); - auto pipeline = createPipeline(params); - if (!pipeline) + auto singlePipeline = createPipeline(params, params.singlePipelineLayout.get(), "single.vertex.hlsl", "aabb_instances.fragment.hlsl"); + if (!singlePipeline) + { + logger->log("Failed to create pipeline!", ILogger::ELL_ERROR); + return nullptr; + } + auto batchPipeline = createPipeline(params, params.batchPipelineLayout.get(), "aabb_instances.vertex.hlsl", "aabb_instances.fragment.hlsl"); + if (!batchPipeline) { logger->log("Failed to create pipeline!", ILogger::ELL_ERROR); return nullptr; @@ -38,25 +44,21 @@ core::smart_refctd_ptr DrawAABB::create(SCreationParameters&& params) logger->log("Failed to create indices buffer!", ILogger::ELL_ERROR); return nullptr; } + auto verticesBuffer = createVerticesBuffer(params); + if (!verticesBuffer) + { + logger->log("Failed to create vertices buffer!", ILogger::ELL_ERROR); + return nullptr; + } - return core::smart_refctd_ptr(new DrawAABB(std::move(params), pipeline, indicesBuffer)); + return core::smart_refctd_ptr(new DrawAABB(std::move(params), singlePipeline, batchPipeline, indicesBuffer, verticesBuffer)); } -DrawAABB::DrawAABB(SCreationParameters&& params, smart_refctd_ptr pipeline, smart_refctd_ptr indicesBuffer) - : m_cachedCreationParams(std::move(params)), m_pipeline(std::move(pipeline)), m_indicesBuffer(std::move(indicesBuffer)) +DrawAABB::DrawAABB(SCreationParameters&& params, core::smart_refctd_ptr singlePipeline, smart_refctd_ptr batchPipeline, + smart_refctd_ptr indicesBuffer, smart_refctd_ptr verticesBuffer) + : m_cachedCreationParams(std::move(params)), m_singlePipeline(std::move(singlePipeline)), m_batchPipeline(std::move(batchPipeline)), + m_indicesBuffer(std::move(indicesBuffer)), m_verticesBuffer(std::move(verticesBuffer)) { - const auto unitAABB = core::aabbox3d({ 0, 0, 0 }, { 1, 1, 1 }); - float32_t3 pMin = { 0, 0, 0 }; - float32_t3 pMax = { 1, 1, 1 }; - - m_unitAABBVertices[0] = float32_t3(pMin.x, pMin.y, pMin.z); - m_unitAABBVertices[1] = float32_t3(pMax.x, pMin.y, pMin.z); - m_unitAABBVertices[2] = float32_t3(pMin.x, pMin.y, pMax.z); - m_unitAABBVertices[3] = float32_t3(pMax.x, pMin.y, pMax.z); - m_unitAABBVertices[4] = float32_t3(pMin.x, pMax.y, pMin.z); - m_unitAABBVertices[5] = float32_t3(pMax.x, pMax.y, pMin.z); - m_unitAABBVertices[6] = float32_t3(pMin.x, pMax.y, pMax.z); - m_unitAABBVertices[7] = float32_t3(pMax.x, pMax.y, pMax.z); } DrawAABB::~DrawAABB() @@ -88,7 +90,7 @@ const smart_refctd_ptr DrawAABB::mount(smart_refctd_ptr l return smart_refctd_ptr(archive); } -smart_refctd_ptr DrawAABB::createPipeline(SCreationParameters& params) +smart_refctd_ptr DrawAABB::createPipeline(SCreationParameters& params, const IGPUPipelineLayout* pipelineLayout, const std::string& vsPath, const std::string& fsPath) { auto system = smart_refctd_ptr(params.assetManager->getSystem()); auto* set = params.assetManager->getCompilerSet(); @@ -128,8 +130,8 @@ smart_refctd_ptr DrawAABB::createPipeline(SCreationParamet if (!system->isDirectory(path(NBL_ARCHIVE_ENTRY.data()))) mount(smart_refctd_ptr(params.utilities->getLogger()), system.get(), NBL_ARCHIVE_ENTRY); - auto vertexShader = compileShader("aabb_instances.vertex.hlsl", IShader::E_SHADER_STAGE::ESS_VERTEX); - auto fragmentShader = compileShader("aabb_instances.fragment.hlsl", IShader::E_SHADER_STAGE::ESS_FRAGMENT); + auto vertexShader = compileShader(vsPath, IShader::E_SHADER_STAGE::ESS_VERTEX); + auto fragmentShader = compileShader(fsPath, IShader::E_SHADER_STAGE::ESS_FRAGMENT); if (!vertexShader || !fragmentShader) { @@ -138,7 +140,7 @@ smart_refctd_ptr DrawAABB::createPipeline(SCreationParamet } video::IGPUGraphicsPipeline::SCreationParams pipelineParams[1] = {}; - pipelineParams[0].layout = params.pipelineLayout.get(); + pipelineParams[0].layout = pipelineLayout; pipelineParams[0].vertexShader = { .shader = vertexShader.get(), .entryPoint = "main" }; pipelineParams[0].fragmentShader = { .shader = fragmentShader.get(), .entryPoint = "main" }; pipelineParams[0].cached = { @@ -269,7 +271,37 @@ smart_refctd_ptr DrawAABB::createIndicesBuffer(SCreationParameters& return indicesBuffer; } -core::smart_refctd_ptr DrawAABB::createDefaultPipelineLayout(video::ILogicalDevice* device, const asset::SPushConstantRange& pcRange) +smart_refctd_ptr DrawAABB::createVerticesBuffer(SCreationParameters& params) +{ + const auto unitAABB = core::aabbox3d({ 0, 0, 0 }, { 1, 1, 1 }); + float32_t3 pMin = { 0, 0, 0 }; + float32_t3 pMax = { 1, 1, 1 }; + + std::array unitAABBVertices; + unitAABBVertices[0] = float32_t3(pMin.x, pMin.y, pMin.z); + unitAABBVertices[1] = float32_t3(pMax.x, pMin.y, pMin.z); + unitAABBVertices[2] = float32_t3(pMin.x, pMin.y, pMax.z); + unitAABBVertices[3] = float32_t3(pMax.x, pMin.y, pMax.z); + unitAABBVertices[4] = float32_t3(pMin.x, pMax.y, pMin.z); + unitAABBVertices[5] = float32_t3(pMax.x, pMax.y, pMin.z); + unitAABBVertices[6] = float32_t3(pMin.x, pMax.y, pMax.z); + unitAABBVertices[7] = float32_t3(pMax.x, pMax.y, pMax.z); + + IGPUBuffer::SCreationParams bufparams; + bufparams.size = sizeof(float32_t3) * unitAABBVertices.size(); + bufparams.usage = IGPUBuffer::EUF_STORAGE_BUFFER_BIT | IGPUBuffer::EUF_TRANSFER_DST_BIT | IGPUBuffer::EUF_SHADER_DEVICE_ADDRESS_BIT; + + smart_refctd_ptr vertexBuffer; + params.utilities->createFilledDeviceLocalBufferOnDedMem( + SIntendedSubmitInfo{ .queue = params.transfer }, + std::move(bufparams), + unitAABBVertices.data() + ).move_into(vertexBuffer); + + return vertexBuffer; +} + +core::smart_refctd_ptr DrawAABB::createPipelineLayoutFromPCRange(video::ILogicalDevice* device, const asset::SPushConstantRange& pcRange) { return device->createPipelineLayout({ &pcRange , 1 }, nullptr, nullptr, nullptr, nullptr); } @@ -284,30 +316,22 @@ core::smart_refctd_ptr DrawAABB::createDefaultPipelin return device->createPipelineLayout({ &pcRange , 1 }, nullptr, nullptr, nullptr, nullptr); } -smart_refctd_ptr DrawAABB::createDefaultPipeline(video::ILogicalDevice* device, video::IGPUPipelineLayout* layout, video::IGPURenderpass* renderpass, video::IGPUGraphicsPipeline::SShaderSpecInfo& vertex, video::IGPUGraphicsPipeline::SShaderSpecInfo& fragment) +bool DrawAABB::renderSingle(IGPUCommandBuffer* commandBuffer, const hlsl::shapes::AABB<3, float>& aabb, const hlsl::float32_t4& color, const hlsl::float32_t4x4& cameraMat) { - smart_refctd_ptr pipeline; - - video::IGPUGraphicsPipeline::SCreationParams params[1] = {}; - params[0].layout = layout; - params[0].vertexShader = vertex; - params[0].fragmentShader = fragment; - params[0].cached = { - .primitiveAssembly = { - .primitiveType = asset::E_PRIMITIVE_TOPOLOGY::EPT_LINE_LIST, - } - }; - params[0].renderpass = renderpass; - - device->createGraphicsPipelines(nullptr, params, &pipeline); + commandBuffer->bindGraphicsPipeline(m_singlePipeline.get()); + commandBuffer->setLineWidth(1.f); + asset::SBufferBinding indexBinding = { .offset = 0, .buffer = m_indicesBuffer }; + commandBuffer->bindIndexBuffer(indexBinding, asset::EIT_32BIT); - return pipeline; -} + SSinglePushConstants pc; + pc.pVertexBuffer = m_verticesBuffer->getDeviceAddress(); -bool DrawAABB::renderSingle(IGPUCommandBuffer* commandBuffer) -{ - commandBuffer->setLineWidth(1.f); - commandBuffer->draw(24, 1, 0, 0); + hlsl::float32_t4x4 instanceTransform = getTransformFromAABB(aabb); + pc.instance.transform = hlsl::mul(cameraMat, instanceTransform); + pc.instance.color = color; + + commandBuffer->pushConstants(m_singlePipeline->getLayout(), ESS_VERTEX, 0, sizeof(SSinglePushConstants), &pc); + commandBuffer->drawIndexed(IndicesCount, 1, 0, 0, 0); return true; } @@ -326,7 +350,7 @@ bool DrawAABB::render(IGPUCommandBuffer* commandBuffer, ISemaphore::SWaitInfo wa auto* const streamingPtr = reinterpret_cast(streaming->getBufferPointer()); assert(streamingPtr); - commandBuffer->bindGraphicsPipeline(m_pipeline.get()); + commandBuffer->bindGraphicsPipeline(m_batchPipeline.get()); commandBuffer->setLineWidth(1.f); asset::SBufferBinding indexBinding = { .offset = 0, .buffer = m_indicesBuffer }; commandBuffer->bindIndexBuffer(indexBinding, asset::EIT_32BIT); @@ -338,9 +362,7 @@ bool DrawAABB::render(IGPUCommandBuffer* commandBuffer, ISemaphore::SWaitInfo wa } auto instancesIt = instances.begin(); - const uint32_t verticesByteSize = sizeof(float32_t3) * m_unitAABBVertices.size(); - const uint32_t availableInstancesByteSize = streaming->getBuffer()->getSize() - verticesByteSize; - const uint32_t instancesPerIter = availableInstancesByteSize / sizeof(InstanceData); + const uint32_t instancesPerIter = streaming->getBuffer()->getSize() / sizeof(InstanceData); using suballocator_t = core::LinearAddressAllocatorST; while (instancesIt != instances.end()) { @@ -348,7 +370,6 @@ bool DrawAABB::render(IGPUCommandBuffer* commandBuffer, ISemaphore::SWaitInfo wa offset_t inputOffset = 0u; offset_t ImaginarySizeUpperBound = 0x1 << 30; suballocator_t imaginaryChunk(nullptr, inputOffset, 0, roundUpToPoT(MaxAlignment), ImaginarySizeUpperBound); - uint32_t vertexByteOffset = imaginaryChunk.alloc_addr(verticesByteSize, sizeof(float32_t3)); uint32_t instancesByteOffset = imaginaryChunk.alloc_addr(sizeof(InstanceData) * instanceCount, sizeof(InstanceData)); const uint32_t totalSize = imaginaryChunk.get_allocated_size(); @@ -356,17 +377,16 @@ bool DrawAABB::render(IGPUCommandBuffer* commandBuffer, ISemaphore::SWaitInfo wa std::chrono::steady_clock::time_point waitTill = std::chrono::steady_clock::now() + std::chrono::milliseconds(1u); streaming->multi_allocate(waitTill, 1, &inputOffset, &totalSize, &MaxAlignment); - memcpy(streamingPtr + vertexByteOffset, m_unitAABBVertices.data(), sizeof(m_unitAABBVertices[0]) * m_unitAABBVertices.size()); memcpy(streamingPtr + instancesByteOffset, std::addressof(*instancesIt), sizeof(InstanceData) * instanceCount); instancesIt += instanceCount; assert(!streaming->needsManualFlushOrInvalidate()); SPushConstants pc; - pc.pVertexBuffer = m_cachedCreationParams.streamingBuffer->getBuffer()->getDeviceAddress() + vertexByteOffset; + pc.pVertexBuffer = m_verticesBuffer->getDeviceAddress(); pc.pInstanceBuffer = m_cachedCreationParams.streamingBuffer->getBuffer()->getDeviceAddress() + instancesByteOffset; - commandBuffer->pushConstants(m_pipeline->getLayout(), ESS_VERTEX, 0, sizeof(SPushConstants), &pc); + commandBuffer->pushConstants(m_batchPipeline->getLayout(), ESS_VERTEX, 0, sizeof(SPushConstants), &pc); commandBuffer->drawIndexed(IndicesCount, instanceCount, 0, 0, 0); streaming->multi_deallocate(1, &inputOffset, &totalSize, waitInfo); @@ -375,44 +395,19 @@ bool DrawAABB::render(IGPUCommandBuffer* commandBuffer, ISemaphore::SWaitInfo wa return true; } -//std::array DrawAABB::getVerticesFromAABB(const core::aabbox3d& aabb) -//{ -// const auto& pMin = aabb.MinEdge; -// const auto& pMax = aabb.MaxEdge; -// -// std::array vertices; -// vertices[0] = float32_t3(pMin.X, pMin.Y, pMin.Z); // 0 -// vertices[1] = float32_t3(pMax.X, pMin.Y, pMin.Z); // 1 -// vertices[2] = float32_t3(pMin.X, pMin.Y, pMin.Z); // 0 -// vertices[3] = float32_t3(pMin.X, pMin.Y, pMax.Z); // 2 -// -// vertices[4] = float32_t3(pMax.X, pMin.Y, pMax.Z); // 3 -// vertices[5] = float32_t3(pMax.X, pMin.Y, pMin.Z); // 1 -// vertices[6] = float32_t3(pMax.X, pMin.Y, pMax.Z); // 3 -// vertices[7] = float32_t3(pMin.X, pMin.Y, pMax.Z); // 2 -// -// vertices[8] = float32_t3(pMin.X, pMax.Y, pMin.Z); // 4 -// vertices[9] = float32_t3(pMax.X, pMax.Y, pMin.Z); // 5 -// vertices[10] = float32_t3(pMin.X, pMax.Y, pMin.Z); // 4 -// vertices[11] = float32_t3(pMin.X, pMax.Y, pMax.Z); // 6 -// -// vertices[12] = float32_t3(pMax.X, pMax.Y, pMax.Z); // 7 -// vertices[13] = float32_t3(pMax.X, pMax.Y, pMin.Z); // 5 -// vertices[14] = float32_t3(pMax.X, pMax.Y, pMax.Z); // 7 -// vertices[15] = float32_t3(pMin.X, pMax.Y, pMax.Z); // 6 -// -// vertices[16] = float32_t3(pMin.X, pMin.Y, pMin.Z); // 0 -// vertices[17] = float32_t3(pMin.X, pMax.Y, pMin.Z); // 4 -// vertices[18] = float32_t3(pMax.X, pMin.Y, pMin.Z); // 1 -// vertices[19] = float32_t3(pMax.X, pMax.Y, pMin.Z); // 5 -// -// vertices[20] = float32_t3(pMin.X, pMin.Y, pMax.Z); // 2 -// vertices[21] = float32_t3(pMin.X, pMax.Y, pMax.Z); // 6 -// vertices[22] = float32_t3(pMax.X, pMin.Y, pMax.Z); // 3 -// vertices[23] = float32_t3(pMax.X, pMax.Y, pMax.Z); // 7 -// -// return vertices; -//} +hlsl::float32_t4x4 DrawAABB::getTransformFromAABB(const hlsl::shapes::AABB<3, float>& aabb) +{ + const auto diagonal = aabb.getExtent(); + hlsl::float32_t4x4 transform; + transform[0][3] = aabb.minVx.x; + transform[1][3] = aabb.minVx.y; + transform[2][3] = aabb.minVx.z; + transform[3][3] = 1.f; + transform[0][0] = diagonal.x; + transform[1][1] = diagonal.y; + transform[2][2] = diagonal.z; + return transform; +} void DrawAABB::addAABB(const hlsl::shapes::AABB<3,float>& aabb, const hlsl::float32_t4& color) { @@ -424,17 +419,8 @@ void DrawAABB::addOBB(const hlsl::shapes::AABB<3, float>& aabb, const hlsl::floa { InstanceData instance; instance.color = color; - const auto diagonal = aabb.getExtent(); - - hlsl::float32_t4x4 instanceTransform; - instanceTransform[0][3] = aabb.minVx.x; - instanceTransform[1][3] = aabb.minVx.y; - instanceTransform[2][3] = aabb.minVx.z; - instanceTransform[3][3] = 1.f; - instanceTransform[0][0] = diagonal.x; - instanceTransform[1][1] = diagonal.y; - instanceTransform[2][2] = diagonal.z; + hlsl::float32_t4x4 instanceTransform = getTransformFromAABB(aabb); instance.transform = math::linalg::promoted_mul(transform, instanceTransform); m_instances.push_back(instance); } diff --git a/src/nbl/ext/DebugDraw/CMakeLists.txt b/src/nbl/ext/DebugDraw/CMakeLists.txt index 7e97cb74a4..b62d06f518 100644 --- a/src/nbl/ext/DebugDraw/CMakeLists.txt +++ b/src/nbl/ext/DebugDraw/CMakeLists.txt @@ -32,6 +32,7 @@ if(NBL_EMBED_BUILTIN_RESOURCES) set(_BR_TARGET_ extDebugDrawbuiltinResourceData) LIST_BUILTIN_RESOURCE(RESOURCES_TO_EMBED "common.hlsl") + LIST_BUILTIN_RESOURCE(RESOURCES_TO_EMBED "single.vertex.hlsl") # (*) LIST_BUILTIN_RESOURCE(RESOURCES_TO_EMBED "aabb_instances.vertex.hlsl") # (*) LIST_BUILTIN_RESOURCE(RESOURCES_TO_EMBED "aabb_instances.fragment.hlsl") # (*) From 328aa3429528c6fd841cf3a70359139e601eaa36 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 20 Aug 2025 10:59:45 +0700 Subject: [PATCH 10/16] change batch render to take span of InstanceData --- include/nbl/ext/DebugDraw/CDrawAABB.h | 7 +------ src/nbl/ext/DebugDraw/CDrawAABB.cpp | 29 +++++---------------------- 2 files changed, 6 insertions(+), 30 deletions(-) diff --git a/include/nbl/ext/DebugDraw/CDrawAABB.h b/include/nbl/ext/DebugDraw/CDrawAABB.h index dad33bea27..089e885887 100644 --- a/include/nbl/ext/DebugDraw/CDrawAABB.h +++ b/include/nbl/ext/DebugDraw/CDrawAABB.h @@ -58,14 +58,10 @@ class DrawAABB final : public core::IReferenceCounted // records draw command for single AABB, user has to set pipeline outside bool renderSingle(video::IGPUCommandBuffer* commandBuffer, const hlsl::shapes::AABB<3, float>& aabb, const hlsl::float32_t4& color, const hlsl::float32_t4x4& cameraMat); - bool render(video::IGPUCommandBuffer* commandBuffer, video::ISemaphore::SWaitInfo waitInfo, const hlsl::float32_t4x4& cameraMat); + bool render(video::IGPUCommandBuffer* commandBuffer, video::ISemaphore::SWaitInfo waitInfo, std::span aabbInstances, const hlsl::float32_t4x4& cameraMat); static hlsl::float32_t4x4 getTransformFromAABB(const hlsl::shapes::AABB<3, float>& aabb); - void addAABB(const hlsl::shapes::AABB<3,float>& aabb, const hlsl::float32_t4& color = { 1,0,0,1 }); - void addOBB(const hlsl::shapes::AABB<3, float>& aabb, const hlsl::float32_t4x4& transform, const hlsl::float32_t4& color = { 1,0,0,1 }); - void clearAABBs(); - protected: DrawAABB(SCreationParameters&& _params, core::smart_refctd_ptr singlePipeline, core::smart_refctd_ptr batchPipeline, core::smart_refctd_ptr indicesBuffer, core::smart_refctd_ptr verticesBuffer); @@ -77,7 +73,6 @@ class DrawAABB final : public core::IReferenceCounted static core::smart_refctd_ptr createIndicesBuffer(SCreationParameters& params); static core::smart_refctd_ptr createVerticesBuffer(SCreationParameters& params); - std::vector m_instances; core::smart_refctd_ptr m_indicesBuffer; core::smart_refctd_ptr m_verticesBuffer; diff --git a/src/nbl/ext/DebugDraw/CDrawAABB.cpp b/src/nbl/ext/DebugDraw/CDrawAABB.cpp index 53a6e3cebb..3c40f9306e 100644 --- a/src/nbl/ext/DebugDraw/CDrawAABB.cpp +++ b/src/nbl/ext/DebugDraw/CDrawAABB.cpp @@ -336,7 +336,7 @@ bool DrawAABB::renderSingle(IGPUCommandBuffer* commandBuffer, const hlsl::shapes return true; } -bool DrawAABB::render(IGPUCommandBuffer* commandBuffer, ISemaphore::SWaitInfo waitInfo, const hlsl::float32_t4x4& cameraMat) +bool DrawAABB::render(IGPUCommandBuffer* commandBuffer, ISemaphore::SWaitInfo waitInfo, std::span aabbInstances, const hlsl::float32_t4x4& cameraMat) { using offset_t = SCachedCreationParameters::streaming_buffer_t::size_type; constexpr auto MdiSizes = std::to_array({ sizeof(float32_t3), sizeof(InstanceData) }); @@ -355,9 +355,11 @@ bool DrawAABB::render(IGPUCommandBuffer* commandBuffer, ISemaphore::SWaitInfo wa asset::SBufferBinding indexBinding = { .offset = 0, .buffer = m_indicesBuffer }; commandBuffer->bindIndexBuffer(indexBinding, asset::EIT_32BIT); - auto instances = m_instances; - for (auto& inst : instances) + std::vector instances(aabbInstances.size()); + for (uint32_t i = 0; i < aabbInstances.size(); i++) { + auto& inst = instances[i]; + inst = aabbInstances[i]; inst.transform = hlsl::mul(cameraMat, inst.transform); } @@ -409,25 +411,4 @@ hlsl::float32_t4x4 DrawAABB::getTransformFromAABB(const hlsl::shapes::AABB<3, fl return transform; } -void DrawAABB::addAABB(const hlsl::shapes::AABB<3,float>& aabb, const hlsl::float32_t4& color) -{ - const auto transform = hlsl::float32_t4x4(1); - addOBB(aabb, transform, color); -} - -void DrawAABB::addOBB(const hlsl::shapes::AABB<3, float>& aabb, const hlsl::float32_t4x4& transform, const hlsl::float32_t4& color) -{ - InstanceData instance; - instance.color = color; - - hlsl::float32_t4x4 instanceTransform = getTransformFromAABB(aabb); - instance.transform = math::linalg::promoted_mul(transform, instanceTransform); - m_instances.push_back(instance); -} - -void DrawAABB::clearAABBs() -{ - m_instances.clear(); -} - } From a14c9dca918353cf713a500b95eec92b4bd728eb Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 20 Aug 2025 11:44:35 +0700 Subject: [PATCH 11/16] latest example --- examples_tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples_tests b/examples_tests index 8518c2b342..323c782226 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 8518c2b342217548d0c6797b26b5c5e20bc4df60 +Subproject commit 323c782226a402e0e4d21e902029a0602f616cff From 9a35c9f6a30aa7ceb4ab7868acae4790a3833299 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 20 Aug 2025 12:00:50 +0700 Subject: [PATCH 12/16] removed vertex buffer, use const vertex array in shader instead --- include/nbl/ext/DebugDraw/CDrawAABB.h | 4 +- .../builtin/hlsl/aabb_instances.vertex.hlsl | 14 +++++- .../ext/DebugDraw/builtin/hlsl/common.hlsl | 2 - .../DebugDraw/builtin/hlsl/single.vertex.hlsl | 13 +++++- src/nbl/ext/DebugDraw/CDrawAABB.cpp | 45 ++----------------- 5 files changed, 28 insertions(+), 50 deletions(-) diff --git a/include/nbl/ext/DebugDraw/CDrawAABB.h b/include/nbl/ext/DebugDraw/CDrawAABB.h index 089e885887..1efe973d10 100644 --- a/include/nbl/ext/DebugDraw/CDrawAABB.h +++ b/include/nbl/ext/DebugDraw/CDrawAABB.h @@ -64,17 +64,15 @@ class DrawAABB final : public core::IReferenceCounted protected: DrawAABB(SCreationParameters&& _params, core::smart_refctd_ptr singlePipeline, core::smart_refctd_ptr batchPipeline, - core::smart_refctd_ptr indicesBuffer, core::smart_refctd_ptr verticesBuffer); + core::smart_refctd_ptr indicesBuffer); ~DrawAABB() override; private: static core::smart_refctd_ptr createPipeline(SCreationParameters& params, const video::IGPUPipelineLayout* pipelineLayout, const std::string& vsPath, const std::string& fsPath); static bool createStreamingBuffer(SCreationParameters& params); static core::smart_refctd_ptr createIndicesBuffer(SCreationParameters& params); - static core::smart_refctd_ptr createVerticesBuffer(SCreationParameters& params); core::smart_refctd_ptr m_indicesBuffer; - core::smart_refctd_ptr m_verticesBuffer; SCachedCreationParameters m_cachedCreationParams; diff --git a/include/nbl/ext/DebugDraw/builtin/hlsl/aabb_instances.vertex.hlsl b/include/nbl/ext/DebugDraw/builtin/hlsl/aabb_instances.vertex.hlsl index 929ff2e60d..bb535a7216 100644 --- a/include/nbl/ext/DebugDraw/builtin/hlsl/aabb_instances.vertex.hlsl +++ b/include/nbl/ext/DebugDraw/builtin/hlsl/aabb_instances.vertex.hlsl @@ -13,9 +13,19 @@ using namespace nbl::ext::debug_draw; [shader("vertex")] PSInput main() { - PSInput output; + const float32_t3 unitAABBVertices[8] = { + float32_t3(0.0, 0.0, 0.0), + float32_t3(1.0, 0.0, 0.0), + float32_t3(0.0, 0.0, 1.0), + float32_t3(1.0, 0.0, 1.0), + float32_t3(0.0, 1.0, 0.0), + float32_t3(1.0, 1.0, 0.0), + float32_t3(0.0, 1.0, 1.0), + float32_t3(1.0, 1.0, 1.0) + }; - float32_t3 vertex = (bda::__ptr::create(pc.pVertexBuffer) + glsl::gl_VertexIndex()).deref_restrict().load(); + PSInput output; + float32_t3 vertex = unitAABBVertices[glsl::gl_VertexIndex()]; InstanceData instance = vk::BufferPointer(pc.pInstanceBuffer + sizeof(InstanceData) * glsl::gl_InstanceIndex()).Get(); output.position = math::linalg::promoted_mul(instance.transform, vertex); diff --git a/include/nbl/ext/DebugDraw/builtin/hlsl/common.hlsl b/include/nbl/ext/DebugDraw/builtin/hlsl/common.hlsl index 03a3bbfa49..a178d45465 100644 --- a/include/nbl/ext/DebugDraw/builtin/hlsl/common.hlsl +++ b/include/nbl/ext/DebugDraw/builtin/hlsl/common.hlsl @@ -18,13 +18,11 @@ struct InstanceData struct SSinglePushConstants { - uint64_t pVertexBuffer; InstanceData instance; }; struct SPushConstants { - uint64_t pVertexBuffer; uint64_t pInstanceBuffer; }; diff --git a/include/nbl/ext/DebugDraw/builtin/hlsl/single.vertex.hlsl b/include/nbl/ext/DebugDraw/builtin/hlsl/single.vertex.hlsl index e9b68a811c..e1a426dec8 100644 --- a/include/nbl/ext/DebugDraw/builtin/hlsl/single.vertex.hlsl +++ b/include/nbl/ext/DebugDraw/builtin/hlsl/single.vertex.hlsl @@ -13,8 +13,19 @@ using namespace nbl::ext::debug_draw; [shader("vertex")] PSInput main() { + const float32_t3 unitAABBVertices[8] = { + float32_t3(0.0, 0.0, 0.0), + float32_t3(1.0, 0.0, 0.0), + float32_t3(0.0, 0.0, 1.0), + float32_t3(1.0, 0.0, 1.0), + float32_t3(0.0, 1.0, 0.0), + float32_t3(1.0, 1.0, 0.0), + float32_t3(0.0, 1.0, 1.0), + float32_t3(1.0, 1.0, 1.0) + }; + PSInput output; - float32_t3 vertex = (bda::__ptr::create(pc.pVertexBuffer) + glsl::gl_VertexIndex()).deref_restrict().load(); + float32_t3 vertex = unitAABBVertices[glsl::gl_VertexIndex()]; output.position = math::linalg::promoted_mul(pc.instance.transform, vertex); output.color = pc.instance.color; diff --git a/src/nbl/ext/DebugDraw/CDrawAABB.cpp b/src/nbl/ext/DebugDraw/CDrawAABB.cpp index 3c40f9306e..a11052aa76 100644 --- a/src/nbl/ext/DebugDraw/CDrawAABB.cpp +++ b/src/nbl/ext/DebugDraw/CDrawAABB.cpp @@ -44,20 +44,13 @@ core::smart_refctd_ptr DrawAABB::create(SCreationParameters&& params) logger->log("Failed to create indices buffer!", ILogger::ELL_ERROR); return nullptr; } - auto verticesBuffer = createVerticesBuffer(params); - if (!verticesBuffer) - { - logger->log("Failed to create vertices buffer!", ILogger::ELL_ERROR); - return nullptr; - } - return core::smart_refctd_ptr(new DrawAABB(std::move(params), singlePipeline, batchPipeline, indicesBuffer, verticesBuffer)); + return core::smart_refctd_ptr(new DrawAABB(std::move(params), singlePipeline, batchPipeline, indicesBuffer)); } -DrawAABB::DrawAABB(SCreationParameters&& params, core::smart_refctd_ptr singlePipeline, smart_refctd_ptr batchPipeline, - smart_refctd_ptr indicesBuffer, smart_refctd_ptr verticesBuffer) +DrawAABB::DrawAABB(SCreationParameters&& params, core::smart_refctd_ptr singlePipeline, smart_refctd_ptr batchPipeline, smart_refctd_ptr indicesBuffer) : m_cachedCreationParams(std::move(params)), m_singlePipeline(std::move(singlePipeline)), m_batchPipeline(std::move(batchPipeline)), - m_indicesBuffer(std::move(indicesBuffer)), m_verticesBuffer(std::move(verticesBuffer)) + m_indicesBuffer(std::move(indicesBuffer)) { } @@ -271,36 +264,6 @@ smart_refctd_ptr DrawAABB::createIndicesBuffer(SCreationParameters& return indicesBuffer; } -smart_refctd_ptr DrawAABB::createVerticesBuffer(SCreationParameters& params) -{ - const auto unitAABB = core::aabbox3d({ 0, 0, 0 }, { 1, 1, 1 }); - float32_t3 pMin = { 0, 0, 0 }; - float32_t3 pMax = { 1, 1, 1 }; - - std::array unitAABBVertices; - unitAABBVertices[0] = float32_t3(pMin.x, pMin.y, pMin.z); - unitAABBVertices[1] = float32_t3(pMax.x, pMin.y, pMin.z); - unitAABBVertices[2] = float32_t3(pMin.x, pMin.y, pMax.z); - unitAABBVertices[3] = float32_t3(pMax.x, pMin.y, pMax.z); - unitAABBVertices[4] = float32_t3(pMin.x, pMax.y, pMin.z); - unitAABBVertices[5] = float32_t3(pMax.x, pMax.y, pMin.z); - unitAABBVertices[6] = float32_t3(pMin.x, pMax.y, pMax.z); - unitAABBVertices[7] = float32_t3(pMax.x, pMax.y, pMax.z); - - IGPUBuffer::SCreationParams bufparams; - bufparams.size = sizeof(float32_t3) * unitAABBVertices.size(); - bufparams.usage = IGPUBuffer::EUF_STORAGE_BUFFER_BIT | IGPUBuffer::EUF_TRANSFER_DST_BIT | IGPUBuffer::EUF_SHADER_DEVICE_ADDRESS_BIT; - - smart_refctd_ptr vertexBuffer; - params.utilities->createFilledDeviceLocalBufferOnDedMem( - SIntendedSubmitInfo{ .queue = params.transfer }, - std::move(bufparams), - unitAABBVertices.data() - ).move_into(vertexBuffer); - - return vertexBuffer; -} - core::smart_refctd_ptr DrawAABB::createPipelineLayoutFromPCRange(video::ILogicalDevice* device, const asset::SPushConstantRange& pcRange) { return device->createPipelineLayout({ &pcRange , 1 }, nullptr, nullptr, nullptr, nullptr); @@ -324,7 +287,6 @@ bool DrawAABB::renderSingle(IGPUCommandBuffer* commandBuffer, const hlsl::shapes commandBuffer->bindIndexBuffer(indexBinding, asset::EIT_32BIT); SSinglePushConstants pc; - pc.pVertexBuffer = m_verticesBuffer->getDeviceAddress(); hlsl::float32_t4x4 instanceTransform = getTransformFromAABB(aabb); pc.instance.transform = hlsl::mul(cameraMat, instanceTransform); @@ -385,7 +347,6 @@ bool DrawAABB::render(IGPUCommandBuffer* commandBuffer, ISemaphore::SWaitInfo wa assert(!streaming->needsManualFlushOrInvalidate()); SPushConstants pc; - pc.pVertexBuffer = m_verticesBuffer->getDeviceAddress(); pc.pInstanceBuffer = m_cachedCreationParams.streamingBuffer->getBuffer()->getDeviceAddress() + instancesByteOffset; commandBuffer->pushConstants(m_batchPipeline->getLayout(), ESS_VERTEX, 0, sizeof(SPushConstants), &pc); From c6bd10b3a98bf0c29c0bb5ce76e32f88e738d31f Mon Sep 17 00:00:00 2001 From: keptsecret Date: Wed, 20 Aug 2025 16:15:36 +0700 Subject: [PATCH 13/16] validate creation params, added draw modes at create time --- examples_tests | 2 +- include/nbl/ext/DebugDraw/CDrawAABB.h | 10 +++++ src/nbl/ext/DebugDraw/CDrawAABB.cpp | 64 ++++++++++++++++++++++++--- 3 files changed, 68 insertions(+), 8 deletions(-) diff --git a/examples_tests b/examples_tests index 323c782226..f75dc215f9 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 323c782226a402e0e4d21e902029a0602f616cff +Subproject commit f75dc215f94f7a30c5083433f78e8937e154da44 diff --git a/include/nbl/ext/DebugDraw/CDrawAABB.h b/include/nbl/ext/DebugDraw/CDrawAABB.h index 1efe973d10..a8e3205f22 100644 --- a/include/nbl/ext/DebugDraw/CDrawAABB.h +++ b/include/nbl/ext/DebugDraw/CDrawAABB.h @@ -18,6 +18,13 @@ class DrawAABB final : public core::IReferenceCounted static constexpr inline uint32_t IndicesCount = 24u; static constexpr inline uint32_t VerticesCount = 8u; + enum DrawMode : uint16_t + { + ADM_DRAW_SINGLE = 0b01, + ADM_DRAW_BATCH = 0b10, + ADM_DRAW_BOTH = 0b11 + }; + struct SCachedCreationParameters { using streaming_buffer_t = video::StreamingTransientDataBufferST>; @@ -25,6 +32,8 @@ class DrawAABB final : public core::IReferenceCounted static constexpr inline auto RequiredAllocateFlags = core::bitflag(video::IDeviceMemoryAllocation::EMAF_DEVICE_ADDRESS_BIT); static constexpr inline auto RequiredUsageFlags = core::bitflag(asset::IBuffer::EUF_STORAGE_BUFFER_BIT) | asset::IBuffer::EUF_SHADER_DEVICE_ADDRESS_BIT; + DrawMode drawMode = ADM_DRAW_BOTH; + core::smart_refctd_ptr utilities; //! optional, default MDI buffer allocated if not provided @@ -68,6 +77,7 @@ class DrawAABB final : public core::IReferenceCounted ~DrawAABB() override; private: + static bool validateCreationParameters(SCreationParameters& params); static core::smart_refctd_ptr createPipeline(SCreationParameters& params, const video::IGPUPipelineLayout* pipelineLayout, const std::string& vsPath, const std::string& fsPath); static bool createStreamingBuffer(SCreationParameters& params); static core::smart_refctd_ptr createIndicesBuffer(SCreationParameters& params); diff --git a/src/nbl/ext/DebugDraw/CDrawAABB.cpp b/src/nbl/ext/DebugDraw/CDrawAABB.cpp index a11052aa76..f3f33d2733 100644 --- a/src/nbl/ext/DebugDraw/CDrawAABB.cpp +++ b/src/nbl/ext/DebugDraw/CDrawAABB.cpp @@ -19,17 +19,32 @@ core::smart_refctd_ptr DrawAABB::create(SCreationParameters&& params) { auto* const logger = params.utilities->getLogger(); - auto singlePipeline = createPipeline(params, params.singlePipelineLayout.get(), "single.vertex.hlsl", "aabb_instances.fragment.hlsl"); - if (!singlePipeline) + if (!validateCreationParameters(params)) { - logger->log("Failed to create pipeline!", ILogger::ELL_ERROR); + logger->log("Failed creation parameters validation!", ILogger::ELL_ERROR); return nullptr; } - auto batchPipeline = createPipeline(params, params.batchPipelineLayout.get(), "aabb_instances.vertex.hlsl", "aabb_instances.fragment.hlsl"); - if (!batchPipeline) + + smart_refctd_ptr singlePipeline = nullptr; + if (params.drawMode & ADM_DRAW_SINGLE) { - logger->log("Failed to create pipeline!", ILogger::ELL_ERROR); - return nullptr; + singlePipeline = createPipeline(params, params.singlePipelineLayout.get(), "single.vertex.hlsl", "aabb_instances.fragment.hlsl"); + if (!singlePipeline) + { + logger->log("Failed to create pipeline!", ILogger::ELL_ERROR); + return nullptr; + } + } + + smart_refctd_ptr batchPipeline = nullptr; + if (params.drawMode & ADM_DRAW_BATCH) + { + batchPipeline = createPipeline(params, params.batchPipelineLayout.get(), "aabb_instances.vertex.hlsl", "aabb_instances.fragment.hlsl"); + if (!batchPipeline) + { + logger->log("Failed to create pipeline!", ILogger::ELL_ERROR); + return nullptr; + } } if (!createStreamingBuffer(params)) @@ -83,6 +98,29 @@ const smart_refctd_ptr DrawAABB::mount(smart_refctd_ptr l return smart_refctd_ptr(archive); } +bool DrawAABB::validateCreationParameters(SCreationParameters& creationParams) +{ + const auto validation = std::to_array + ({ + std::make_pair(bool(creationParams.assetManager), "Invalid `creationParams.assetManager` is nullptr!"), + std::make_pair(bool(creationParams.assetManager->getSystem()), "Invalid `creationParams.assetManager->getSystem()` is nullptr!"), + std::make_pair(bool(creationParams.utilities), "Invalid `creationParams.utilities` is nullptr!"), + std::make_pair(bool(creationParams.transfer), "Invalid `creationParams.transfer` is nullptr!"), + std::make_pair(bool(creationParams.renderpass), "Invalid `creationParams.renderpass` is nullptr!"), + (creationParams.assetManager && creationParams.utilities && creationParams.transfer && creationParams.renderpass) ? std::make_pair(bool(creationParams.utilities->getLogicalDevice()->getPhysicalDevice()->getQueueFamilyProperties()[creationParams.transfer->getFamilyIndex()].queueFlags.hasFlags(IQueue::FAMILY_FLAGS::TRANSFER_BIT)), "Invalid `creationParams.transfer` is not capable of transfer operations!") : std::make_pair(false, "Pass valid required DrawAABB::S_CREATION_PARAMETERS!") + }); + + system::logger_opt_ptr logger = creationParams.utilities->getLogger(); + for (const auto& [ok, error] : validation) + if (!ok) + { + logger.log(error, ILogger::ELL_ERROR); + return false; + } + + return true; +} + smart_refctd_ptr DrawAABB::createPipeline(SCreationParameters& params, const IGPUPipelineLayout* pipelineLayout, const std::string& vsPath, const std::string& fsPath) { auto system = smart_refctd_ptr(params.assetManager->getSystem()); @@ -281,6 +319,12 @@ core::smart_refctd_ptr DrawAABB::createDefaultPipelin bool DrawAABB::renderSingle(IGPUCommandBuffer* commandBuffer, const hlsl::shapes::AABB<3, float>& aabb, const hlsl::float32_t4& color, const hlsl::float32_t4x4& cameraMat) { + if (!(m_cachedCreationParams.drawMode & ADM_DRAW_SINGLE)) + { + m_cachedCreationParams.utilities->getLogger()->log("DrawAABB has not been enabled for draw single!", ILogger::ELL_ERROR); + return false; + } + commandBuffer->bindGraphicsPipeline(m_singlePipeline.get()); commandBuffer->setLineWidth(1.f); asset::SBufferBinding indexBinding = { .offset = 0, .buffer = m_indicesBuffer }; @@ -300,6 +344,12 @@ bool DrawAABB::renderSingle(IGPUCommandBuffer* commandBuffer, const hlsl::shapes bool DrawAABB::render(IGPUCommandBuffer* commandBuffer, ISemaphore::SWaitInfo waitInfo, std::span aabbInstances, const hlsl::float32_t4x4& cameraMat) { + if (!(m_cachedCreationParams.drawMode & ADM_DRAW_BATCH)) + { + m_cachedCreationParams.utilities->getLogger()->log("DrawAABB has not been enabled for draw batches!", ILogger::ELL_ERROR); + return false; + } + using offset_t = SCachedCreationParameters::streaming_buffer_t::size_type; constexpr auto MdiSizes = std::to_array({ sizeof(float32_t3), sizeof(InstanceData) }); // shared nPoT alignment needs to be divisible by all smaller ones to satisfy an allocation from all From e5ceb1b35175c2a3a7c6e2899e00a73c8a28e3d9 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Mon, 8 Sep 2025 10:56:03 +0700 Subject: [PATCH 14/16] enable debug draw by default --- CMakeLists.txt | 2 +- examples_tests | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c2c1c21f8..25134b04e7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -182,7 +182,7 @@ option(NBL_FAST_MATH "Enable fast low-precision math" ON) option(NBL_BUILD_EXAMPLES "Enable building examples" ON) option(NBL_BUILD_MITSUBA_LOADER "Enable nbl::ext::MitsubaLoader?" OFF) # TODO: once it compies turn this ON by default! option(NBL_BUILD_IMGUI "Enable nbl::ext::ImGui?" ON) -option(NBL_BUILD_DEBUG_DRAW "Enable Nabla Debug Draw extension?" OFF) +option(NBL_BUILD_DEBUG_DRAW "Enable Nabla Debug Draw extension?" ON) option(NBL_BUILD_OPTIX "Enable nbl::ext::OptiX?" OFF) if(NBL_COMPILE_WITH_CUDA) diff --git a/examples_tests b/examples_tests index 347933d952..3b1016e58a 160000 --- a/examples_tests +++ b/examples_tests @@ -1 +1 @@ -Subproject commit 347933d9523618715f6373a97cba85f38e177985 +Subproject commit 3b1016e58ab5d9cb53bd9c37707dad356d30173d From bfa233fe68521c52f7484a7ebf04ecef8d099b80 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 16 Sep 2025 11:13:54 +0700 Subject: [PATCH 15/16] fix embed builtin resource build --- src/nbl/ext/DebugDraw/CDrawAABB.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/nbl/ext/DebugDraw/CDrawAABB.cpp b/src/nbl/ext/DebugDraw/CDrawAABB.cpp index f3f33d2733..f445398e0c 100644 --- a/src/nbl/ext/DebugDraw/CDrawAABB.cpp +++ b/src/nbl/ext/DebugDraw/CDrawAABB.cpp @@ -5,6 +5,10 @@ #include "nbl/ext/DebugDraw/CDrawAABB.h" #include "nbl/builtin/hlsl/math/linalg/fast_affine.hlsl" +#ifdef NBL_EMBED_BUILTIN_RESOURCES +#include "nbl/ext/debug_draw/builtin/CArchive.h" +#endif + using namespace nbl; using namespace core; using namespace video; From 3b67580f67281905c2c6d694ed405148931841e0 Mon Sep 17 00:00:00 2001 From: Arkadiusz Lachowicz Date: Tue, 16 Sep 2025 21:21:17 +0200 Subject: [PATCH 16/16] resolve https://github.com/Devsh-Graphics-Programming/Nabla/pull/900#discussion_r2352585679 --- .../ext/DebugDraw/builtin/hlsl/aabb_instances.fragment.hlsl | 2 +- .../nbl/ext/DebugDraw/builtin/hlsl/aabb_instances.vertex.hlsl | 2 +- include/nbl/ext/DebugDraw/builtin/hlsl/single.vertex.hlsl | 2 +- include/nbl/system/ISystem.h | 1 + src/nbl/ext/DebugDraw/CDrawAABB.cpp | 2 +- src/nbl/ext/DebugDraw/CMakeLists.txt | 4 ++-- 6 files changed, 7 insertions(+), 6 deletions(-) diff --git a/include/nbl/ext/DebugDraw/builtin/hlsl/aabb_instances.fragment.hlsl b/include/nbl/ext/DebugDraw/builtin/hlsl/aabb_instances.fragment.hlsl index 686e8934db..09a12f3d07 100644 --- a/include/nbl/ext/DebugDraw/builtin/hlsl/aabb_instances.fragment.hlsl +++ b/include/nbl/ext/DebugDraw/builtin/hlsl/aabb_instances.fragment.hlsl @@ -1,6 +1,6 @@ #pragma shader_stage(fragment) -#include "common.hlsl" +#include "nbl/ext/DebugDraw/builtin/hlsl/common.hlsl" using namespace nbl::ext::debug_draw; diff --git a/include/nbl/ext/DebugDraw/builtin/hlsl/aabb_instances.vertex.hlsl b/include/nbl/ext/DebugDraw/builtin/hlsl/aabb_instances.vertex.hlsl index bb535a7216..5f67aa2f1e 100644 --- a/include/nbl/ext/DebugDraw/builtin/hlsl/aabb_instances.vertex.hlsl +++ b/include/nbl/ext/DebugDraw/builtin/hlsl/aabb_instances.vertex.hlsl @@ -3,7 +3,7 @@ #include "nbl/builtin/hlsl/math/linalg/fast_affine.hlsl" #include "nbl/builtin/hlsl/glsl_compat/core.hlsl" #include "nbl/builtin/hlsl/bda/__ptr.hlsl" -#include "common.hlsl" +#include "nbl/ext/DebugDraw/builtin/hlsl/common.hlsl" using namespace nbl::hlsl; using namespace nbl::ext::debug_draw; diff --git a/include/nbl/ext/DebugDraw/builtin/hlsl/single.vertex.hlsl b/include/nbl/ext/DebugDraw/builtin/hlsl/single.vertex.hlsl index e1a426dec8..64ca75d5ab 100644 --- a/include/nbl/ext/DebugDraw/builtin/hlsl/single.vertex.hlsl +++ b/include/nbl/ext/DebugDraw/builtin/hlsl/single.vertex.hlsl @@ -3,7 +3,7 @@ #include "nbl/builtin/hlsl/math/linalg/fast_affine.hlsl" #include "nbl/builtin/hlsl/glsl_compat/core.hlsl" #include "nbl/builtin/hlsl/bda/__ptr.hlsl" -#include "common.hlsl" +#include "nbl/ext/DebugDraw/builtin/hlsl/common.hlsl" using namespace nbl::hlsl; using namespace nbl::ext::debug_draw; diff --git a/include/nbl/system/ISystem.h b/include/nbl/system/ISystem.h index 4e02221d7c..65f0351582 100644 --- a/include/nbl/system/ISystem.h +++ b/include/nbl/system/ISystem.h @@ -70,6 +70,7 @@ class NBL_API2 ISystem : public core::IReferenceCounted // virtual inline bool isDirectory(const system::path& p) const { + // TODO: fix bug, input "nbl/ext/DebugDraw/builtin/hlsl" -> returs true when no such dir present in mounted stuff due to how it uses parent paths in loop (goes up up till matches "nbl" builtin archive and thinks it resolved the requested dir) if (isPathReadOnly(p)) return p.extension()==""; // TODO: this is a temporary decision until we figure out how to check if a file is directory in android APK else diff --git a/src/nbl/ext/DebugDraw/CDrawAABB.cpp b/src/nbl/ext/DebugDraw/CDrawAABB.cpp index f445398e0c..d231f21e3e 100644 --- a/src/nbl/ext/DebugDraw/CDrawAABB.cpp +++ b/src/nbl/ext/DebugDraw/CDrawAABB.cpp @@ -162,7 +162,7 @@ smart_refctd_ptr DrawAABB::createPipeline(SCreationParamet return params.utilities->getLogicalDevice()->compileShader({ shaderSrc.get() }); }; - if (!system->isDirectory(path(NBL_ARCHIVE_ENTRY.data()))) + if (!system->exists(path(NBL_ARCHIVE_ENTRY) / "common.hlsl", {})) mount(smart_refctd_ptr(params.utilities->getLogger()), system.get(), NBL_ARCHIVE_ENTRY); auto vertexShader = compileShader(vsPath, IShader::E_SHADER_STAGE::ESS_VERTEX); diff --git a/src/nbl/ext/DebugDraw/CMakeLists.txt b/src/nbl/ext/DebugDraw/CMakeLists.txt index b62d06f518..4cb2ee54cf 100644 --- a/src/nbl/ext/DebugDraw/CMakeLists.txt +++ b/src/nbl/ext/DebugDraw/CMakeLists.txt @@ -20,8 +20,8 @@ nbl_create_ext_library_project( ) # this should be standard for all extensions -set(_ARCHIVE_ENTRY_KEY_ "DebugDraw/builtin/hlsl") # then each one has unique archive key -get_filename_component(_ARCHIVE_ABSOLUTE_ENTRY_PATH_ "${NBL_EXT_INTERNAL_INCLUDE_DIR}/nbl/ext" ABSOLUTE) +set(_ARCHIVE_ENTRY_KEY_ "nbl/ext/DebugDraw/builtin/hlsl") # then each one has unique archive key +get_filename_component(_ARCHIVE_ABSOLUTE_ENTRY_PATH_ "${NBL_EXT_INTERNAL_INCLUDE_DIR}" ABSOLUTE) get_filename_component(_OUTPUT_DIRECTORY_SOURCE_ "${CMAKE_CURRENT_BINARY_DIR}/src" ABSOLUTE) get_filename_component(_OUTPUT_DIRECTORY_HEADER_ "${CMAKE_CURRENT_BINARY_DIR}/include" ABSOLUTE)