From 639c44a04ca123a89ca6cb2b248de9633d6f48e3 Mon Sep 17 00:00:00 2001
From: Alexander Gauggel <agauggel@uni-koblenz.de>
Date: Sun, 13 Jun 2021 00:11:52 +0200
Subject: [PATCH] [#65] Added dispatch recording commands and adjusted test
 compute shader

---
 include/vkcv/Core.hpp                       |   9 ++++-
 projects/cmd_sync_test/src/main.cpp         |   2 +-
 projects/first_mesh/src/main.cpp            |   6 +--
 projects/first_triangle/shaders/comp.spv    | Bin 2004 -> 1520 bytes
 projects/first_triangle/shaders/compile.bat |   1 +
 projects/first_triangle/shaders/shader.comp |  28 +++++++------
 projects/first_triangle/src/main.cpp        |  23 +++++++++++
 src/vkcv/Core.cpp                           |  41 ++++++++++++++++++--
 src/vkcv/DescriptorManager.cpp              |   3 +-
 src/vkcv/DescriptorManager.hpp              |   3 +-
 10 files changed, 91 insertions(+), 25 deletions(-)

diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp
index d44c5016..4a51b24f 100644
--- a/include/vkcv/Core.hpp
+++ b/include/vkcv/Core.hpp
@@ -224,7 +224,7 @@ namespace vkcv
          */
         [[nodiscard]]
         DescriptorSetHandle createDescriptorSet(const std::vector<DescriptorBinding> &bindings);
-		void writeResourceDescription(DescriptorSetHandle handle, size_t setIndex, const DescriptorWrites& writes);
+		void writeDescriptorSet(DescriptorSetHandle handle, const DescriptorWrites& writes);
 
 		DescriptorSet getDescriptorSet(const DescriptorSetHandle handle) const;
 
@@ -241,6 +241,13 @@ namespace vkcv
 			const std::vector<DrawcallInfo> &drawcalls,
 			const std::vector<ImageHandle>  &renderTargets);
 
+		void recordComputeDispatchToCmdStream(
+			CommandStreamHandle cmdStream,
+			PipelineHandle computePipeline,
+			const uint32_t dispatchCount[3],
+			const std::vector<DescriptorSetUsage> &descriptorSetUsages,
+			const PushConstantData& pushConstantData);
+
 		/**
 		 * @brief end recording and present image
 		*/
diff --git a/projects/cmd_sync_test/src/main.cpp b/projects/cmd_sync_test/src/main.cpp
index 3886a53d..2494793f 100644
--- a/projects/cmd_sync_test/src/main.cpp
+++ b/projects/cmd_sync_test/src/main.cpp
@@ -207,7 +207,7 @@ int main(int argc, const char** argv) {
         vkcv::SamplerDescriptorWrite(1, sampler), 
         vkcv::SamplerDescriptorWrite(4, shadowSampler) };
     setWrites.uniformBufferWrites   = { vkcv::UniformBufferDescriptorWrite(2, lightBuffer.getHandle()) };
-	core.writeResourceDescription(descriptorSet, 0, setWrites);
+	core.writeDescriptorSet(descriptorSet, setWrites);
 
 	auto start = std::chrono::system_clock::now();
 	const auto appStartTime = start;
diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp
index 00a77c76..15bb872c 100644
--- a/projects/first_mesh/src/main.cpp
+++ b/projects/first_mesh/src/main.cpp
@@ -130,9 +130,9 @@ int main(int argc, const char** argv) {
 	};
 
 	vkcv::DescriptorWrites setWrites;
-	setWrites.sampledImageWrites	= { vkcv::SampledImageDescriptorWrite(0, texture.getHandle()) };
-	setWrites.samplerWrites			= { vkcv::SamplerDescriptorWrite(1, sampler) };
-	core.writeResourceDescription(descriptorSet, 0, setWrites);
+	setWrites.sampledImageWrites    = { vkcv::SampledImageDescriptorWrite(0, texture.getHandle()) };
+	setWrites.samplerWrites         = { vkcv::SamplerDescriptorWrite(1, sampler) };
+	core.writeDescriptorSet(descriptorSet, setWrites);
 
 	vkcv::ImageHandle depthBuffer = core.createImage(vk::Format::eD32Sfloat, windowWidth, windowHeight).getHandle();
 
diff --git a/projects/first_triangle/shaders/comp.spv b/projects/first_triangle/shaders/comp.spv
index 622ced351097932ea7f7eb1451e9433bc017812d..b414e36b2bea66dab00746298e536d029091e0fd 100644
GIT binary patch
literal 1520
zcmZQ(Qf6mhU}WH8;AJplfB-=TCI&_Z1_o{hHZbk(6YQf`T#}+^Vrl?V!N<T1qQG+e
z3~UUn3=9k`3=9mpiJ5sI2~GwE1_1^(u$UkN16Uqp9tbltFf%YQFfi<31nJ>oaQBIK
z_xE@Aag9$dD2OjEsmw`@&&kY7jZeueN=+`wEK3Ec<3LiEnU|bXnu4r=m4O9p7tDTE
z1`Y<08`5*)-E;Dj5_3HB%JP#FOEUBGJYB%<VP%kDU|=XoEiQ2?O-oBHVgUOBBnEOn
zNZgPCAqH|cNX!UH4CDupm@(KqW(FycMlhR|L5G2XAvr&<xFj*Jq!_G+9V`Y?Qczl)
z;S7}n@mU#|8T3F51_lOq1{ScpxfvK3WT1ReuzpY&K;*^H_~J->4+e<8K*lM92nGfQ
zm>9?pATbRjF_0fXVgX>gn89HJidm35K>ksJngQc0Lir#wL4E{rLHa?oI|DP=k03Ka
z>P^Avhk-$ofq_Aofe9SviVUFGX8^NB8CV$D7#J87K$;mC7{nP^7}%kH0l7hefrWvC
z0hBTsz~a_WJ}6#6e$j^N=Yr}7sRxA{NDgE!OrDQ{fdQmOgn@~HpMilvjDeX!1ZuAg
z0}BHvd_jDWIuIWezQ}w~_`>*d(C`K60jUGYf$RnO5#(=B`T@BU#0P~RNDSmpX{dc5
zw}IRR;)CKB<aCgJP&k9sg6x6Gt3dq@;)BH1L5dl=oIre#eoY2QILbl89i#?imM#MW
zI1Pc~2jmtIAC$g8;Rce|hsuN0gUkYj6(kKaFu?dGP`h;)*uY^Aic63hkT?jNF|dN;
z5R~UZ&H}~P4+bW1K6hkbWdOwk57Zt|*xN$mikE?b0VKYTffXDV0t^fcATdzbe`jE3
z5CR#-z`*c}frSAi2P!*2Vj#0Y?7s|*3?Md03}%lk7JK9v7#Kj}Fg5a6)PT|*NW6f7
z1)Ls0X&WTw$iT(`iVsk_2E`#Lo<Qc=F)%ZL#6ap`=Bi>bSB-&z0VEDH2bAAH=78c8
zBnL7FBnFC4m^oTl%+Y3GU;v4O)PUj)RPci05#%0Fc!J^&R7QcsVRnJaCy-sBv;oo&
QvI`^zQU?k<3kF680KX7p%K!iX

literal 2004
zcmZQ(Qf6mhU}WH8;AQY)fB-=TCI&_Z1_o{hHZbk(6YQf`T#}+^Vrl?V!N<T1qQG+e
z3~UUn3=9k`3=9mpiJ5sI31J2X1_1^(u$UkN$aDl|W?*JuVqjp{!3fgB#o+D}@9yvK
z?&BJtTu=~STvC~n8lRJyml~gvS(KVwl3A7tQpbU$E;BDVr!)mw0V@Lw*e;m;tPHFS
zoD2*M0f|M4xv3?oMa2wYSAxVq?hDUMDal|!h=Kg-k(!yFQ34WU0qX_1F_D3R0c18e
z0|P?=$gE-zpMwG9zx14V_niEs#2nAOvi#)4lFa-(PZzLyW(Exg28PTOkXjZ7BL)VB
zoWx3SxPd|n#0R+{v8X7%5~|(=Bmic!Fjzy>8-j#D>Op)E8>GGhtcIDv79_yHz~BM(
zCy1*IB9O#DegcVs;svG-<R_3A2Ll6xI|DP^pY9ASU_XKUDFc>cVE{RR4H~Z?{V;cf
z^n<Jd=?95{QUXXn$PY>&38;P$UlECK1rBdeTteIp^B1ytATgMEAU`6T2jYXw1NjSN
zpF1>Nfvf=WJ)nG;yeByQGB8LoFfa%+FoDyYA_FM(F@V`33``6l|A{iNFt9T)Fercw
zVqjnpV_;?gg%5}?2Mu44JP1R?Ss1t&7{Fl%N>A1d5I!jEKzxvSJW%sMZqa67VF2-Y
zq2?<vurTmJ^@Ge5XJBCf<q;4Y<ady~5Y#Uqagg~SJ}Aw>%mb+vK{8JisvaZ`vkw%H
z$m->xYCz_zGcbVt3{o%4zzmLSkl*AOn8E246!#!?#te|K0>v}P9Uwj^UP0*yW{(+E
z4M@E?)L$U8K<0wt9K;5h3yND1AEeF(ss|(nG8e=L#V^QQki0!q9;DX@8b7f3hVfzX
zZOp(14nI(QgVcb;L4Gx3U<JoBDE)(i3KX_K7?{9i706Cd7=ZFAC=47KSiy0^4^1<m
zxUz-XE5N|O01^kO0fn;|I6W~ifWjZ9MjV`O7#KD&u!7T+1i1WTU;v4)U|<1@fzlyJ
z{5u0PgEYuN3=9mv7+ApRQ;LBBECzBPhz+s}ltyHs?g7Om%q}?w1_qEgNDat6pmYjK
z8z4W!)PV8{NF3%KP(A|b1Bw4+V1nBPa>rK&cCh<E`4HqjP+1OA4{`^{t*S_F1*uVC
zU|;}=f!qpW|7Bog0I@-0AUA>BtqFBEayV)+Fff3`L25wm)`o^7vb%K{7#Kj}Eex#S
z^r_3hzyQ(*5{K#2gX%*Le|-i929S6IR3E6Y1?dHe+c7}OV~`jud`uY_z-2VZOi-G&
zfVvlymO*Mj>CTdYfdM2A;)BwN9b69^11NnuFff42VUQm|av*geeU1za3?R8y23Bx6
z;>5tf05S_C?#KYq>&(Ew0Ln)oy&$*1^n&USkX$2FuPXxs14s;H228ITnqH9qKw==Z
Lpt!JLU}OLQO6q=L

diff --git a/projects/first_triangle/shaders/compile.bat b/projects/first_triangle/shaders/compile.bat
index b4521235..17743a7c 100644
--- a/projects/first_triangle/shaders/compile.bat
+++ b/projects/first_triangle/shaders/compile.bat
@@ -1,3 +1,4 @@
 %VULKAN_SDK%\Bin32\glslc.exe shader.vert -o vert.spv
 %VULKAN_SDK%\Bin32\glslc.exe shader.frag -o frag.spv
+%VULKAN_SDK%\Bin32\glslc.exe shader.comp -o comp.spv
 pause
\ No newline at end of file
diff --git a/projects/first_triangle/shaders/shader.comp b/projects/first_triangle/shaders/shader.comp
index c63870da..fad6cd08 100644
--- a/projects/first_triangle/shaders/shader.comp
+++ b/projects/first_triangle/shaders/shader.comp
@@ -1,21 +1,25 @@
 #version 440
 
-layout(local_size_x_id = 0, local_size_y_id = 1) in; // workgroup size defined with specialization constants. On cpp side there is associated SpecializationInfo entry in PipelineShaderStageCreateInfo
-layout(push_constant) uniform Parameters {           // specify push constants. on cpp side its layout is fixed at PipelineLayout, and values are provided via vk::CommandBuffer::pushConstants()
-    uint Width;
-    uint Height;
-    float a;
-} params;
+layout(std430, binding = 0) buffer testBuffer
+{ 
+    float test1[10];
+    float test2[10];
+    float test3[10];
+};
 
-layout(std430, binding = 0) buffer lay0 { float arr_y[]; };
-layout(std430, binding = 1) buffer lay1 { float arr_x[]; };
+layout( push_constant ) uniform constants{
+    float pushConstant;
+};
+
+layout(local_size_x = 5) in;
 
 void main(){
-    // drop threads outside the buffer dimensions.
-    if(params.Width <= gl_GlobalInvocationID.x || params.Height <= gl_GlobalInvocationID.y){
+
+    if(gl_GlobalInvocationID.x >= 10){
         return;
     }
-    const uint id = params.Width*gl_GlobalInvocationID.y + gl_GlobalInvocationID.x; // current offset
 
-    arr_y[id] += params.a*arr_x[id]; // saxpy
+    test1[gl_GlobalInvocationID.x] = gl_GlobalInvocationID.x;
+    test2[gl_GlobalInvocationID.x] = 69;  // nice!
+    test3[gl_GlobalInvocationID.x] = pushConstant;    
 }
\ No newline at end of file
diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp
index d79ece30..ca10434b 100644
--- a/projects/first_triangle/src/main.cpp
+++ b/projects/first_triangle/src/main.cpp
@@ -128,6 +128,18 @@ int main(int argc, const char** argv) {
 		computeShaderProgram, 
 		{ core.getDescriptorSet(computeDescriptorSet).layout });
 
+	struct ComputeTestBuffer {
+		float test1[10];
+		float test2[10];
+		float test3[10];
+	};
+
+	vkcv::Buffer computeTestBuffer = core.createBuffer<ComputeTestBuffer>(vkcv::BufferType::STORAGE, 1);
+
+	vkcv::DescriptorWrites computeDescriptorWrites;
+	computeDescriptorWrites.storageBufferWrites = { vkcv::StorageBufferDescriptorWrite(0, computeTestBuffer.getHandle()) };
+	core.writeDescriptorSet(computeDescriptorSet, computeDescriptorWrites);
+
 	/*
 	 * BufferHandle triangleVertices = core.createBuffer(vertices);
 	 * BufferHandle triangleIndices = core.createBuffer(indices);
@@ -177,6 +189,17 @@ int main(int argc, const char** argv) {
 			pushConstantData,
 			{ drawcall },
 			{ swapchainInput });
+
+		const uint32_t dispatchSize[3] = { 2, 1, 1 };
+		const float theMeaningOfLife = 42;
+
+		core.recordComputeDispatchToCmdStream(
+			cmdStream,
+			computePipeline,
+			dispatchSize,
+			{ vkcv::DescriptorSetUsage(0, core.getDescriptorSet(computeDescriptorSet).vulkanHandle) },
+			vkcv::PushConstantData((void*)&theMeaningOfLife, sizeof(theMeaningOfLife)));
+
 		core.prepareSwapchainImageForPresent(cmdStream);
 		core.submitCommandStream(cmdStream);
 	    
diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp
index afa45006..339f1072 100644
--- a/src/vkcv/Core.cpp
+++ b/src/vkcv/Core.cpp
@@ -305,6 +305,40 @@ namespace vkcv
 		recordCommandsToStream(cmdStreamHandle, submitFunction, finishFunction);
 	}
 
+	void Core::recordComputeDispatchToCmdStream(
+		CommandStreamHandle cmdStreamHandle,
+		PipelineHandle computePipeline,
+		const uint32_t dispatchCount[3],
+		const std::vector<DescriptorSetUsage>& descriptorSetUsages,
+		const PushConstantData& pushConstantData) {
+
+		auto submitFunction = [&](const vk::CommandBuffer& cmdBuffer) {
+
+			const auto pipelineLayout = m_PipelineManager->getVkPipelineLayout(computePipeline);
+
+			cmdBuffer.bindPipeline(vk::PipelineBindPoint::eCompute, m_PipelineManager->getVkPipeline(computePipeline));
+			for (const auto& usage : descriptorSetUsages) {
+				cmdBuffer.bindDescriptorSets(
+					vk::PipelineBindPoint::eCompute,
+					pipelineLayout,
+					usage.setLocation,
+					{ usage.vulkanHandle },
+					{});
+			}
+			if (pushConstantData.sizePerDrawcall > 0) {
+				cmdBuffer.pushConstants(
+					pipelineLayout,
+					vk::ShaderStageFlagBits::eCompute,
+					0,
+					pushConstantData.sizePerDrawcall,
+					pushConstantData.data);
+			}
+			cmdBuffer.dispatch(dispatchCount[0], dispatchCount[1], dispatchCount[2]);
+		};
+
+		recordCommandsToStream(cmdStreamHandle, submitFunction, nullptr);
+	}
+
 	void Core::endFrame() {
 		if (m_currentSwapchainImageIndex == std::numeric_limits<uint32_t>::max()) {
 			return;
@@ -409,10 +443,9 @@ namespace vkcv
         return m_DescriptorManager->createDescriptorSet(bindings);
     }
 
-	void Core::writeResourceDescription(DescriptorSetHandle handle, size_t setIndex, const DescriptorWrites &writes) {
-		m_DescriptorManager->writeResourceDescription(
-			handle, 
-			setIndex, 
+	void Core::writeDescriptorSet(DescriptorSetHandle handle, const DescriptorWrites &writes) {
+		m_DescriptorManager->writeDescriptorSet(
+			handle,  
 			writes, 
 			*m_ImageManager, 
 			*m_BufferManager, 
diff --git a/src/vkcv/DescriptorManager.cpp b/src/vkcv/DescriptorManager.cpp
index 99e9928d..5c14b928 100644
--- a/src/vkcv/DescriptorManager.cpp
+++ b/src/vkcv/DescriptorManager.cpp
@@ -90,9 +90,8 @@ namespace vkcv
 		vk::DescriptorType type;
     };
 
-	void DescriptorManager::writeResourceDescription(
+	void DescriptorManager::writeDescriptorSet(
 		const DescriptorSetHandle	&handle,
-		size_t					setIndex,
 		const DescriptorWrites	&writes,
 		const ImageManager		&imageManager, 
 		const BufferManager		&bufferManager,
diff --git a/src/vkcv/DescriptorManager.hpp b/src/vkcv/DescriptorManager.hpp
index d8607b93..d18be64f 100644
--- a/src/vkcv/DescriptorManager.hpp
+++ b/src/vkcv/DescriptorManager.hpp
@@ -23,9 +23,8 @@ namespace vkcv
 
         DescriptorSetHandle createDescriptorSet(const std::vector<DescriptorBinding> &descriptorBindings);
 
-		void writeResourceDescription(
+		void writeDescriptorSet(
 			const DescriptorSetHandle	&handle,
-			size_t					setIndex,
 			const DescriptorWrites  &writes,
 			const ImageManager      &imageManager,
 			const BufferManager     &bufferManager,
-- 
GitLab