From 4d5ec8ef3d6767a905ca9cc3ca9be7e56a204abb Mon Sep 17 00:00:00 2001
From: Alexander Gauggel <agauggel@uni-koblenz.de>
Date: Tue, 6 Jul 2021 15:34:43 +0200
Subject: [PATCH] [#87] Prepare mesh shader data

---
 .../mesh_shader/resources/shaders/shader.frag |   8 +-
 .../mesh_shader/resources/shaders/shader.mesh |  24 +++-
 .../mesh_shader/resources/shaders/shader.task |  11 --
 .../mesh_shader/resources/shaders/shader.vert |   8 +-
 projects/mesh_shader/src/main.cpp             | 127 ++++++++++++------
 src/vkcv/PipelineManager.cpp                  |  39 +++---
 6 files changed, 135 insertions(+), 82 deletions(-)

diff --git a/projects/mesh_shader/resources/shaders/shader.frag b/projects/mesh_shader/resources/shaders/shader.frag
index 11d4f36e..c3740e2c 100644
--- a/projects/mesh_shader/resources/shaders/shader.frag
+++ b/projects/mesh_shader/resources/shaders/shader.frag
@@ -1,11 +1,9 @@
 #version 450
 #extension GL_ARB_separate_shader_objects : enable
 
-layout(location = 0) in vec3 VertexColor;
-layout(location = 1) in vec3 passNormal;
-layout(location = 0) out vec4 outColor;
+layout(location = 0) in  vec3 passNormal;
+layout(location = 0) out vec3 outColor;
 
 void main() {
-	vec3 vis = normalize(passNormal) * 0.5 +0.5;
-	outColor = vec4(vis , 1);
+	outColor = normalize(passNormal) * 0.5 +0.5;
 }
\ No newline at end of file
diff --git a/projects/mesh_shader/resources/shaders/shader.mesh b/projects/mesh_shader/resources/shaders/shader.mesh
index 7e78cced..fc1480bc 100644
--- a/projects/mesh_shader/resources/shaders/shader.mesh
+++ b/projects/mesh_shader/resources/shaders/shader.mesh
@@ -11,7 +11,23 @@ layout( push_constant ) uniform constants{
     mat4 mvp;
 };
 
-layout(location = 0) out vec3 vertexColors[];
+layout(location = 0) out vec3 passNormal[];
+
+struct Vertex
+{
+    vec3 position;
+    vec3 normal;
+};
+
+layout(std430, binding = 0) readonly buffer vertexBuffer
+{
+    Vertex vertices[];
+};
+
+layout(std430, binding = 1) readonly buffer indexBuffer
+{
+    uint indices[]; // breaks for 16 bit indices
+};
 
 void main()	{
 	if(gl_LocalInvocationID.x == 0)
@@ -25,8 +41,8 @@ void main()	{
 		gl_MeshVerticesNV[1].gl_Position = mvp * vec4( 0.5,  0.5, 0.5, 1);
 		gl_MeshVerticesNV[2].gl_Position = mvp * vec4( 0  , -0.5, 0.5, 1);
 		
-		vertexColors[0] = vec3(1, 0, 0);
-		vertexColors[1] = vec3(0, 1, 0);
-		vertexColors[2] = vec3(0, 0, 1);		
+		passNormal[0] = vec3(1, 0, 0);
+		passNormal[1] = vec3(0, 1, 0);
+		passNormal[2] = vec3(0, 0, 1);		
 	}
 }
\ No newline at end of file
diff --git a/projects/mesh_shader/resources/shaders/shader.task b/projects/mesh_shader/resources/shaders/shader.task
index 1b2472df..a41b6d21 100644
--- a/projects/mesh_shader/resources/shaders/shader.task
+++ b/projects/mesh_shader/resources/shaders/shader.task
@@ -9,17 +9,6 @@ layout(local_size_x=32) in;
 //  uint subIDs[32];
 //} OUT;
 
-struct Mesh
-{
-    vec3 position;
-    vec3 index;
-};
-
-layout(std430, binding = 0) coherent buffer buffer_inMesh
-{
-    Mesh mesh[];
-};
-
 void main() {
 	if(gl_LocalInvocationID.x == 0)
 	{
diff --git a/projects/mesh_shader/resources/shaders/shader.vert b/projects/mesh_shader/resources/shaders/shader.vert
index 425fc412..5e1f72dc 100644
--- a/projects/mesh_shader/resources/shaders/shader.vert
+++ b/projects/mesh_shader/resources/shaders/shader.vert
@@ -4,15 +4,13 @@
 layout(location = 0) in vec3 inPosition;
 layout(location = 1) in vec3 inNormal;
 
-layout(location = 0) out vec3 fragColor;
-layout(location = 1) out vec3 passNormal;
+layout(location = 0) out vec3 passNormal;
 
 layout( push_constant ) uniform constants{
     mat4 mvp;
 };
 
 void main()	{
-    gl_Position = mvp * vec4(inPosition, 1.0);
-    passNormal  = inNormal;
-	fragColor = vec3(1.f);
+	gl_Position = mvp * vec4(inPosition, 1.0);
+	passNormal  = inNormal;
 }
\ No newline at end of file
diff --git a/projects/mesh_shader/src/main.cpp b/projects/mesh_shader/src/main.cpp
index 884581ef..03e4b68e 100644
--- a/projects/mesh_shader/src/main.cpp
+++ b/projects/mesh_shader/src/main.cpp
@@ -9,6 +9,40 @@
 #include <vkcv/asset/asset_loader.hpp>
 #include "MeshStruct.hpp"
 
+struct Vertex {
+	glm::vec3 position;
+	glm::vec3 normal;
+};
+
+std::vector<Vertex> convertToVertices(
+	const std::vector<uint8_t>&         vertexData,
+	const uint64_t                      vertexCount,
+	const vkcv::asset::VertexAttribute& positionAttribute,
+	const vkcv::asset::VertexAttribute& normalAttribute) {
+
+	assert(positionAttribute.type   == vkcv::asset::PrimitiveType::POSITION);
+	assert(normalAttribute.type     == vkcv::asset::PrimitiveType::NORMAL);
+
+	std::vector<Vertex> vertices;
+	vertices.reserve(vertexCount);
+
+	const size_t positionStepSize   = positionAttribute.stride == 0 ? sizeof(glm::vec3) : positionAttribute.stride;
+	const size_t normalStepSize     = normalAttribute.stride   == 0 ? sizeof(glm::vec3) : normalAttribute.stride;
+
+	for (int i = 0; i < vertexCount; i++) {
+		Vertex v;
+
+		const size_t positionOffset = positionAttribute.offset  + positionStepSize  * i;
+		const size_t normalOffset   = normalAttribute.offset    + normalStepSize    * i;
+
+		v.position  = *reinterpret_cast<const glm::vec3*>(&(vertexData[positionOffset]));
+		v.normal    = *reinterpret_cast<const glm::vec3*>(&(vertexData[normalOffset]));
+		vertices.push_back(v);
+	}
+
+	return vertices;
+}
+
 int main(int argc, const char** argv) {
 	const char* applicationName = "Mesh shader";
 
@@ -57,18 +91,33 @@ int main(int argc, const char** argv) {
     );
     indexBuffer.fill(mesh.vertexGroups[0].indexBuffer.data);
 
-    auto meshBuffer = core.createBuffer<MeshStruct>(
-            vkcv::BufferType::STORAGE,
-            mesh.vertexGroups[0].vertexBuffer.data.size()
-    );
-//    meshBuffer.fill();
+	// format data for mesh shader
+	auto& attributes = mesh.vertexGroups[0].vertexBuffer.attributes;
 
-    auto& attributes = mesh.vertexGroups[0].vertexBuffer.attributes;
+	std::sort(attributes.begin(), attributes.end(), [](const vkcv::asset::VertexAttribute& x, const vkcv::asset::VertexAttribute& y) {
+		return static_cast<uint32_t>(x.type) < static_cast<uint32_t>(y.type);
+	});
+
+	const std::vector<vkcv::VertexBufferBinding> vertexBufferBindings = {
+			vkcv::VertexBufferBinding(static_cast<vk::DeviceSize>(attributes[0].offset), vertexBuffer.getVulkanHandle()),
+			vkcv::VertexBufferBinding(static_cast<vk::DeviceSize>(attributes[1].offset), vertexBuffer.getVulkanHandle()),
+			vkcv::VertexBufferBinding(static_cast<vk::DeviceSize>(attributes[2].offset), vertexBuffer.getVulkanHandle()) };
+
+	const auto& bunny = mesh.vertexGroups[0];
+	const auto interleavedVertices = convertToVertices(bunny.vertexBuffer.data, bunny.numVertices, attributes[0], attributes[1]);
 
-    std::sort(attributes.begin(), attributes.end(), [](const vkcv::asset::VertexAttribute& x, const vkcv::asset::VertexAttribute& y) {
-        return static_cast<uint32_t>(x.type) < static_cast<uint32_t>(y.type);
-    });
+	// mesh shader buffers
+	auto meshBuffer = core.createBuffer<Vertex>(
+		vkcv::BufferType::STORAGE,
+		interleavedVertices.size());
+	meshBuffer.fill(interleavedVertices);
 
+	auto meshShaderIndexBuffer = core.createBuffer<uint8_t>(
+		vkcv::BufferType::STORAGE,
+		mesh.vertexGroups[0].indexBuffer.data.size());
+	meshShaderIndexBuffer.fill(mesh.vertexGroups[0].indexBuffer.data);
+
+	// attachments
 	const vkcv::AttachmentDescription present_color_attachment(
 		vkcv::AttachmentOperation::STORE,
 		vkcv::AttachmentOperation::CLEAR,
@@ -145,7 +194,7 @@ int main(int argc, const char** argv) {
 	});
 
     uint32_t setID = 0;
-    vkcv::DescriptorSetHandle descriptorSet = core.createDescriptorSet( meshShaderProgram.getReflectedDescriptors()[setID]);
+    vkcv::DescriptorSetHandle meshShaderDescriptorSet = core.createDescriptorSet( meshShaderProgram.getReflectedDescriptors()[setID]);
     const vkcv::VertexLayout meshShaderLayout(bindings);
 
 	const vkcv::PipelineConfig meshShaderPipelineDefinition{
@@ -154,7 +203,7 @@ int main(int argc, const char** argv) {
 		(uint32_t)windowHeight,
 		renderPass,
 		{meshShaderLayout},
-		{core.getDescriptorSet(descriptorSet).layout},
+		{core.getDescriptorSet(meshShaderDescriptorSet).layout},
 		false
 	};
 
@@ -166,14 +215,11 @@ int main(int argc, const char** argv) {
 		return EXIT_FAILURE;
 	}
 
-    const std::vector<vkcv::VertexBufferBinding> vertexBufferBindings = {
-            vkcv::VertexBufferBinding(static_cast<vk::DeviceSize>(attributes[0].offset), vertexBuffer.getVulkanHandle()),
-            vkcv::VertexBufferBinding(static_cast<vk::DeviceSize>(attributes[1].offset), vertexBuffer.getVulkanHandle()),
-            vkcv::VertexBufferBinding(static_cast<vk::DeviceSize>(attributes[2].offset), vertexBuffer.getVulkanHandle()) };
-
-    vkcv::DescriptorWrites setWrites;
-    setWrites.storageBufferWrites = {vkcv::StorageBufferDescriptorWrite(0, meshBuffer.getHandle())};
-    core.writeDescriptorSet( descriptorSet, setWrites);
+    vkcv::DescriptorWrites meshShaderWrites;
+	meshShaderWrites.storageBufferWrites = {
+		vkcv::StorageBufferDescriptorWrite(0, meshBuffer.getHandle()), 
+		vkcv::StorageBufferDescriptorWrite(1, meshShaderIndexBuffer.getHandle()) };
+    core.writeDescriptorSet( meshShaderDescriptorSet, meshShaderWrites);
 
     vkcv::ImageHandle depthBuffer = core.createImage(vk::Format::eD32Sfloat, windowWidth, windowHeight, 1, false).getHandle();
 
@@ -183,9 +229,6 @@ int main(int argc, const char** argv) {
 
     const vkcv::Mesh renderMesh(vertexBufferBindings, indexBuffer.getVulkanHandle(), mesh.vertexGroups[0].numIndices, vkcv::IndexBitCount::Bit32);
 
-//    vkcv::DescriptorSetUsage    descriptorUsage(0, core.getDescriptorSet(descriptorSet).vulkanHandle);
-    vkcv::DrawcallInfo          drawcall(renderMesh, {});
-
 	const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle();
 
     vkcv::camera::CameraManager cameraManager(window);
@@ -216,23 +259,29 @@ int main(int argc, const char** argv) {
         const std::vector<vkcv::ImageHandle> renderTargets = { swapchainInput, depthBuffer };
 		auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics);
 
-		/*
-		core.recordMeshShaderDrawcalls(
-			cmdStream,
-			renderPass,
-			meshShaderPipeline,
-			pushConstantData,
-			{ vkcv::MeshShaderDrawcall({}, 1) },
-			{ swapchainInput });
-		*/
-
-		core.recordDrawcallsToCmdStream(
-                cmdStream,
-                renderPass,
-                bunnyPipeline,
-                pushConstantData,
-                { drawcall },
-                { renderTargets });
+		const bool useMeshShader = true;
+
+		if (useMeshShader) {
+
+			vkcv::DescriptorSetUsage descriptorUsage(0, core.getDescriptorSet(meshShaderDescriptorSet).vulkanHandle);
+
+			core.recordMeshShaderDrawcalls(
+				cmdStream,
+				renderPass,
+				meshShaderPipeline,
+				pushConstantData,
+				{ vkcv::MeshShaderDrawcall({descriptorUsage}, 1) },
+				{ renderTargets });
+		}
+		else {
+			core.recordDrawcallsToCmdStream(
+				cmdStream,
+				renderPass,
+				bunnyPipeline,
+				pushConstantData,
+				{ vkcv::DrawcallInfo(renderMesh, {}) },
+				{ renderTargets });
+		}
 
 		core.prepareSwapchainImageForPresent(cmdStream);
 		core.submitCommandStream(cmdStream);
diff --git a/src/vkcv/PipelineManager.cpp b/src/vkcv/PipelineManager.cpp
index fc77e37d..5123e19c 100644
--- a/src/vkcv/PipelineManager.cpp
+++ b/src/vkcv/PipelineManager.cpp
@@ -194,25 +194,28 @@ namespace vkcv
         std::vector<vk::VertexInputAttributeDescription>	vertexAttributeDescriptions;
 		std::vector<vk::VertexInputBindingDescription>		vertexBindingDescriptions;
 
-        const VertexLayout &layout = config.m_VertexLayout;
-
-        // iterate over the layout's specified, mutually exclusive buffer bindings that make up a vertex buffer
-        for (const auto &vertexBinding : layout.vertexBindings)
-        {
-            vertexBindingDescriptions.emplace_back(vertexBinding.bindingLocation,
-                                                   vertexBinding.stride,
-                                                   vk::VertexInputRate::eVertex);
-
-            // iterate over the bindings' specified, mutually exclusive vertex input attachments that make up a vertex
-            for(const auto &vertexAttachment: vertexBinding.vertexAttachments)
-            {
-                vertexAttributeDescriptions.emplace_back(vertexAttachment.inputLocation,
-                                                         vertexBinding.bindingLocation,
-                                                         vertexFormatToVulkanFormat(vertexAttachment.format),
-                                                         vertexAttachment.offset % vertexBinding.stride);
+		if (existsVertexShader) {
+			const VertexLayout& layout = config.m_VertexLayout;
+
+			// iterate over the layout's specified, mutually exclusive buffer bindings that make up a vertex buffer
+			for (const auto& vertexBinding : layout.vertexBindings)
+			{
+				vertexBindingDescriptions.emplace_back(vertexBinding.bindingLocation,
+					vertexBinding.stride,
+					vk::VertexInputRate::eVertex);
+
+				// iterate over the bindings' specified, mutually exclusive vertex input attachments that make up a vertex
+				for (const auto& vertexAttachment : vertexBinding.vertexAttachments)
+				{
+					vertexAttributeDescriptions.emplace_back(vertexAttachment.inputLocation,
+						vertexBinding.bindingLocation,
+						vertexFormatToVulkanFormat(vertexAttachment.format),
+						vertexAttachment.offset % vertexBinding.stride);
+
+				}
+			}
 
-            }
-        }
+		}
 
         // Handover Containers to PipelineVertexInputStateCreateIngo Struct
         vk::PipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo(
-- 
GitLab