Skip to content

Commit 0bc0557

Browse files
author
kevyuu
committed
Fix example 67
1 parent f66d952 commit 0bc0557

File tree

4 files changed

+142
-95
lines changed

4 files changed

+142
-95
lines changed

67_RayQueryGeometry/app_resources/common.hlsl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ struct SGeomInfo
1010
{
1111
uint64_t vertexBufferAddress;
1212
uint64_t indexBufferAddress;
13+
uint64_t normalBufferAddress;
1314

1415
uint32_t vertexStride : 29;
1516
uint32_t indexType : 2; // 16 bit, 32 bit or none
@@ -35,8 +36,6 @@ enum ObjectType : uint32_t // matches c++
3536
OT_SPHERE,
3637
OT_CYLINDER,
3738
OT_RECTANGLE,
38-
OT_DISK,
39-
OT_ARROW,
4039
OT_CONE,
4140
OT_ICOSPHERE,
4241

67_RayQueryGeometry/app_resources/render.comp.hlsl

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,11 @@ float3 calculateSmoothNormals(int instID, int primID, SGeomInfo geom, float2 bar
2929
{
3030
const uint indexType = geom.indexType;
3131
const uint vertexStride = geom.vertexStride;
32+
const uint objType = instID;
3233

3334
const uint64_t vertexBufferAddress = geom.vertexBufferAddress;
3435
const uint64_t indexBufferAddress = geom.indexBufferAddress;
36+
const uint64_t normalBufferAddress = geom.normalBufferAddress;
3537

3638
uint32_t3 indices;
3739
switch (indexType)
@@ -51,42 +53,31 @@ float3 calculateSmoothNormals(int instID, int primID, SGeomInfo geom, float2 bar
5153
}
5254

5355
float3 n0, n1, n2;
54-
switch (instID)
56+
switch (objType)
5557
{
5658
case OT_CUBE:
59+
case OT_SPHERE:
60+
case OT_RECTANGLE:
61+
case OT_CYLINDER:
62+
//case OT_ARROW:
63+
case OT_CONE:
5764
{
5865
// TODO: document why the alignment is 2 here and nowhere else? isnt the `vertexStride` aligned to more than 2 anyway?
59-
uint32_t v0 = vk::RawBufferLoad<uint32_t>(vertexBufferAddress + indices[0] * vertexStride, 2u);
60-
uint32_t v1 = vk::RawBufferLoad<uint32_t>(vertexBufferAddress + indices[1] * vertexStride, 2u);
61-
uint32_t v2 = vk::RawBufferLoad<uint32_t>(vertexBufferAddress + indices[2] * vertexStride, 2u);
66+
uint32_t v0 = vk::RawBufferLoad<uint32_t>(normalBufferAddress + indices[0] * 4);
67+
uint32_t v1 = vk::RawBufferLoad<uint32_t>(normalBufferAddress + indices[1] * 4);
68+
uint32_t v2 = vk::RawBufferLoad<uint32_t>(normalBufferAddress + indices[2] * 4);
6269

6370
n0 = normalize(nbl::hlsl::spirv::unpackSnorm4x8(v0).xyz);
6471
n1 = normalize(nbl::hlsl::spirv::unpackSnorm4x8(v1).xyz);
6572
n2 = normalize(nbl::hlsl::spirv::unpackSnorm4x8(v2).xyz);
6673
}
6774
break;
68-
case OT_SPHERE:
69-
case OT_CYLINDER:
70-
case OT_ARROW:
71-
case OT_CONE:
72-
{
73-
uint32_t v0 = vk::RawBufferLoad<uint32_t>(vertexBufferAddress + indices[0] * vertexStride);
74-
uint32_t v1 = vk::RawBufferLoad<uint32_t>(vertexBufferAddress + indices[1] * vertexStride);
75-
uint32_t v2 = vk::RawBufferLoad<uint32_t>(vertexBufferAddress + indices[2] * vertexStride);
76-
77-
n0 = normalize(unpackNormals3x10(v0));
78-
n1 = normalize(unpackNormals3x10(v1));
79-
n2 = normalize(unpackNormals3x10(v2));
80-
}
81-
break;
82-
case OT_RECTANGLE:
83-
case OT_DISK:
8475
case OT_ICOSPHERE:
8576
default:
8677
{
87-
n0 = normalize(vk::RawBufferLoad<float3>(vertexBufferAddress + indices[0] * vertexStride));
88-
n1 = normalize(vk::RawBufferLoad<float3>(vertexBufferAddress + indices[1] * vertexStride));
89-
n2 = normalize(vk::RawBufferLoad<float3>(vertexBufferAddress + indices[2] * vertexStride));
78+
n0 = normalize(vk::RawBufferLoad<float3>(normalBufferAddress + indices[0] * vertexStride));
79+
n1 = normalize(vk::RawBufferLoad<float3>(normalBufferAddress + indices[1] * vertexStride));
80+
n2 = normalize(vk::RawBufferLoad<float3>(normalBufferAddress + indices[2] * vertexStride));
9081
}
9182
}
9283

67_RayQueryGeometry/include/common.hpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,70 @@ using namespace nbl::examples;
1515

1616
#include "app_resources/common.hlsl"
1717

18+
namespace nbl::scene
19+
{
20+
enum ObjectType : uint8_t
21+
{
22+
OT_CUBE,
23+
OT_SPHERE,
24+
OT_CYLINDER,
25+
OT_RECTANGLE,
26+
OT_CONE,
27+
OT_ICOSPHERE,
28+
29+
OT_COUNT,
30+
OT_UNKNOWN = std::numeric_limits<uint8_t>::max()
31+
};
32+
33+
static constexpr uint32_t s_smoothNormals[OT_COUNT] = { 0, 1, 1, 0, 1, 1 };
34+
35+
struct ObjectMeta
36+
{
37+
ObjectType type = OT_UNKNOWN;
38+
std::string_view name = "Unknown";
39+
};
40+
41+
struct ObjectDrawHookCpu
42+
{
43+
nbl::core::matrix3x4SIMD model;
44+
ObjectMeta meta;
45+
};
46+
47+
enum GeometryShader
48+
{
49+
GP_BASIC = 0,
50+
GP_CONE,
51+
GP_ICO,
52+
53+
GP_COUNT
54+
};
55+
56+
struct ReferenceObjectCpu
57+
{
58+
ObjectMeta meta;
59+
GeometryShader shadersType;
60+
core::smart_refctd_ptr<ICPUPolygonGeometry> data;
61+
};
62+
63+
struct ReferenceObjectGpu
64+
{
65+
struct Bindings
66+
{
67+
nbl::asset::SBufferBinding<IGPUBuffer> vertex, index;
68+
};
69+
70+
ObjectMeta meta;
71+
Bindings bindings;
72+
uint32_t vertexStride;
73+
nbl::asset::E_INDEX_TYPE indexType = nbl::asset::E_INDEX_TYPE::EIT_UNKNOWN;
74+
uint32_t indexCount = {};
75+
76+
const bool useIndex() const
77+
{
78+
return bindings.index.buffer && (indexType != E_INDEX_TYPE::EIT_UNKNOWN);
79+
}
80+
};
81+
}
82+
83+
1884
#endif // _NBL_THIS_EXAMPLE_COMMON_H_INCLUDED_

67_RayQueryGeometry/main.cpp

Lines changed: 61 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
// For conditions of distribution and use, see copyright notice in nabla.h
44
#include "common.hpp"
55

6-
class RayQueryGeometryApp final : public SimpleWindowedApplication, public MonoAssetManagerAndBuiltinResourceApplication
6+
class RayQueryGeometryApp final : public SimpleWindowedApplication, public BuiltinResourcesApplication
77
{
88
using device_base_t = SimpleWindowedApplication;
9-
using asset_base_t = MonoAssetManagerAndBuiltinResourceApplication;
9+
using asset_base_t = BuiltinResourcesApplication;
1010
using clock_t = std::chrono::steady_clock;
1111

1212
constexpr static inline uint32_t WIN_W = 1280, WIN_H = 720;
@@ -486,25 +486,22 @@ class RayQueryGeometryApp final : public SimpleWindowedApplication, public MonoA
486486

487487
smart_refctd_ptr<IGPUDescriptorSet> createAccelerationStructureDS(video::CThreadSafeQueueAdapter* queue)
488488
{
489-
// get geometries in ICPUBuffers
490-
#if 1
491-
return nullptr;
492-
#else
493-
std::array<ReferenceObjectCpu, OT_COUNT> objectsCpu;
494-
objectsCpu[OT_CUBE] = ReferenceObjectCpu{ .meta = {.type = OT_CUBE, .name = "Cube Mesh" }, .shadersType = GP_BASIC, .data = gc->createCubeMesh(nbl::core::vector3df(1.f, 1.f, 1.f)) };
495-
objectsCpu[OT_SPHERE] = ReferenceObjectCpu{ .meta = {.type = OT_SPHERE, .name = "Sphere Mesh" }, .shadersType = GP_BASIC, .data = gc->createSphereMesh(2, 16, 16) };
496-
objectsCpu[OT_CYLINDER] = ReferenceObjectCpu{ .meta = {.type = OT_CYLINDER, .name = "Cylinder Mesh" }, .shadersType = GP_BASIC, .data = gc->createCylinderMesh(2, 2, 20) };
497-
objectsCpu[OT_RECTANGLE] = ReferenceObjectCpu{ .meta = {.type = OT_RECTANGLE, .name = "Rectangle Mesh" }, .shadersType = GP_BASIC, .data = gc->createRectangleMesh(nbl::core::vector2df_SIMD(1.5, 3)) };
498-
objectsCpu[OT_DISK] = ReferenceObjectCpu{ .meta = {.type = OT_DISK, .name = "Disk Mesh" }, .shadersType = GP_BASIC, .data = gc->createDiskMesh(2, 30) };
499-
objectsCpu[OT_ARROW] = ReferenceObjectCpu{ .meta = {.type = OT_ARROW, .name = "Arrow Mesh" }, .shadersType = GP_BASIC, .data = gc->createArrowMesh() };
500-
objectsCpu[OT_CONE] = ReferenceObjectCpu{ .meta = {.type = OT_CONE, .name = "Cone Mesh" }, .shadersType = GP_CONE, .data = gc->createConeMesh(2, 3, 10) };
501-
objectsCpu[OT_ICOSPHERE] = ReferenceObjectCpu{ .meta = {.type = OT_ICOSPHERE, .name = "Icosphere Mesh" }, .shadersType = GP_ICO, .data = gc->createIcoSphere(1, 3, true) };
489+
using namespace nbl::scene;
490+
491+
// triangles geometries
492+
auto gc = make_smart_refctd_ptr<CGeometryCreator>();
493+
494+
std::array<ReferenceObjectCpu, OT_COUNT> cpuObjects;
495+
cpuObjects[OT_CUBE] = ReferenceObjectCpu{ .meta = {.type = OT_CUBE, .name = "Cube Mesh" }, .shadersType = GP_BASIC, .data = gc->createCube({1.f, 1.f, 1.f}) };
496+
cpuObjects[OT_SPHERE] = ReferenceObjectCpu{ .meta = {.type = OT_SPHERE, .name = "Sphere Mesh" }, .shadersType = GP_BASIC, .data = gc->createSphere(2, 16, 16) };
497+
cpuObjects[OT_CYLINDER] = ReferenceObjectCpu{ .meta = {.type = OT_CYLINDER, .name = "Cylinder Mesh" }, .shadersType = GP_BASIC, .data = gc->createCylinder(2, 2, 20) };
498+
cpuObjects[OT_RECTANGLE] = ReferenceObjectCpu{ .meta = {.type = OT_RECTANGLE, .name = "Rectangle Mesh" }, .shadersType = GP_BASIC, .data = gc->createRectangle({1.5, 3}) };
499+
cpuObjects[OT_CONE] = ReferenceObjectCpu{ .meta = {.type = OT_CONE, .name = "Cone Mesh" }, .shadersType = GP_CONE, .data = gc->createCone(2, 3, 10) };
500+
cpuObjects[OT_ICOSPHERE] = ReferenceObjectCpu{ .meta = {.type = OT_ICOSPHERE, .name = "Icosphere Mesh" }, .shadersType = GP_ICO, .data = gc->createIcoSphere(1, 3, true) };
502501

503502
auto geomInfoBuffer = ICPUBuffer::create({ OT_COUNT * sizeof(SGeomInfo) });
504503

505504
SGeomInfo* geomInfos = reinterpret_cast<SGeomInfo*>(geomInfoBuffer->getPointer());
506-
const uint32_t byteOffsets[OT_COUNT] = { 18, 24, 24, 20, 20, 24, 16, 12 }; // based on normals data position
507-
const uint32_t smoothNormals[OT_COUNT] = { 0, 1, 1, 0, 0, 1, 1, 1 };
508505

509506
// get ICPUBuffers into ICPUBottomLevelAccelerationStructures
510507
std::array<smart_refctd_ptr<ICPUBottomLevelAccelerationStructure>, OT_COUNT> cpuBlas;
@@ -514,37 +511,14 @@ class RayQueryGeometryApp final : public SimpleWindowedApplication, public MonoA
514511
auto primitiveCounts = make_refctd_dynamic_array<smart_refctd_dynamic_array<uint32_t>>(1u);
515512

516513
auto& tri = triangles->front();
517-
auto& primCount = primitiveCounts->front();
518-
const auto& geom = objectsCpu[i];
519-
520-
const bool useIndex = geom.data.indexType != EIT_UNKNOWN;
521-
const uint32_t vertexStride = geom.data.inputParams.bindings[0].stride;
522-
const uint32_t numVertices = (geom.data.bindings[0].buffer->getSize()-geom.data.bindings[0].offset) / vertexStride;
523514

524-
if (useIndex)
525-
primCount = geom.data.indexCount / 3;
526-
else
527-
primCount = numVertices / 3;
528-
529-
geomInfos[i].indexType = geom.data.indexType;
530-
geomInfos[i].vertexStride = vertexStride;
531-
geomInfos[i].smoothNormals = smoothNormals[i];
515+
auto& primCount = primitiveCounts->front();
516+
primCount = cpuObjects[i].data->getPrimitiveCount();
532517

533-
geom.data.bindings[0].buffer->setContentHash(geom.data.bindings[0].buffer->computeContentHash());
534-
tri.vertexData[0] = geom.data.bindings[0];
535-
if (useIndex)
536-
{
537-
geom.data.indexBuffer.buffer->setContentHash(geom.data.indexBuffer.buffer->computeContentHash());
538-
tri.indexData = geom.data.indexBuffer;
539-
}
540-
tri.maxVertex = numVertices - 1;
541-
tri.vertexStride = vertexStride;
542-
tri.vertexFormat = static_cast<E_FORMAT>(geom.data.inputParams.attributes[0].format);
543-
tri.indexType = geom.data.indexType;
544-
tri.geometryFlags = IGPUBottomLevelAccelerationStructure::GEOMETRY_FLAGS::OPAQUE_BIT;
518+
tri = cpuObjects[i].data->exportForBLAS();
545519

546520
auto& blas = cpuBlas[i];
547-
blas = make_smart_refctd_ptr<ICPUBottomLevelAccelerationStructure>();
521+
blas = make_smart_refctd_ptr<ICPUBottomLevelAccelerationStructure>();
548522
blas->setGeometries(std::move(triangles), std::move(primitiveCounts));
549523

550524
auto blasFlags = bitflag(IGPUBottomLevelAccelerationStructure::BUILD_FLAGS::PREFER_FAST_TRACE_BIT) | IGPUBottomLevelAccelerationStructure::BUILD_FLAGS::ALLOW_COMPACTION_BIT;
@@ -639,28 +613,25 @@ class RayQueryGeometryApp final : public SimpleWindowedApplication, public MonoA
639613
CAssetConverter::patch_t<ICPUTopLevelAccelerationStructure> tlasPatch = {};
640614
tlasPatch.compactAfterBuild = true;
641615
std::array<CAssetConverter::patch_t<ICPUBottomLevelAccelerationStructure>,OT_COUNT> tmpBLASPatches = {};
642-
std::array<const ICPUBuffer*, OT_COUNT * 2u> tmpBuffers;
643-
std::array<CAssetConverter::patch_t<ICPUBuffer>, OT_COUNT * 2u> tmpBufferPatches;
616+
std::array<ICPUPolygonGeometry*, std::size(cpuObjects)> tmpGeometries;
617+
std::array<CAssetConverter::patch_t<asset::ICPUPolygonGeometry>, std::size(cpuObjects)> tmpGeometryPatches;
644618
{
645619
tmpBLASPatches.front().compactAfterBuild = true;
646620
std::fill(tmpBLASPatches.begin(),tmpBLASPatches.end(),tmpBLASPatches.front());
647621
//
648-
for (uint32_t i = 0; i < objectsCpu.size(); i++)
649-
{
650-
tmpBuffers[2 * i + 0] = cpuBlas[i]->getTriangleGeometries().front().vertexData[0].buffer.get();
651-
tmpBuffers[2 * i + 1] = cpuBlas[i]->getTriangleGeometries().front().indexData.buffer.get();
652-
}
653-
// make sure all buffers are BDA-readable
654-
for (auto& patch : tmpBufferPatches)
655-
patch.usage |= asset::IBuffer::E_USAGE_FLAGS::EUF_SHADER_DEVICE_ADDRESS_BIT;
622+
for (uint32_t i = 0; i < cpuObjects.size(); i++)
623+
{
624+
tmpGeometries[i] = cpuObjects[i].data.get();
625+
tmpGeometryPatches[i].indexBufferUsages= IGPUBuffer::E_USAGE_FLAGS::EUF_SHADER_DEVICE_ADDRESS_BIT;
626+
}
656627

657628
std::get<CAssetConverter::SInputs::asset_span_t<ICPUDescriptorSet>>(inputs.assets) = {&descriptorSet.get(),1};
658629
std::get<CAssetConverter::SInputs::asset_span_t<ICPUTopLevelAccelerationStructure>>(inputs.assets) = {&cpuTlas.get(),1};
659630
std::get<CAssetConverter::SInputs::patch_span_t<ICPUTopLevelAccelerationStructure>>(inputs.patches) = {&tlasPatch,1};
660631
std::get<CAssetConverter::SInputs::asset_span_t<ICPUBottomLevelAccelerationStructure>>(inputs.assets) = {&cpuBlas.data()->get(),cpuBlas.size()};
661632
std::get<CAssetConverter::SInputs::patch_span_t<ICPUBottomLevelAccelerationStructure>>(inputs.patches) = tmpBLASPatches;
662-
std::get<CAssetConverter::SInputs::asset_span_t<ICPUBuffer>>(inputs.assets) = tmpBuffers;
663-
std::get<CAssetConverter::SInputs::patch_span_t<ICPUBuffer>>(inputs.patches) = tmpBufferPatches;
633+
std::get<CAssetConverter::SInputs::asset_span_t<ICPUPolygonGeometry>>(inputs.assets) = tmpGeometries;
634+
std::get<CAssetConverter::SInputs::patch_span_t<ICPUPolygonGeometry>>(inputs.patches) = tmpGeometryPatches;
664635
}
665636

666637
auto reservation = converter->reserve(inputs);
@@ -783,19 +754,38 @@ class RayQueryGeometryApp final : public SimpleWindowedApplication, public MonoA
783754
return {};
784755
}
785756

786-
// assign gpu objects to output
787-
for (const auto& buffer : reservation.getGPUObjects<ICPUBuffer>())
788-
retainedBuffers.push_back(buffer.value);
789-
for (uint32_t i = 0; i < objectsCpu.size(); i++)
790-
{
791-
auto vBuffer = retainedBuffers[2 * i + 0].get();
792-
auto iBuffer = retainedBuffers[2 * i + 1].get();
793-
const auto& geom = objectsCpu[i];
794-
const bool useIndex = geom.data.indexType != EIT_UNKNOWN;
757+
auto&& tlases = reservation.getGPUObjects<ICPUTopLevelAccelerationStructure>();
758+
m_gpuTlas = tlases[0].value;
795759

796-
geomInfos[i].vertexBufferAddress = vBuffer->getDeviceAddress() + byteOffsets[i];
797-
geomInfos[i].indexBufferAddress = useIndex ? iBuffer->getDeviceAddress():0x0ull;
798-
}
760+
auto&& gpuPolygonGeometries = reservation.getGPUObjects<ICPUPolygonGeometry>();
761+
m_gpuPolygons.resize(gpuPolygonGeometries.size());
762+
763+
// assign gpu objects to output
764+
for (uint32_t i = 0; i < gpuPolygonGeometries.size(); i++)
765+
{
766+
const auto& cpuObject = cpuObjects[i];
767+
const auto& gpuPolygon = gpuPolygonGeometries[i].value;
768+
const auto gpuTriangles = gpuPolygon->exportForBLAS();
769+
770+
const auto& vertexBufferBinding = gpuTriangles.vertexData[0];
771+
const uint64_t vertexBufferAddress = vertexBufferBinding.buffer->getDeviceAddress() + vertexBufferBinding.offset;
772+
773+
const auto& normalView = gpuPolygon->getNormalView();
774+
const uint64_t normalBufferAddress = normalView ? normalView.src.buffer->getDeviceAddress() + normalView.src.offset : 0;
775+
776+
const auto& indexBufferBinding = gpuTriangles.indexData;
777+
auto& geomInfo = geomInfos[i];
778+
geomInfo = {
779+
.vertexBufferAddress = vertexBufferAddress,
780+
.indexBufferAddress = indexBufferBinding.buffer ? indexBufferBinding.buffer->getDeviceAddress() + indexBufferBinding.offset : vertexBufferAddress,
781+
.normalBufferAddress = normalBufferAddress,
782+
.vertexStride = gpuTriangles.vertexStride,
783+
.indexType = gpuTriangles.indexType,
784+
.smoothNormals = s_smoothNormals[cpuObject.meta.type],
785+
};
786+
787+
m_gpuPolygons[i] = gpuPolygon;
788+
}
799789
}
800790

801791
//
@@ -892,7 +882,6 @@ class RayQueryGeometryApp final : public SimpleWindowedApplication, public MonoA
892882
m_api->endCapture();
893883

894884
return reservation.getGPUObjects<ICPUDescriptorSet>().front().value;
895-
#endif
896885
}
897886

898887

@@ -911,11 +900,13 @@ class RayQueryGeometryApp final : public SimpleWindowedApplication, public MonoA
911900
video::CDumbPresentationOracle oracle;
912901

913902
smart_refctd_ptr<IGPUBuffer> geometryInfoBuffer;
914-
core::vector<smart_refctd_ptr<IGPUBuffer>> retainedBuffers;
915903
smart_refctd_ptr<IGPUImage> outHDRImage;
904+
core::vector<smart_refctd_ptr<IGPUPolygonGeometry>> m_gpuPolygons;
905+
smart_refctd_ptr<IGPUTopLevelAccelerationStructure> m_gpuTlas;
916906

917907
smart_refctd_ptr<IGPUComputePipeline> renderPipeline;
918908
smart_refctd_ptr<IGPUDescriptorSet> renderDs;
909+
919910
};
920911

921912
NBL_MAIN_FUNC(RayQueryGeometryApp)

0 commit comments

Comments
 (0)