From f1ba9662732a90809202e95602bbdae17306e693 Mon Sep 17 00:00:00 2001
From: Alexander Gauggel <agauggel@uni-koblenz.de>
Date: Sat, 12 Jun 2021 23:26:05 +0200
Subject: [PATCH] [#65] Set compute pipeline descriptor set layout and push
 constant ranges correctly

---
 include/vkcv/Core.hpp                |  4 +++-
 projects/first_triangle/src/main.cpp |  8 +++++++-
 src/vkcv/Core.cpp                    |  6 ++++--
 src/vkcv/PipelineManager.cpp         | 20 +++++++++++---------
 src/vkcv/PipelineManager.hpp         |  4 +++-
 5 files changed, 28 insertions(+), 14 deletions(-)

diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp
index fbd1cc9c..d44c5016 100644
--- a/include/vkcv/Core.hpp
+++ b/include/vkcv/Core.hpp
@@ -166,7 +166,9 @@ namespace vkcv
          * @return True if pipeline creation was successful, False if not
          */
         [[nodiscard]]
-        PipelineHandle createComputePipeline(const ShaderProgram &config);
+        PipelineHandle createComputePipeline(
+            const ShaderProgram &config, 
+            const std::vector<vk::DescriptorSetLayout> &descriptorSetLayouts);
 
         /**
          * Creates a basic vulkan render pass using @p config from the render pass config class and returns it using the @p handle.
diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp
index 648118a6..d79ece30 100644
--- a/projects/first_triangle/src/main.cpp
+++ b/projects/first_triangle/src/main.cpp
@@ -119,8 +119,14 @@ int main(int argc, const char** argv) {
 	// Compute Pipeline
 	vkcv::ShaderProgram computeShaderProgram{};
 	computeShaderProgram.addShader(vkcv::ShaderStage::COMPUTE, std::filesystem::path("shaders/comp.spv"));
+	computeShaderProgram.reflectShader(vkcv::ShaderStage::COMPUTE);
 
-	vkcv::PipelineHandle computePipeline = core.createComputePipeline(computeShaderProgram);
+	// take care, assuming shader has exactly one descriptor set
+	vkcv::DescriptorSetHandle computeDescriptorSet = core.createDescriptorSet(computeShaderProgram.getReflectedDescriptors()[0]);
+
+	vkcv::PipelineHandle computePipeline = core.createComputePipeline(
+		computeShaderProgram, 
+		{ core.getDescriptorSet(computeDescriptorSet).layout });
 
 	/*
 	 * BufferHandle triangleVertices = core.createBuffer(vertices);
diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp
index 05782111..afa45006 100644
--- a/src/vkcv/Core.cpp
+++ b/src/vkcv/Core.cpp
@@ -101,9 +101,11 @@ namespace vkcv
         return m_PipelineManager->createPipeline(config, *m_PassManager);
     }
 
-    PipelineHandle Core::createComputePipeline(const ShaderProgram &shaderProgram)
+    PipelineHandle Core::createComputePipeline(
+        const ShaderProgram &shaderProgram, 
+        const std::vector<vk::DescriptorSetLayout>& descriptorSetLayouts)
     {
-        return m_PipelineManager->createComputePipeline(shaderProgram);
+        return m_PipelineManager->createComputePipeline(shaderProgram, descriptorSetLayouts);
     }
 
 
diff --git a/src/vkcv/PipelineManager.cpp b/src/vkcv/PipelineManager.cpp
index 6a0a42b2..765263b2 100644
--- a/src/vkcv/PipelineManager.cpp
+++ b/src/vkcv/PipelineManager.cpp
@@ -315,9 +315,11 @@ namespace vkcv
         return m_Configs.at(id);
     }
 
-    PipelineHandle PipelineManager::createComputePipeline(const ShaderProgram &shaderProgram) {
-        // Temporally handing over the Shader Program instead of a pipeline config
+    PipelineHandle PipelineManager::createComputePipeline(
+        const ShaderProgram &shaderProgram, 
+        const std::vector<vk::DescriptorSetLayout> &descriptorSetLayouts) {
 
+        // Temporally handing over the Shader Program instead of a pipeline config
         vk::ShaderModule computeModule{};
         if (createShaderModule(computeModule, shaderProgram, ShaderStage::COMPUTE) != vk::Result::eSuccess)
             return PipelineHandle();
@@ -330,14 +332,14 @@ namespace vkcv
                 nullptr
         );
 
-        // TODO: Validation Layer Error -> the size is 0 but has to be greater!
-        const size_t matrixPushConstantSize = shaderProgram.getPushConstantSize();
-        const vk::PushConstantRange pushConstantRange(vk::ShaderStageFlagBits::eAll, 0, matrixPushConstantSize);
+        vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo({}, descriptorSetLayouts);
 
-        vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo( // TODO: Check this. I'm not sure if this is correct
-            {},
-            {}, // TODO: For now no Descriptor Set
-            {});// (pushConstantRange)); push constant range must not be size 0, either do not specify or or set size
+        const size_t pushConstantSize = shaderProgram.getPushConstantSize();
+        vk::PushConstantRange pushConstantRange(vk::ShaderStageFlagBits::eCompute, 0, pushConstantSize);
+        if (pushConstantSize > 0) {
+            pipelineLayoutCreateInfo.setPushConstantRangeCount(1);
+            pipelineLayoutCreateInfo.setPPushConstantRanges(&pushConstantRange);
+        }
 
         vk::PipelineLayout vkPipelineLayout{};
         if (m_Device.createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &vkPipelineLayout) != vk::Result::eSuccess)
diff --git a/src/vkcv/PipelineManager.hpp b/src/vkcv/PipelineManager.hpp
index 568a8d5b..634f5f4e 100644
--- a/src/vkcv/PipelineManager.hpp
+++ b/src/vkcv/PipelineManager.hpp
@@ -37,7 +37,9 @@ namespace vkcv
 
         PipelineHandle createPipeline(const PipelineConfig &config, PassManager& passManager);
 
-        PipelineHandle createComputePipeline(const ShaderProgram &shaderProgram);
+        PipelineHandle createComputePipeline(
+            const ShaderProgram& shaderProgram,
+            const std::vector<vk::DescriptorSetLayout>& descriptorSetLayouts);
 
         [[nodiscard]]
         vk::Pipeline getVkPipeline(const PipelineHandle &handle) const;
-- 
GitLab