Skip to content

Mesh loaders kevin #199

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 1 addition & 81 deletions 71_RayTracingPipeline/app_resources/common.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ struct STriangleGeomInfo
MaterialPacked material;
uint64_t vertexBufferAddress;
uint64_t indexBufferAddress;
uint64_t normalBufferAddress;

uint32_t vertexStride : 26;
uint32_t objType: 3;
Expand Down Expand Up @@ -238,8 +239,6 @@ enum ObjectType : uint32_t // matches c++
OT_COUNT
};

static uint32_t s_offsetsToNormalBytes[OT_COUNT] = { 18, 24, 24, 20, 20, 24, 16, 12 }; // based on normals data position

float32_t3 computeDiffuse(Material mat, float32_t3 light_dir, float32_t3 normal)
{
float32_t dotNL = max(dot(normal, light_dir), 0.0);
Expand Down Expand Up @@ -271,85 +270,6 @@ float3 unpackNormals3x10(uint32_t v)
return clamp(float3(pn) / 511.0, -1.0, 1.0);
}

float32_t3 fetchVertexNormal(int instID, int primID, STriangleGeomInfo geom, float2 bary)
{
uint idxOffset = primID * 3;

const uint indexType = geom.indexType;
const uint vertexStride = geom.vertexStride;

const uint32_t objType = geom.objType;
const uint64_t indexBufferAddress = geom.indexBufferAddress;

uint i0, i1, i2;
switch (indexType)
{
case 0: // EIT_16BIT
{
i0 = uint32_t(vk::RawBufferLoad < uint16_t > (indexBufferAddress + (idxOffset + 0) * sizeof(uint16_t), 2u));
i1 = uint32_t(vk::RawBufferLoad < uint16_t > (indexBufferAddress + (idxOffset + 1) * sizeof(uint16_t), 2u));
i2 = uint32_t(vk::RawBufferLoad < uint16_t > (indexBufferAddress + (idxOffset + 2) * sizeof(uint16_t), 2u));
}
break;
case 1: // EIT_32BIT
{
i0 = vk::RawBufferLoad < uint32_t > (indexBufferAddress + (idxOffset + 0) * sizeof(uint32_t));
i1 = vk::RawBufferLoad < uint32_t > (indexBufferAddress + (idxOffset + 1) * sizeof(uint32_t));
i2 = vk::RawBufferLoad < uint32_t > (indexBufferAddress + (idxOffset + 2) * sizeof(uint32_t));
}
break;
default: // EIT_NONE
{
i0 = idxOffset;
i1 = idxOffset + 1;
i2 = idxOffset + 2;
}
}

const uint64_t normalVertexBufferAddress = geom.vertexBufferAddress + s_offsetsToNormalBytes[objType];
float3 n0, n1, n2;
switch (objType)
{
case OT_CUBE:
{
uint32_t v0 = vk::RawBufferLoad < uint32_t > (normalVertexBufferAddress + i0 * vertexStride, 2u);
uint32_t v1 = vk::RawBufferLoad < uint32_t > (normalVertexBufferAddress + i1 * vertexStride, 2u);
uint32_t v2 = vk::RawBufferLoad < uint32_t > (normalVertexBufferAddress + i2 * vertexStride, 2u);

n0 = normalize(nbl::hlsl::spirv::unpackSnorm4x8(v0).xyz);
n1 = normalize(nbl::hlsl::spirv::unpackSnorm4x8(v1).xyz);
n2 = normalize(nbl::hlsl::spirv::unpackSnorm4x8(v2).xyz);
}
break;
case OT_SPHERE:
case OT_CYLINDER:
case OT_ARROW:
case OT_CONE:
{
uint32_t v0 = vk::RawBufferLoad < uint32_t > (normalVertexBufferAddress + i0 * vertexStride);
uint32_t v1 = vk::RawBufferLoad < uint32_t > (normalVertexBufferAddress + i1 * vertexStride);
uint32_t v2 = vk::RawBufferLoad < uint32_t > (normalVertexBufferAddress + i2 * vertexStride);

n0 = normalize(unpackNormals3x10(v0));
n1 = normalize(unpackNormals3x10(v1));
n2 = normalize(unpackNormals3x10(v2));
}
break;
case OT_RECTANGLE:
case OT_DISK:
case OT_ICOSPHERE:
default:
{
n0 = vk::RawBufferLoad < float3 > (normalVertexBufferAddress + i0 * vertexStride);
n1 = vk::RawBufferLoad < float3 > (normalVertexBufferAddress + i1 * vertexStride);
n2 = vk::RawBufferLoad < float3 > (normalVertexBufferAddress + i2 * vertexStride);
}
}

float3 barycentrics = float3(0.0, bary);
barycentrics.x = 1.0 - barycentrics.y - barycentrics.z;
return normalize(barycentrics.x * n0 + barycentrics.y * n1 + barycentrics.z * n2);
}
#endif

namespace nbl
Expand Down
97 changes: 97 additions & 0 deletions 71_RayTracingPipeline/app_resources/raytrace.rchit.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,103 @@

[[vk::push_constant]] SPushConstants pc;

float32_t3 fetchVertexNormal(int instID, int primID, STriangleGeomInfo geom, float2 bary)
{
uint idxOffset = primID * 3;

const uint indexType = geom.indexType;
const uint vertexStride = geom.vertexStride;

const uint32_t objType = geom.objType;
const uint64_t indexBufferAddress = geom.indexBufferAddress;

uint i0, i1, i2;
switch (indexType)
{
case 0: // EIT_16BIT
{
i0 = uint32_t(vk::RawBufferLoad < uint16_t > (indexBufferAddress + (idxOffset + 0) * sizeof(uint16_t), 2u));
i1 = uint32_t(vk::RawBufferLoad < uint16_t > (indexBufferAddress + (idxOffset + 1) * sizeof(uint16_t), 2u));
i2 = uint32_t(vk::RawBufferLoad < uint16_t > (indexBufferAddress + (idxOffset + 2) * sizeof(uint16_t), 2u));
}
break;
case 1: // EIT_32BIT
{
i0 = vk::RawBufferLoad < uint32_t > (indexBufferAddress + (idxOffset + 0) * sizeof(uint32_t));
i1 = vk::RawBufferLoad < uint32_t > (indexBufferAddress + (idxOffset + 1) * sizeof(uint32_t));
i2 = vk::RawBufferLoad < uint32_t > (indexBufferAddress + (idxOffset + 2) * sizeof(uint32_t));
}
break;
default: // EIT_NONE
{
i0 = idxOffset;
i1 = idxOffset + 1;
i2 = idxOffset + 2;
}
}

const uint64_t normalVertexBufferAddress = geom.normalBufferAddress;
float3 n0, n1, n2;

// TODO(kevin): Currently this will work correctly both for cubes and rectangle, which are the only triangles geometry that is used in this example. Need to implement other geometry
uint32_t v0 = vk::RawBufferLoad < uint32_t > (normalVertexBufferAddress + i0 * 4);
uint32_t v1 = vk::RawBufferLoad < uint32_t > (normalVertexBufferAddress + i1 * 4);
uint32_t v2 = vk::RawBufferLoad < uint32_t > (normalVertexBufferAddress + i2 * 4);


n0 = normalize(nbl::hlsl::spirv::unpackSnorm4x8(v0).xyz);
n1 = normalize(nbl::hlsl::spirv::unpackSnorm4x8(v1).xyz);
n2 = normalize(nbl::hlsl::spirv::unpackSnorm4x8(v2).xyz);

// switch (objType)
// {
// case OT_CUBE:
// {
// // TODO(kevin): Don't hardcode the normal stride in hlsl
// uint32_t v0 = vk::RawBufferLoad < uint32_t > (normalVertexBufferAddress + i0 * 4);
// uint32_t v1 = vk::RawBufferLoad < uint32_t > (normalVertexBufferAddress + i1 * 4);
// uint32_t v2 = vk::RawBufferLoad < uint32_t > (normalVertexBufferAddress + i2 * 4);
//
// n0 = normalize(nbl::hlsl::spirv::unpackSnorm4x8(v0).xyz);
// n1 = normalize(nbl::hlsl::spirv::unpackSnorm4x8(v1).xyz);
// n2 = normalize(nbl::hlsl::spirv::unpackSnorm4x8(v2).xyz);
// }
// break;
// case OT_SPHERE:
// case OT_CYLINDER:
// case OT_ARROW:
// case OT_CONE:
// {
// // TODO(kevin): Fix this logic. Don't use vertex stride since nomral is separated from position
// uint32_t v0 = vk::RawBufferLoad < uint32_t > (normalVertexBufferAddress + i0 * vertexStride);
// uint32_t v1 = vk::RawBufferLoad < uint32_t > (normalVertexBufferAddress + i1 * vertexStride);
// uint32_t v2 = vk::RawBufferLoad < uint32_t > (normalVertexBufferAddress + i2 * vertexStride);
//
// n0 = normalize(unpackNormals3x10(v0));
// n1 = normalize(unpackNormals3x10(v1));
// n2 = normalize(unpackNormals3x10(v2));
// }
// break;
// case OT_RECTANGLE:
// case OT_DISK:
// case OT_ICOSPHERE:
// default:
// {
// // TODO(kevin): Don't hardcode the normal stride in hlsl
// n0 = vk::RawBufferLoad < float3 > (normalVertexBufferAddress + i0 * 4);
// n1 = vk::RawBufferLoad < float3 > (normalVertexBufferAddress + i1 * 4);
// n2 = vk::RawBufferLoad < float3 > (normalVertexBufferAddress + i2 * 4);
// }
// }

// n0 = float3(0, 1, 0);
// n1 = float3(0, 1, 0);
// n2 = float3(0, 1, 0);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can delete old code


float3 barycentrics = float3(0.0, bary);
barycentrics.x = 1.0 - barycentrics.y - barycentrics.z;
return normalize(barycentrics.x * n0 + barycentrics.y * n1 + barycentrics.z * n2);
}

[shader("closesthit")]
void main(inout PrimaryPayload payload, in BuiltInTriangleIntersectionAttributes attribs)
Expand Down
27 changes: 1 addition & 26 deletions 71_RayTracingPipeline/include/common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,40 +45,15 @@ struct ObjectMeta
std::string_view name = "Unknown";
};

struct ObjectDrawHookCpu
{
nbl::core::matrix3x4SIMD model;
ObjectMeta meta;
};

struct ReferenceObjectCpu
{
ObjectMeta meta;
core::smart_refctd_ptr<ICPUPolygonGeometry> data;
Material material;
core::matrix3x4SIMD transform;
};

struct ReferenceObjectGpu
{
struct Bindings
{
nbl::asset::SBufferBinding<IGPUBuffer> vertex, index;
};

ObjectMeta meta;
Bindings bindings;
uint32_t vertexStride;
nbl::asset::E_INDEX_TYPE indexType = nbl::asset::E_INDEX_TYPE::EIT_UNKNOWN;
uint32_t indexCount = {};
MaterialPacked material;
core::matrix3x4SIMD transform;

const bool useIndex() const
{
return bindings.index.buffer && (indexType != E_INDEX_TYPE::EIT_UNKNOWN);
}
};

}

#endif // __NBL_THIS_EXAMPLE_COMMON_H_INCLUDED__
50 changes: 35 additions & 15 deletions 71_RayTracingPipeline/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
#include "nbl/ext/FullScreenTriangle/FullScreenTriangle.h"
#include "nbl/builtin/hlsl/indirect_commands.hlsl"

#include "nbl/examples/common/BuiltinResourcesApplication.hpp"

class RaytracingPipelineApp final : public SimpleWindowedApplication, public application_templates::MonoAssetManagerAndBuiltinResourceApplication

class RaytracingPipelineApp final : public SimpleWindowedApplication, public BuiltinResourcesApplication
{
using device_base_t = SimpleWindowedApplication;
using asset_base_t = application_templates::MonoAssetManagerAndBuiltinResourceApplication;
using asset_base_t = BuiltinResourcesApplication;
using clock_t = std::chrono::steady_clock;

constexpr static inline uint32_t WIN_W = 1280, WIN_H = 720;
Expand Down Expand Up @@ -1220,14 +1222,15 @@ class RaytracingPipelineApp final : public SimpleWindowedApplication, public app
}
else
{
auto triangles = make_refctd_dynamic_array<smart_refctd_dynamic_array<ICPUBottomLevelAccelerationStructure::Triangles<ICPUBuffer>>>(cpuObjects[i].data->exportForBLAS());
auto triangles = make_refctd_dynamic_array<smart_refctd_dynamic_array<ICPUBottomLevelAccelerationStructure::Triangles<ICPUBuffer>>>(1u);
auto primitiveCounts = make_refctd_dynamic_array<smart_refctd_dynamic_array<uint32_t>>(1u);

auto& tri = triangles->front();

auto& primCount = primitiveCounts->front();
primCount = cpuObjects[i].data->getPrimitiveCount();

tri = cpuObjects[i].data->exportForBLAS();
tri.geometryFlags = cpuObjects[i].material.isTransparent() ?
IGPUBottomLevelAccelerationStructure::GEOMETRY_FLAGS::NO_DUPLICATE_ANY_HIT_INVOCATION_BIT :
IGPUBottomLevelAccelerationStructure::GEOMETRY_FLAGS::OPAQUE_BIT;
Expand Down Expand Up @@ -1257,7 +1260,7 @@ class RaytracingPipelineApp final : public SimpleWindowedApplication, public app
inst.base.blas = cpuBlasList[i];
inst.base.flags = static_cast<uint32_t>(IGPUTopLevelAccelerationStructure::INSTANCE_FLAGS::TRIANGLE_FACING_CULL_DISABLE_BIT);
inst.base.instanceCustomIndex = i;
inst.base.instanceShaderBindingTableRecordOffset = isProceduralInstance ? 2 : 0;;
inst.base.instanceShaderBindingTableRecordOffset = isProceduralInstance ? 2 : 0;
inst.base.mask = 0xFF;
inst.transform = isProceduralInstance ? matrix3x4SIMD() : cpuObjects[i].transform;

Expand Down Expand Up @@ -1305,19 +1308,22 @@ class RaytracingPipelineApp final : public SimpleWindowedApplication, public app
inputs.allocator = &myalloc;

std::array<ICPUTopLevelAccelerationStructure*, 1u> tmpTlas;
std::array<ICPUPolygonGeometry*, std::size(cpuObjects)> tmpGeometries;
std::array<ICPUBuffer*, 1> tmpBuffers;
std::array<ICPUPolygonGeometry*, std::size(cpuObjects)> tmpGeometries;
std::array<CAssetConverter::patch_t<asset::ICPUPolygonGeometry>, std::size(cpuObjects)> tmpGeometryPatches;
{
tmpTlas[0] = cpuTlas.get();
tmpBuffers[0] = cpuProcBuffer.get();
for (uint32_t i = 0; i < cpuObjects.size(); i++)
{
tmpGeometries[i] = cpuObjects[i].data.get();
tmpGeometryPatches[i].indexBufferUsages= IGPUBuffer::E_USAGE_FLAGS::EUF_SHADER_DEVICE_ADDRESS_BIT;
}

std::get<CAssetConverter::SInputs::asset_span_t<ICPUTopLevelAccelerationStructure>>(inputs.assets) = tmpTlas;
std::get<CAssetConverter::SInputs::asset_span_t<ICPUBuffer>>(inputs.assets) = tmpBuffers;
std::get<CAssetConverter::SInputs::asset_span_t<ICPUPolygonGeometry>>(inputs.assets) = tmpGeometries;
std::get<CAssetConverter::SInputs::patch_span_t<ICPUPolygonGeometry>>(inputs.patches) = tmpGeometryPatches;
}

auto reservation = converter->reserve(inputs);
Expand Down Expand Up @@ -1346,6 +1352,7 @@ class RaytracingPipelineApp final : public SimpleWindowedApplication, public app

prepass.template operator() < ICPUTopLevelAccelerationStructure > (tmpTlas);
prepass.template operator() < ICPUBuffer > (tmpBuffers);
prepass.template operator() < ICPUPolygonGeometry > (tmpGeometries);
}

constexpr auto CompBufferCount = 2;
Expand Down Expand Up @@ -1425,25 +1432,37 @@ class RaytracingPipelineApp final : public SimpleWindowedApplication, public app
auto&& tlases = reservation.getGPUObjects<ICPUTopLevelAccelerationStructure>();
m_gpuTlas = tlases[0].value;
auto&& buffers = reservation.getGPUObjects<ICPUBuffer>();
m_proceduralAabbBuffer = buffers[0].value;

m_proceduralAabbBuffer = buffers[2 * proceduralBlasIdx].value;
auto&& gpuPolygonGeometries = reservation.getGPUObjects<ICPUPolygonGeometry>();
m_gpuPolygons.resize(gpuPolygonGeometries.size());

for (uint32_t i = 0; i < cpuObjects.size(); i++)
for (uint32_t i = 0; i < gpuPolygonGeometries.size(); i++)
{
const auto& cpuObject = cpuObjects[i];
const auto& cpuBlas = cpuBlasList[i];
const auto& geometry = cpuBlas->getTriangleGeometries()[0];
const uint64_t vertexBufferAddress = buffers[2 * i].value->getDeviceAddress();
const uint64_t indexBufferAddress = buffers[(2 * i) + 1].value->getDeviceAddress();
geomInfos[i] = {
const auto& gpuPolygon = gpuPolygonGeometries[i].value;
const auto gpuTriangles = gpuPolygon->exportForBLAS();

const auto& vertexBufferBinding = gpuTriangles.vertexData[0];
const uint64_t vertexBufferAddress = vertexBufferBinding.buffer->getDeviceAddress() + vertexBufferBinding.offset;

const auto& normalView = gpuPolygon->getNormalView();
const uint64_t normalBufferAddress = normalView ? normalView.src.buffer->getDeviceAddress() + normalView.src.offset : 0;

const auto& indexBufferBinding = gpuTriangles.indexData;
auto& geomInfo = geomInfos[i];
geomInfo = {
.material = hlsl::_static_cast<MaterialPacked>(cpuObject.material),
.vertexBufferAddress = vertexBufferAddress,
.indexBufferAddress = geometry.indexData.buffer ? indexBufferAddress : vertexBufferAddress,
.vertexStride = geometry.vertexStride,
.indexBufferAddress = indexBufferBinding.buffer ? indexBufferBinding.buffer->getDeviceAddress() + indexBufferBinding.offset : vertexBufferAddress,
.normalBufferAddress = normalBufferAddress,
.vertexStride = gpuTriangles.vertexStride,
.objType = cpuObject.meta.type,
.indexType = geometry.indexType,
.indexType = gpuTriangles.indexType,
.smoothNormals = scene::s_smoothNormals[cpuObject.meta.type],
};

m_gpuPolygons[i] = gpuPolygon;
}
}

Expand Down Expand Up @@ -1508,6 +1527,7 @@ class RaytracingPipelineApp final : public SimpleWindowedApplication, public app
core::vector<SProceduralGeomInfo> m_gpuIntersectionSpheres;
uint32_t m_intersectionHitGroupIdx;

core::vector<smart_refctd_ptr<IGPUPolygonGeometry>> m_gpuPolygons;
smart_refctd_ptr<IGPUTopLevelAccelerationStructure> m_gpuTlas;
smart_refctd_ptr<IGPUBuffer> m_instanceBuffer;

Expand Down