From 2e977ce75b5ebd6ce2223b7d55a36ec42eab3b54 Mon Sep 17 00:00:00 2001 From: Tobias Frisch <tfrisch@uni-koblenz.de> Date: Tue, 29 Nov 2022 00:54:32 +0100 Subject: [PATCH] First changes in scene module to allow creation of acceleration structures from static scene graph Signed-off-by: Tobias Frisch <tfrisch@uni-koblenz.de> --- modules/scene/include/vkcv/scene/Mesh.hpp | 10 ++++++ modules/scene/include/vkcv/scene/MeshPart.hpp | 5 +++ modules/scene/include/vkcv/scene/Node.hpp | 10 ++++++ modules/scene/include/vkcv/scene/Scene.hpp | 9 +++++ modules/scene/src/vkcv/scene/Mesh.cpp | 23 ++++++++++++ modules/scene/src/vkcv/scene/MeshPart.cpp | 35 +++++++++++++++++++ modules/scene/src/vkcv/scene/Node.cpp | 11 ++++++ modules/scene/src/vkcv/scene/Scene.cpp | 10 ++++++ projects/rt_ambient_occlusion/CMakeLists.txt | 6 ++-- .../resources/shaders/ambientOcclusion.rchit | 4 ++- projects/rt_ambient_occlusion/src/main.cpp | 15 +++++++- src/vkcv/AccelerationStructureManager.cpp | 28 +++++++++++++-- src/vkcv/AccelerationStructureManager.hpp | 1 + src/vkcv/GeometryData.cpp | 2 +- 14 files changed, 161 insertions(+), 8 deletions(-) diff --git a/modules/scene/include/vkcv/scene/Mesh.hpp b/modules/scene/include/vkcv/scene/Mesh.hpp index 059eb6bc..d0eb3597 100644 --- a/modules/scene/include/vkcv/scene/Mesh.hpp +++ b/modules/scene/include/vkcv/scene/Mesh.hpp @@ -85,6 +85,16 @@ namespace vkcv::scene { PushConstants& pushConstants, std::vector<InstanceDrawcall>& drawcalls, const RecordMeshDrawcallFunction& record); + + /** + * Creates acceleration structures for the whole geometry of this mesh and + * appends it to a given list. + * + * @param[in,out] core Core instance + * @param[out] accelerationStructures List of acceleration structures + */ + void appendAccelerationStructures(Core& core, + std::vector<AccelerationStructureHandle>&accelerationStructures) const; /** * Return the amount of drawcalls of the mesh diff --git a/modules/scene/include/vkcv/scene/MeshPart.hpp b/modules/scene/include/vkcv/scene/MeshPart.hpp index 72fd6151..a0529100 100644 --- a/modules/scene/include/vkcv/scene/MeshPart.hpp +++ b/modules/scene/include/vkcv/scene/MeshPart.hpp @@ -35,6 +35,11 @@ namespace vkcv::scene { * The vertex data containing its part of the mesh. */ VertexData m_data; + + /** + * The geometry data describing its part of the mesh. + */ + GeometryData m_geometry; /** * Axis aligned bounding box of the mesh part. diff --git a/modules/scene/include/vkcv/scene/Node.hpp b/modules/scene/include/vkcv/scene/Node.hpp index de40adcf..ff38328a 100644 --- a/modules/scene/include/vkcv/scene/Node.hpp +++ b/modules/scene/include/vkcv/scene/Node.hpp @@ -81,6 +81,16 @@ namespace vkcv::scene { PushConstants& pushConstants, std::vector<InstanceDrawcall>& drawcalls, const RecordMeshDrawcallFunction& record); + + /** + * Creates acceleration structures for all meshes of this node and its child + * nodes to append them to a given list. + * + * @param[in,out] core Core instance + * @param[out] accelerationStructures List of acceleration structures + */ + void appendAccelerationStructures(Core& core, + std::vector<AccelerationStructureHandle>&accelerationStructures) const; /** * Splits child nodes into tree based graphs of nodes diff --git a/modules/scene/include/vkcv/scene/Scene.hpp b/modules/scene/include/vkcv/scene/Scene.hpp index d6db062c..7c1806e5 100644 --- a/modules/scene/include/vkcv/scene/Scene.hpp +++ b/modules/scene/include/vkcv/scene/Scene.hpp @@ -187,6 +187,15 @@ namespace vkcv::scene { const RecordMeshDrawcallFunction &record, const std::vector<ImageHandle> &renderTargets, const WindowHandle &windowHandle); + + /** + * Create a top-level acceleration structure representing the scene in current state + * which contains all of its meshes as bottom-level acceleration structures with + * its given geometry. + * + * @return Acceleration structure + */ + AccelerationStructureHandle createAccelerationStructure() const; /** * Instantiation function to create a new scene instance. diff --git a/modules/scene/src/vkcv/scene/Mesh.cpp b/modules/scene/src/vkcv/scene/Mesh.cpp index 3c6249fb..09358824 100644 --- a/modules/scene/src/vkcv/scene/Mesh.cpp +++ b/modules/scene/src/vkcv/scene/Mesh.cpp @@ -123,6 +123,29 @@ namespace vkcv::scene { } } + void Mesh::appendAccelerationStructures(Core &core, + std::vector<AccelerationStructureHandle> &accelerationStructures) const { + std::vector<GeometryData> geometryData; + geometryData.reserve(m_parts.size()); + + for (auto& part : m_parts) { + if (part.m_geometry.isValid()) { + geometryData.push_back(part.m_geometry); + break; // TODO: Ensure safe support of multiple geometry data structures to build bottom-level acceleration structures first! Avoid crashes! + } + } + + if (geometryData.empty()) { + return; + } + + const AccelerationStructureHandle handle = core.createAccelerationStructure(geometryData); + + if (handle) { + accelerationStructures.push_back(handle); + } + } + size_t Mesh::getDrawcallCount() const { return m_drawcalls.size(); } diff --git a/modules/scene/src/vkcv/scene/MeshPart.cpp b/modules/scene/src/vkcv/scene/MeshPart.cpp index 959148b0..88070f02 100644 --- a/modules/scene/src/vkcv/scene/MeshPart.cpp +++ b/modules/scene/src/vkcv/scene/MeshPart.cpp @@ -9,6 +9,7 @@ namespace vkcv::scene { MeshPart::MeshPart(Scene& scene) : m_scene(scene), m_data(), + m_geometry(), m_bounds(), m_materialIndex(std::numeric_limits<size_t>::max()) {} @@ -32,6 +33,27 @@ namespace vkcv::scene { ) ); + size_t positionAttributeIndex = types.size(); + for (size_t i = 0; i < types.size(); i++) { + if (types[i] == asset::PrimitiveType::POSITION) { + positionAttributeIndex = i; + break; + } + } + + const uint32_t stride = vertexGroup.numVertices > 0? static_cast<uint32_t>( + vertexGroup.vertexBuffer.data.size() / vertexGroup.numVertices + ) : 0; + + if ((positionAttributeIndex < m_data.getVertexBufferBindings().size()) && + (stride > 0)) { + m_geometry = GeometryData( + m_data.getVertexBufferBindings()[positionAttributeIndex], + stride, + GeometryVertexType::POSITION_FLOAT3 + ); + } + if (!vertexGroup.indexBuffer.data.empty()) { auto indexBuffer = buffer<uint8_t>( core, BufferType::INDEX, vertexGroup.indexBuffer.data.size() @@ -58,8 +80,17 @@ namespace vkcv::scene { m_data.setIndexBuffer(indexBuffer.getHandle(), indexBitCount); m_data.setCount(vertexGroup.numIndices); + + if (m_geometry.isValid()) { + m_geometry.setIndexBuffer(indexBuffer.getHandle(), indexBitCount); + m_geometry.setCount(vertexGroup.numIndices); + } } else { m_data.setCount(vertexGroup.numVertices); + + if (m_geometry.isValid()) { + m_geometry.setCount(vertexGroup.numIndices); + } } m_bounds.setMin(glm::vec3( @@ -103,6 +134,7 @@ namespace vkcv::scene { MeshPart::MeshPart(const MeshPart &other) : m_scene(other.m_scene), m_data(other.m_data), + m_geometry(other.m_geometry), m_bounds(other.m_bounds), m_materialIndex(other.m_materialIndex) { m_scene.increaseMaterialUsage(m_materialIndex); @@ -111,6 +143,7 @@ namespace vkcv::scene { MeshPart::MeshPart(MeshPart &&other) noexcept : m_scene(other.m_scene), m_data(other.m_data), + m_geometry(other.m_geometry), m_bounds(other.m_bounds), m_materialIndex(other.m_materialIndex) { m_scene.increaseMaterialUsage(m_materialIndex); @@ -122,6 +155,7 @@ namespace vkcv::scene { } m_data = other.m_data; + m_geometry = other.m_geometry; m_bounds = other.m_bounds; m_materialIndex = other.m_materialIndex; @@ -130,6 +164,7 @@ namespace vkcv::scene { MeshPart &MeshPart::operator=(MeshPart &&other) noexcept { m_data = other.m_data; + m_geometry = other.m_geometry; m_bounds = other.m_bounds; m_materialIndex = other.m_materialIndex; diff --git a/modules/scene/src/vkcv/scene/Node.cpp b/modules/scene/src/vkcv/scene/Node.cpp index f5234dd4..550a02c0 100644 --- a/modules/scene/src/vkcv/scene/Node.cpp +++ b/modules/scene/src/vkcv/scene/Node.cpp @@ -109,6 +109,17 @@ namespace vkcv::scene { } } + void Node::appendAccelerationStructures(Core& core, + std::vector<AccelerationStructureHandle> &accelerationStructures) const { + for (auto& mesh : m_meshes) { + mesh.appendAccelerationStructures(core, accelerationStructures); + } + + for (auto& node : m_nodes) { + node.appendAccelerationStructures(core, accelerationStructures); + } + } + void Node::splitMeshesToSubNodes(size_t maxMeshesPerNode) { if (m_meshes.size() <= maxMeshesPerNode) { return; diff --git a/modules/scene/src/vkcv/scene/Scene.cpp b/modules/scene/src/vkcv/scene/Scene.cpp index dfe3ac54..abd0774e 100644 --- a/modules/scene/src/vkcv/scene/Scene.cpp +++ b/modules/scene/src/vkcv/scene/Scene.cpp @@ -150,6 +150,16 @@ namespace vkcv::scene { m_core->recordEndDebugLabel(cmdStream); } + AccelerationStructureHandle Scene::createAccelerationStructure() const { + std::vector<AccelerationStructureHandle> accelerationStructures; + + for (auto& node : m_nodes) { + node.appendAccelerationStructures(*m_core, accelerationStructures); + } + + return m_core->createAccelerationStructure(accelerationStructures); + } + Scene Scene::create(Core& core) { return Scene(&core); } diff --git a/projects/rt_ambient_occlusion/CMakeLists.txt b/projects/rt_ambient_occlusion/CMakeLists.txt index a20dab4d..6ed4c40c 100644 --- a/projects/rt_ambient_occlusion/CMakeLists.txt +++ b/projects/rt_ambient_occlusion/CMakeLists.txt @@ -16,7 +16,8 @@ target_include_directories(rt_ambient_occlusion SYSTEM BEFORE PRIVATE ${vkcv_camera_include} ${vkcv_geometry_include} ${vkcv_scene_include} - ${vkcv_shader_compiler_include}) + ${vkcv_shader_compiler_include} + ${vkcv_scene_include}) # linking with libraries from all dependencies and the VkCV framework target_link_libraries(rt_ambient_occlusion @@ -25,4 +26,5 @@ target_link_libraries(rt_ambient_occlusion vkcv_camera vkcv_geometry vkcv_scene - vkcv_shader_compiler) + vkcv_shader_compiler + vkcv_scene) diff --git a/projects/rt_ambient_occlusion/resources/shaders/ambientOcclusion.rchit b/projects/rt_ambient_occlusion/resources/shaders/ambientOcclusion.rchit index 807fe544..5f578536 100644 --- a/projects/rt_ambient_occlusion/resources/shaders/ambientOcclusion.rchit +++ b/projects/rt_ambient_occlusion/resources/shaders/ambientOcclusion.rchit @@ -24,6 +24,8 @@ layout(binding = 3, set = 0, scalar) buffer rtIndices void main() { payload.worldPosition = vec3(1.0, 0.0, 0.5); + payload.worldNormal = vec3(1.0 - attributes.x - attributes.y, attributes.xy); +/* ivec3 indicesVec = ivec3(indices[3 * gl_PrimitiveID + 0], indices[3 * gl_PrimitiveID + 1], indices[3 * gl_PrimitiveID + 2]); // current triangle @@ -42,6 +44,6 @@ void main() { payload.worldNormal = normalize((objectNormal * gl_WorldToObjectEXT).xyz); payload.worldNormal = faceforward(payload.worldNormal, gl_WorldRayDirectionEXT, payload.worldNormal); - +*/ payload.hitSky = 0.0f; } diff --git a/projects/rt_ambient_occlusion/src/main.cpp b/projects/rt_ambient_occlusion/src/main.cpp index fd722518..608b8a5e 100644 --- a/projects/rt_ambient_occlusion/src/main.cpp +++ b/projects/rt_ambient_occlusion/src/main.cpp @@ -2,6 +2,7 @@ #include <vkcv/camera/CameraManager.hpp> #include <vkcv/geometry/Teapot.hpp> #include <vkcv/shader/GLSLCompiler.hpp> +#include <vkcv/scene/Scene.hpp> /** * Note: This project is based on the following tutorial https://github.com/Apress/Ray-Tracing-Gems-II/tree/main/Chapter_16. @@ -50,6 +51,16 @@ int main(int argc, const char** argv) { vkcv::WindowHandle windowHandle = core.createWindow(applicationName, 800, 600, true); + vkcv::scene::Scene scene = vkcv::scene::Scene::load( + core, + "../first_scene/assets/Sponza/Sponza.gltf", + { + vkcv::asset::PrimitiveType::POSITION, + vkcv::asset::PrimitiveType::NORMAL, + vkcv::asset::PrimitiveType::TEXCOORD_0 + } + ); + vkcv::geometry::Teapot teapot (glm::vec3(0.0f), 1.0f); vkcv::VertexData vertexData = teapot.generateVertexData(core); vkcv::GeometryData geometryData = teapot.extractGeometryData(vertexData); @@ -89,9 +100,11 @@ int main(int argc, const char** argv) { vkcv::AccelerationStructureHandle blas = core.createAccelerationStructure({ geometryData }); vkcv::AccelerationStructureHandle tlas = core.createAccelerationStructure({ blas }); + vkcv::AccelerationStructureHandle scene_tlas = scene.createAccelerationStructure(); + { vkcv::DescriptorWrites writes; - writes.writeAcceleration(1, { core.getVulkanAccelerationStructure(tlas) }); + writes.writeAcceleration(1, { core.getVulkanAccelerationStructure(scene_tlas) }); writes.writeStorageBuffer(2, geometryData.getVertexBufferBinding().buffer); writes.writeStorageBuffer(3, geometryData.getIndexBuffer()); core.writeDescriptorSet(descriptorSetHandles[0], writes); diff --git a/src/vkcv/AccelerationStructureManager.cpp b/src/vkcv/AccelerationStructureManager.cpp index 919a0677..1dafe9f3 100644 --- a/src/vkcv/AccelerationStructureManager.cpp +++ b/src/vkcv/AccelerationStructureManager.cpp @@ -40,6 +40,10 @@ namespace vkcv { if (accelerationStructure.m_storageBuffer) { accelerationStructure.m_storageBuffer = BufferHandle(); } + + if (!accelerationStructure.m_children.empty()) { + accelerationStructure.m_children.clear(); + } } const BufferManager &AccelerationStructureManager::getBufferManager() const { @@ -210,7 +214,8 @@ namespace vkcv { return { accelerationStructure, - asStorageBuffer + asStorageBuffer, + {} }; } @@ -220,6 +225,17 @@ namespace vkcv { std::vector<vk::AccelerationStructureBuildGeometryInfoKHR> geometryInfos; std::vector<std::vector<vk::AccelerationStructureBuildRangeInfoKHR>> rangeInfos; + if (geometryData.empty()) { + return {}; + } + + for (const auto& geometry : geometryData) { + if (!geometry.isValid()) { + vkcv_log(LogLevel::ERROR, "Invalid geometry used for acceleration structure") + return {}; + } + } + auto& bufferManager = getBufferManager(); vk::DeviceSize accelerationStructureSize = 0; @@ -326,10 +342,14 @@ namespace vkcv { AccelerationStructureHandle AccelerationStructureManager::createAccelerationStructure( const std::vector<AccelerationStructureHandle> &accelerationStructures) { std::vector<vk::AccelerationStructureInstanceKHR> asInstances; + + if (accelerationStructures.empty()) { + return {}; + } + asInstances.reserve(accelerationStructures.size()); auto& bufferManager = getBufferManager(); - const auto &dynamicDispatch = getCore().getContext().getDispatchLoaderDynamic(); for (const auto& accelerationStructure : accelerationStructures) { @@ -443,7 +463,7 @@ namespace vkcv { dynamicDispatch ); - const auto entry = buildAccelerationStructure( + auto entry = buildAccelerationStructure( getCore(), bufferManager, asBuildGeometryInfos, @@ -457,6 +477,8 @@ namespace vkcv { return {}; } + entry.m_children = accelerationStructures; + return add(entry); } diff --git a/src/vkcv/AccelerationStructureManager.hpp b/src/vkcv/AccelerationStructureManager.hpp index d7cc67f1..5e773669 100644 --- a/src/vkcv/AccelerationStructureManager.hpp +++ b/src/vkcv/AccelerationStructureManager.hpp @@ -21,6 +21,7 @@ namespace vkcv { struct AccelerationStructureEntry { vk::AccelerationStructureKHR m_accelerationStructure; BufferHandle m_storageBuffer; + std::vector<AccelerationStructureHandle> m_children; }; /** diff --git a/src/vkcv/GeometryData.cpp b/src/vkcv/GeometryData.cpp index 6a5cc577..35d29128 100644 --- a/src/vkcv/GeometryData.cpp +++ b/src/vkcv/GeometryData.cpp @@ -22,7 +22,7 @@ namespace vkcv { m_count(0) {} bool GeometryData::isValid() const { - return m_vertexType == GeometryVertexType::UNDEFINED; + return m_vertexType != GeometryVertexType::UNDEFINED; } const VertexBufferBinding &GeometryData::getVertexBufferBinding() const { -- GitLab