Skip to content

Commit a40f540

Browse files
committed
some fixes to draw aabb
1 parent 1f73ca9 commit a40f540

File tree

3 files changed

+126
-98
lines changed

3 files changed

+126
-98
lines changed

examples_tests

include/nbl/ext/DebugDraw/CDrawAABB.h

Lines changed: 98 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,21 @@
22
// This file is part of the "Nabla Engine".
33
// For conditions of distribution and use, see copyright notice in nabla.h
44

5-
#ifndef _NBL_EXT_DRAW_AABB_H_
6-
#define _NBL_EXT_DRAW_AABB_H_
5+
#ifndef _NBL_EXT_DEBUG_DRAW_DRAW_AABB_H_
6+
#define _NBL_EXT_DEBUG_DRAW_DRAW_AABB_H_
77

88
#include "nbl/video/declarations.h"
99
#include "nbl/builtin/hlsl/cpp_compat.hlsl"
1010
#include "nbl/builtin/hlsl/shapes/aabb.hlsl"
11+
#include "nbl/builtin/hlsl/math/linalg/fast_affine.hlsl"
1112
#include "nbl/ext/DebugDraw/builtin/hlsl/common.hlsl"
1213

1314
namespace nbl::ext::debug_draw
1415
{
15-
class DrawAABB final : public core::IReferenceCounted
16-
{
16+
class DrawAABB final : public core::IReferenceCounted
17+
{
1718
public:
1819
static constexpr inline uint32_t IndicesCount = 24u;
19-
static constexpr inline uint32_t VerticesCount = 8u;
2020

2121
enum DrawMode : uint16_t
2222
{
@@ -39,7 +39,8 @@ class DrawAABB final : public core::IReferenceCounted
3939
//! optional, default MDI buffer allocated if not provided
4040
core::smart_refctd_ptr<streaming_buffer_t> streamingBuffer = nullptr;
4141
};
42-
42+
43+
// only used to make the 24 element index buffer and instanced pipeline on create
4344
struct SCreationParameters : SCachedCreationParameters
4445
{
4546
video::IQueue* transfer = nullptr;
@@ -48,6 +49,29 @@ class DrawAABB final : public core::IReferenceCounted
4849
core::smart_refctd_ptr<video::IGPUPipelineLayout> singlePipelineLayout;
4950
core::smart_refctd_ptr<video::IGPUPipelineLayout> batchPipelineLayout;
5051
core::smart_refctd_ptr<video::IGPURenderpass> renderpass = nullptr;
52+
53+
inline bool validate() const
54+
{
55+
const auto validation = std::to_array
56+
({
57+
std::make_pair(bool(assetManager), "Invalid `creationParams.assetManager` is nullptr!"),
58+
std::make_pair(bool(assetManager->getSystem()), "Invalid `creationParams.assetManager->getSystem()` is nullptr!"),
59+
std::make_pair(bool(utilities), "Invalid `creationParams.utilities` is nullptr!"),
60+
std::make_pair(bool(transfer), "Invalid `creationParams.transfer` is nullptr!"),
61+
std::make_pair(bool(renderpass), "Invalid `creationParams.renderpass` is nullptr!"),
62+
(assetManager && utilities && transfer && renderpass) ? std::make_pair(bool(utilities->getLogicalDevice()->getPhysicalDevice()->getQueueFamilyProperties()[transfer->getFamilyIndex()].queueFlags.hasFlags(video::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!")
63+
});
64+
65+
system::logger_opt_ptr logger = utilities->getLogger();
66+
for (const auto& [ok, error] : validation)
67+
if (!ok)
68+
{
69+
logger.log(error, system::ILogger::ELL_ERROR);
70+
return false;
71+
}
72+
73+
return true;
74+
}
5175
};
5276

5377
// creates an instance that can draw one AABB via push constant or multiple using streaming buffer
@@ -67,7 +91,73 @@ class DrawAABB final : public core::IReferenceCounted
6791
// records draw command for single AABB, user has to set pipeline outside
6892
bool renderSingle(video::IGPUCommandBuffer* commandBuffer, const hlsl::shapes::AABB<3, float>& aabb, const hlsl::float32_t4& color, const hlsl::float32_t4x4& cameraMat);
6993

70-
bool render(video::IGPUCommandBuffer* commandBuffer, video::ISemaphore::SWaitInfo waitInfo, std::span<const InstanceData> aabbInstances, const hlsl::float32_t4x4& cameraMat);
94+
// records draw command for rendering batch of AABB instances as InstanceData
95+
// user has to set span of filled-in InstanceData; camera matrix used in push constant
96+
inline bool render(video::IGPUCommandBuffer* commandBuffer, video::ISemaphore::SWaitInfo waitInfo, std::span<const InstanceData> aabbInstances, const hlsl::float32_t4x4& cameraMat)
97+
{
98+
if (!(m_cachedCreationParams.drawMode & ADM_DRAW_BATCH))
99+
{
100+
m_cachedCreationParams.utilities->getLogger()->log("DrawAABB has not been enabled for draw batches!", system::ILogger::ELL_ERROR);
101+
return false;
102+
}
103+
104+
using offset_t = SCachedCreationParameters::streaming_buffer_t::size_type;
105+
constexpr auto MdiSizes = std::to_array<offset_t>({ sizeof(hlsl::float32_t3), sizeof(InstanceData) });
106+
// shared nPoT alignment needs to be divisible by all smaller ones to satisfy an allocation from all
107+
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); });
108+
// allocator initialization needs us to round up to PoT
109+
const auto MaxPOTAlignment = hlsl::roundUpToPoT(MaxAlignment);
110+
111+
auto* streaming = m_cachedCreationParams.streamingBuffer.get();
112+
113+
auto* const streamingPtr = reinterpret_cast<uint8_t*>(streaming->getBufferPointer());
114+
assert(streamingPtr);
115+
116+
commandBuffer->bindGraphicsPipeline(m_batchPipeline.get());
117+
commandBuffer->setLineWidth(1.f);
118+
asset::SBufferBinding<video::IGPUBuffer> indexBinding = { .offset = 0, .buffer = m_indicesBuffer };
119+
commandBuffer->bindIndexBuffer(indexBinding, asset::EIT_32BIT);
120+
121+
std::vector<InstanceData> instances(aabbInstances.size());
122+
for (uint32_t i = 0; i < aabbInstances.size(); i++)
123+
{
124+
auto& inst = instances[i];
125+
inst = aabbInstances[i];
126+
inst.transform = hlsl::mul(cameraMat, inst.transform);
127+
}
128+
129+
auto instancesIt = instances.begin();
130+
const uint32_t instancesPerIter = streaming->getBuffer()->getSize() / sizeof(InstanceData);
131+
using suballocator_t = core::LinearAddressAllocatorST<offset_t>;
132+
while (instancesIt != instances.end())
133+
{
134+
const uint32_t instanceCount = hlsl::min<uint32_t>(instancesPerIter, instances.size());
135+
offset_t inputOffset = 0u;
136+
offset_t ImaginarySizeUpperBound = 0x1 << 30;
137+
suballocator_t imaginaryChunk(nullptr, inputOffset, 0, hlsl::roundUpToPoT(MaxAlignment), ImaginarySizeUpperBound);
138+
uint32_t instancesByteOffset = imaginaryChunk.alloc_addr(sizeof(InstanceData) * instanceCount, sizeof(InstanceData));
139+
const uint32_t totalSize = imaginaryChunk.get_allocated_size();
140+
141+
inputOffset = SCachedCreationParameters::streaming_buffer_t::invalid_value;
142+
std::chrono::steady_clock::time_point waitTill = std::chrono::steady_clock::now() + std::chrono::milliseconds(1u);
143+
streaming->multi_allocate(waitTill, 1, &inputOffset, &totalSize, &MaxAlignment);
144+
145+
memcpy(streamingPtr + instancesByteOffset, std::addressof(*instancesIt), sizeof(InstanceData) * instanceCount);
146+
instancesIt += instanceCount;
147+
148+
assert(!streaming->needsManualFlushOrInvalidate());
149+
150+
SPushConstants pc;
151+
pc.pInstanceBuffer = m_cachedCreationParams.streamingBuffer->getBuffer()->getDeviceAddress() + instancesByteOffset;
152+
153+
commandBuffer->pushConstants(m_batchPipeline->getLayout(), asset::IShader::E_SHADER_STAGE::ESS_VERTEX, 0, sizeof(SPushConstants), &pc);
154+
commandBuffer->drawIndexed(IndicesCount, instanceCount, 0, 0, 0);
155+
156+
streaming->multi_deallocate(1, &inputOffset, &totalSize, waitInfo);
157+
}
158+
159+
return true;
160+
}
71161

72162
static hlsl::float32_t4x4 getTransformFromAABB(const hlsl::shapes::AABB<3, float>& aabb);
73163

@@ -77,7 +167,7 @@ class DrawAABB final : public core::IReferenceCounted
77167
~DrawAABB() override;
78168

79169
private:
80-
static bool validateCreationParameters(SCreationParameters& params);
170+
//static bool validateCreationParameters(SCreationParameters& params);
81171
static core::smart_refctd_ptr<video::IGPUGraphicsPipeline> createPipeline(SCreationParameters& params, const video::IGPUPipelineLayout* pipelineLayout, const std::string& vsPath, const std::string& fsPath);
82172
static bool createStreamingBuffer(SCreationParameters& params);
83173
static core::smart_refctd_ptr<video::IGPUBuffer> createIndicesBuffer(SCreationParameters& params);

src/nbl/ext/DebugDraw/CDrawAABB.cpp

Lines changed: 27 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
// For conditions of distribution and use, see copyright notice in nabla.h
44

55
#include "nbl/ext/DebugDraw/CDrawAABB.h"
6-
#include "nbl/builtin/hlsl/math/linalg/fast_affine.hlsl"
76

87
#ifdef NBL_EMBED_BUILTIN_RESOURCES
98
#include "nbl/ext/debug_draw/builtin/CArchive.h"
@@ -23,7 +22,7 @@ core::smart_refctd_ptr<DrawAABB> DrawAABB::create(SCreationParameters&& params)
2322
{
2423
auto* const logger = params.utilities->getLogger();
2524

26-
if (!validateCreationParameters(params))
25+
if (!params.validate())
2726
{
2827
logger->log("Failed creation parameters validation!", ILogger::ELL_ERROR);
2928
return nullptr;
@@ -102,28 +101,28 @@ const smart_refctd_ptr<IFileArchive> DrawAABB::mount(smart_refctd_ptr<ILogger> l
102101
return smart_refctd_ptr(archive);
103102
}
104103

105-
bool DrawAABB::validateCreationParameters(SCreationParameters& creationParams)
106-
{
107-
const auto validation = std::to_array
108-
({
109-
std::make_pair(bool(creationParams.assetManager), "Invalid `creationParams.assetManager` is nullptr!"),
110-
std::make_pair(bool(creationParams.assetManager->getSystem()), "Invalid `creationParams.assetManager->getSystem()` is nullptr!"),
111-
std::make_pair(bool(creationParams.utilities), "Invalid `creationParams.utilities` is nullptr!"),
112-
std::make_pair(bool(creationParams.transfer), "Invalid `creationParams.transfer` is nullptr!"),
113-
std::make_pair(bool(creationParams.renderpass), "Invalid `creationParams.renderpass` is nullptr!"),
114-
(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!")
115-
});
116-
117-
system::logger_opt_ptr logger = creationParams.utilities->getLogger();
118-
for (const auto& [ok, error] : validation)
119-
if (!ok)
120-
{
121-
logger.log(error, ILogger::ELL_ERROR);
122-
return false;
123-
}
124-
125-
return true;
126-
}
104+
//bool DrawAABB::validateCreationParameters(SCreationParameters& creationParams)
105+
//{
106+
// const auto validation = std::to_array
107+
// ({
108+
// std::make_pair(bool(creationParams.assetManager), "Invalid `creationParams.assetManager` is nullptr!"),
109+
// std::make_pair(bool(creationParams.assetManager->getSystem()), "Invalid `creationParams.assetManager->getSystem()` is nullptr!"),
110+
// std::make_pair(bool(creationParams.utilities), "Invalid `creationParams.utilities` is nullptr!"),
111+
// std::make_pair(bool(creationParams.transfer), "Invalid `creationParams.transfer` is nullptr!"),
112+
// std::make_pair(bool(creationParams.renderpass), "Invalid `creationParams.renderpass` is nullptr!"),
113+
// (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!")
114+
// });
115+
//
116+
// system::logger_opt_ptr logger = creationParams.utilities->getLogger();
117+
// for (const auto& [ok, error] : validation)
118+
// if (!ok)
119+
// {
120+
// logger.log(error, ILogger::ELL_ERROR);
121+
// return false;
122+
// }
123+
//
124+
// return true;
125+
//}
127126

128127
smart_refctd_ptr<IGPUGraphicsPipeline> DrawAABB::createPipeline(SCreationParameters& params, const IGPUPipelineLayout* pipelineLayout, const std::string& vsPath, const std::string& fsPath)
129128
{
@@ -346,71 +345,10 @@ bool DrawAABB::renderSingle(IGPUCommandBuffer* commandBuffer, const hlsl::shapes
346345
return true;
347346
}
348347

349-
bool DrawAABB::render(IGPUCommandBuffer* commandBuffer, ISemaphore::SWaitInfo waitInfo, std::span<const InstanceData> aabbInstances, const hlsl::float32_t4x4& cameraMat)
350-
{
351-
if (!(m_cachedCreationParams.drawMode & ADM_DRAW_BATCH))
352-
{
353-
m_cachedCreationParams.utilities->getLogger()->log("DrawAABB has not been enabled for draw batches!", ILogger::ELL_ERROR);
354-
return false;
355-
}
356-
357-
using offset_t = SCachedCreationParameters::streaming_buffer_t::size_type;
358-
constexpr auto MdiSizes = std::to_array<offset_t>({ sizeof(float32_t3), sizeof(InstanceData) });
359-
// shared nPoT alignment needs to be divisible by all smaller ones to satisfy an allocation from all
360-
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); });
361-
// allocator initialization needs us to round up to PoT
362-
const auto MaxPOTAlignment = roundUpToPoT(MaxAlignment);
363-
364-
auto* streaming = m_cachedCreationParams.streamingBuffer.get();
365-
366-
auto* const streamingPtr = reinterpret_cast<uint8_t*>(streaming->getBufferPointer());
367-
assert(streamingPtr);
368-
369-
commandBuffer->bindGraphicsPipeline(m_batchPipeline.get());
370-
commandBuffer->setLineWidth(1.f);
371-
asset::SBufferBinding<video::IGPUBuffer> indexBinding = { .offset = 0, .buffer = m_indicesBuffer };
372-
commandBuffer->bindIndexBuffer(indexBinding, asset::EIT_32BIT);
373-
374-
std::vector<InstanceData> instances(aabbInstances.size());
375-
for (uint32_t i = 0; i < aabbInstances.size(); i++)
376-
{
377-
auto& inst = instances[i];
378-
inst = aabbInstances[i];
379-
inst.transform = hlsl::mul(cameraMat, inst.transform);
380-
}
381-
382-
auto instancesIt = instances.begin();
383-
const uint32_t instancesPerIter = streaming->getBuffer()->getSize() / sizeof(InstanceData);
384-
using suballocator_t = core::LinearAddressAllocatorST<offset_t>;
385-
while (instancesIt != instances.end())
386-
{
387-
const uint32_t instanceCount = min(instancesPerIter, instances.size());
388-
offset_t inputOffset = 0u;
389-
offset_t ImaginarySizeUpperBound = 0x1 << 30;
390-
suballocator_t imaginaryChunk(nullptr, inputOffset, 0, roundUpToPoT(MaxAlignment), ImaginarySizeUpperBound);
391-
uint32_t instancesByteOffset = imaginaryChunk.alloc_addr(sizeof(InstanceData) * instanceCount, sizeof(InstanceData));
392-
const uint32_t totalSize = imaginaryChunk.get_allocated_size();
393-
394-
inputOffset = SCachedCreationParameters::streaming_buffer_t::invalid_value;
395-
std::chrono::steady_clock::time_point waitTill = std::chrono::steady_clock::now() + std::chrono::milliseconds(1u);
396-
streaming->multi_allocate(waitTill, 1, &inputOffset, &totalSize, &MaxAlignment);
397-
398-
memcpy(streamingPtr + instancesByteOffset, std::addressof(*instancesIt), sizeof(InstanceData) * instanceCount);
399-
instancesIt += instanceCount;
400-
401-
assert(!streaming->needsManualFlushOrInvalidate());
402-
403-
SPushConstants pc;
404-
pc.pInstanceBuffer = m_cachedCreationParams.streamingBuffer->getBuffer()->getDeviceAddress() + instancesByteOffset;
405-
406-
commandBuffer->pushConstants(m_batchPipeline->getLayout(), ESS_VERTEX, 0, sizeof(SPushConstants), &pc);
407-
commandBuffer->drawIndexed(IndicesCount, instanceCount, 0, 0, 0);
408-
409-
streaming->multi_deallocate(1, &inputOffset, &totalSize, waitInfo);
410-
}
411-
412-
return true;
413-
}
348+
//bool DrawAABB::render(IGPUCommandBuffer* commandBuffer, ISemaphore::SWaitInfo waitInfo, std::span<const InstanceData> aabbInstances, const hlsl::float32_t4x4& cameraMat)
349+
//{
350+
//
351+
//}
414352

415353
hlsl::float32_t4x4 DrawAABB::getTransformFromAABB(const hlsl::shapes::AABB<3, float>& aabb)
416354
{

0 commit comments

Comments
 (0)