From 094d81a8b02d8e35ab439f43473a4dd3f8063a3b Mon Sep 17 00:00:00 2001
From: Alexander Gauggel <agauggel@uni-koblenz.de>
Date: Tue, 27 Jul 2021 12:05:29 +0200
Subject: [PATCH] [#87] Properly cut meshlets to avoid meshlets not being
 culled properly

---
 modules/meshlet/include/vkcv/meshlet/Meshlet.hpp   |  3 ++-
 modules/meshlet/src/vkcv/meshlet/Meshlet.cpp       | 14 +++++++++++++-
 modules/meshlet/src/vkcv/meshlet/Tipsify.cpp       |  7 ++++++-
 projects/mesh_shader/resources/shaders/shader.task |  1 -
 projects/mesh_shader/src/main.cpp                  |  4 ++--
 5 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/modules/meshlet/include/vkcv/meshlet/Meshlet.hpp b/modules/meshlet/include/vkcv/meshlet/Meshlet.hpp
index 159bdb1a..124639d8 100644
--- a/modules/meshlet/include/vkcv/meshlet/Meshlet.hpp
+++ b/modules/meshlet/include/vkcv/meshlet/Meshlet.hpp
@@ -37,7 +37,8 @@ namespace vkcv::meshlet {
 
     MeshShaderModelData createMeshShaderModelData(
             const std::vector<Vertex>&      inVertices,
-            const std::vector<uint32_t>&    inIndices);
+            const std::vector<uint32_t>&    inIndices,
+            const std::vector<uint32_t>& deadEndIndices = {});
 
     std::vector<uint32_t> assetLoaderIndicesTo32BitIndices(
             const std::vector<uint8_t>& indexData,
diff --git a/modules/meshlet/src/vkcv/meshlet/Meshlet.cpp b/modules/meshlet/src/vkcv/meshlet/Meshlet.cpp
index f5447a01..abcad720 100644
--- a/modules/meshlet/src/vkcv/meshlet/Meshlet.cpp
+++ b/modules/meshlet/src/vkcv/meshlet/Meshlet.cpp
@@ -2,6 +2,7 @@
 #include "vkcv/meshlet/Meshlet.hpp"
 #include <vkcv/Logger.hpp>
 #include <cassert>
+#include <iostream>
 
 namespace vkcv::meshlet {
 
@@ -35,7 +36,8 @@ std::vector<vkcv::meshlet::Vertex> convertToVertices(
 
 MeshShaderModelData createMeshShaderModelData(
         const std::vector<Vertex>&      inVertices,
-        const std::vector<uint32_t>&    inIndices) {
+        const std::vector<uint32_t>&    inIndices,
+        const std::vector<uint32_t>&    deadEndIndices) {
 
     MeshShaderModelData data;
     size_t currentIndex = 0;
@@ -45,6 +47,8 @@ MeshShaderModelData createMeshShaderModelData(
 
     bool indicesAreLeft = true;
 
+    size_t deadEndIndicesIndex = 0;
+
     while (indicesAreLeft) {
         Meshlet meshlet;
 
@@ -59,6 +63,14 @@ MeshShaderModelData createMeshShaderModelData(
 
         while (true) {
 
+            if (deadEndIndicesIndex < deadEndIndices.size()) {
+                const uint32_t deadEndIndex = deadEndIndices[deadEndIndicesIndex];
+                if (deadEndIndex == currentIndex) {
+                    deadEndIndicesIndex++;
+                    break;
+                }
+            }
+
             indicesAreLeft = currentIndex + 1 <= inIndices.size();
             if (!indicesAreLeft) {
                 break;
diff --git a/modules/meshlet/src/vkcv/meshlet/Tipsify.cpp b/modules/meshlet/src/vkcv/meshlet/Tipsify.cpp
index 21c03645..48357b06 100644
--- a/modules/meshlet/src/vkcv/meshlet/Tipsify.cpp
+++ b/modules/meshlet/src/vkcv/meshlet/Tipsify.cpp
@@ -6,6 +6,7 @@
 namespace vkcv::meshlet {
 
     const int maxUsedVertices           = 128;
+    size_t testTriangleIndex;
     std::vector<uint32_t> skippedIndices;
 
     /**
@@ -48,7 +49,7 @@ namespace vkcv::meshlet {
         while (lowestLivingVertexIndex + 1 < vertexCount) {
             lowestLivingVertexIndex++;
             if (livingTriangles[lowestLivingVertexIndex] > 0) {
-                skippedIndices.push_back(static_cast<uint32_t>(lowestLivingVertexIndex));
+                skippedIndices.push_back(static_cast<uint32_t>(testTriangleIndex * 3));
                 return lowestLivingVertexIndex;
             }
         }
@@ -198,6 +199,8 @@ namespace vkcv::meshlet {
 
         std::vector<uint32_t> possibleCandidates(3 * maxOffset);
 
+        testTriangleIndex = 0;
+
         // run while not all indices are fanned out, -1 equals all are fanned out
         while (currentVertexIndex >= 0) {
             // number of possible candidates for a fanning VertexIndex
@@ -216,6 +219,8 @@ namespace vkcv::meshlet {
                     // this allows us to iterate over the indexBuffer with the first vertex of the triangle as start
                     const uint32_t *vertexIndexOfTriangle        = &indexBuffer32Bit[3 * triangleIndex];
 
+                    testTriangleIndex++;
+
                     // save emitted vertexIndexOfTriangle to reorderedTriangleIndexBuffer and set it to emitted
                     reorderedTriangleIndexBuffer[triangleOutputOffset++]    = triangleIndex;
                     isEmittedTriangles[triangleIndex]                       = true;
diff --git a/projects/mesh_shader/resources/shaders/shader.task b/projects/mesh_shader/resources/shaders/shader.task
index f00e749f..7a692e98 100644
--- a/projects/mesh_shader/resources/shaders/shader.task
+++ b/projects/mesh_shader/resources/shaders/shader.task
@@ -47,7 +47,6 @@ bool isSphereInsideFrustum(vec3 spherePos, float sphereRadius, Plane cameraPlane
     for(int i = 0; i < 6; i++){
         Plane p     = cameraPlanes[i];
         isInside    = isInside && dot(p.normal, spherePos - p.pointOnPlane) - sphereRadius < 0;
-        //break;
     }
     return isInside;
 }
diff --git a/projects/mesh_shader/src/main.cpp b/projects/mesh_shader/src/main.cpp
index bfbd595e..1a596be0 100644
--- a/projects/mesh_shader/src/main.cpp
+++ b/projects/mesh_shader/src/main.cpp
@@ -143,7 +143,7 @@ int main(int argc, const char** argv) {
     vkcv::meshlet::tipsifyResult tipsifyResult      = vkcv::meshlet::tipsifyMesh(indexBuffer32Bit, interleavedVertices.size());
     //std::vector<uint32_t> reorderedIndexBuffer32Bit = vkcv::meshlet::forsythReorder(indexBuffer32Bit, interleavedVertices.size());
 
-    const auto meshShaderModelData = createMeshShaderModelData(interleavedVertices, tipsifyResult.indexBuffer);
+    const auto meshShaderModelData = createMeshShaderModelData(interleavedVertices, tipsifyResult.indexBuffer, tipsifyResult.skippedIndices);
 
 	auto meshShaderVertexBuffer = core.createBuffer<vkcv::meshlet::Vertex>(
 		vkcv::BufferType::STORAGE,
@@ -380,7 +380,7 @@ int main(int argc, const char** argv) {
 		
 		ImGui::Begin("Settings");
 		ImGui::Checkbox("Use mesh shader", &useMeshShader);
-		ImGui::Checkbox("Upadte frustum culling", &updateFrustumPlanes);
+		ImGui::Checkbox("Update frustum culling", &updateFrustumPlanes);
 
 		ImGui::End();
 		
-- 
GitLab