From ca8612807ff4f025f9d923436c065699ec5a0002 Mon Sep 17 00:00:00 2001 From: keptsecret Date: Tue, 1 Jul 2025 11:07:58 +0700 Subject: [PATCH 01/13] 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/13] 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/13] 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/13] 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/13] 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/13] 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/13] 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/13] 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/13] 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/13] 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/13] 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/13] 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/13] 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