From cdfcc722a620ebc777fccec0a0874e9d408c412d Mon Sep 17 00:00:00 2001
From: Alexander Gauggel <agauggel@uni-koblenz.de>
Date: Sun, 13 Jun 2021 23:52:48 +0200
Subject: [PATCH] [#70] Add compute shader that resets voxel image every frame

---
 .../resources/shaders/compile.bat             |   2 +
 .../resources/shaders/voxelReset.comp         |  13 +++
 .../resources/shaders/voxelReset_comp.spv     | Bin 0 -> 912 bytes
 projects/cmd_sync_test/src/main.cpp           |  98 +++++++++++-------
 4 files changed, 78 insertions(+), 35 deletions(-)
 create mode 100644 projects/cmd_sync_test/resources/shaders/voxelReset.comp
 create mode 100644 projects/cmd_sync_test/resources/shaders/voxelReset_comp.spv

diff --git a/projects/cmd_sync_test/resources/shaders/compile.bat b/projects/cmd_sync_test/resources/shaders/compile.bat
index 26239841..b43ba299 100644
--- a/projects/cmd_sync_test/resources/shaders/compile.bat
+++ b/projects/cmd_sync_test/resources/shaders/compile.bat
@@ -11,4 +11,6 @@
 %VULKAN_SDK%\Bin32\glslc.exe voxelVisualisation.vert -o voxelVisualisation_vert.spv
 %VULKAN_SDK%\Bin32\glslc.exe voxelVisualisation.geom -o voxelVisualisation_geom.spv
 %VULKAN_SDK%\Bin32\glslc.exe voxelVisualisation.frag -o voxelVisualisation_frag.spv
+
+%VULKAN_SDK%\Bin32\glslc.exe voxelReset.comp -o voxelReset_comp.spv
 pause
\ No newline at end of file
diff --git a/projects/cmd_sync_test/resources/shaders/voxelReset.comp b/projects/cmd_sync_test/resources/shaders/voxelReset.comp
new file mode 100644
index 00000000..ca67b74c
--- /dev/null
+++ b/projects/cmd_sync_test/resources/shaders/voxelReset.comp
@@ -0,0 +1,13 @@
+#version 440
+
+layout(set=0, binding=0, r8) uniform image3D voxelImage;
+
+layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
+
+void main(){
+
+    if(any(greaterThanEqual(gl_GlobalInvocationID, imageSize(voxelImage)))){
+        return;
+    }  
+    imageStore(voxelImage, ivec3(gl_GlobalInvocationID), vec4(0.f));
+}
\ No newline at end of file
diff --git a/projects/cmd_sync_test/resources/shaders/voxelReset_comp.spv b/projects/cmd_sync_test/resources/shaders/voxelReset_comp.spv
new file mode 100644
index 0000000000000000000000000000000000000000..6917b65c17f738d9f3378bd219467f2132e3f62d
GIT binary patch
literal 912
zcmYk4-D=cO6orp7omyM_Xa6kzW!lS@Vnsy|@02hw&<h_RjG0gaX{NN}&_bWYhw$1r
zvj~FUmt-KjtnRbc*=L`%Po~>Bd>F!mupCyyVW?v>bWlPtpEmgoc_l1XdOZ9(Jh`5Z
zPu{+J?TNL}HC21-)bv;{fQwOHsy_l7=xUq5JV%$a9r$l9T);&<OyaY%c=#nrFE5kp
z>1~lEMP6pfIKRr$X+F!WTWZziWm^0gw+nhywD0dxuZQy@iHpg%Q86fIlXNuAC*|NX
zdXK*~@@#UG6@!b>Id{Z#@XQK$4&>Gx0AtSkHLbXN*6)KYrgE-6^Z7cicj&Q5j)1WT
z=kY7enh3r`<|!)uW5e~Kwo51bM_?a!kI8a-w?n=T?6=x%SZhDIa~S&BAV<Ld`tkdy
z>1UhH+l{_c@mja;CEUAx=Og~Reg%wU+`AtEwKlBv4f?>d$1vaEpwZODd%lTtSYznt
z9>w3*CsfZY1K&pOe9r7_-{H>jq|xr0`mIL$MHlDU1@=(?NliU#t^eUhzoYS&y*=_%
mpr#Mk|9CamYI6_ISnFZ#(cg|9^`NI0KrMw^E02J^K7ju(u0rns

literal 0
HcmV?d00001

diff --git a/projects/cmd_sync_test/src/main.cpp b/projects/cmd_sync_test/src/main.cpp
index a8a51b3b..ddc6420f 100644
--- a/projects/cmd_sync_test/src/main.cpp
+++ b/projects/cmd_sync_test/src/main.cpp
@@ -189,12 +189,6 @@ int main(int argc, const char** argv) {
 
 	const uint32_t voxelResolution = 32;
 	vkcv::Image voxelImage = core.createImage(vk::Format::eR8Unorm, voxelResolution, voxelResolution, voxelResolution, true);
-
-	{
-		char voxelData [voxelResolution * voxelResolution * voxelResolution];
-		memset(voxelData, 0, sizeof(voxelData));
-		voxelImage.fill(voxelData);
-	}
 	
 	const vk::Format voxelizationDummyFormat = vk::Format::eR8Unorm;
 	vkcv::Image voxelizationDummyRenderTarget = core.createImage(voxelizationDummyFormat, voxelResolution, voxelResolution, 1, false, true);
@@ -294,29 +288,9 @@ int main(int argc, const char** argv) {
 		vkcv::Mesh({}, voxelVisualisationIndexBuffer.getVulkanHandle(), voxelCount),
 		{ vkcv::DescriptorSetUsage(0, core.getDescriptorSet(voxelVisualisationDescriptorSet).vulkanHandle) });
 
-	const std::vector<glm::vec3> instancePositions = {
-		glm::vec3(0.f, -2.f, 0.f),
-		glm::vec3(3.f,  0.f, 0.f),
-		glm::vec3(-3.f,  0.f, 0.f),
-		glm::vec3(0.f,  2.f, 0.f),
-		glm::vec3(0.f, -5.f, 0.f)
-	};
-
 	const vkcv::DescriptorSetUsage descriptorUsage(0, core.getDescriptorSet(descriptorSet).vulkanHandle);
 	const vkcv::DescriptorSetUsage voxelizationDescriptorUsage(0, core.getDescriptorSet(voxelizationDescriptorSet).vulkanHandle);
 
-	std::vector<glm::mat4> modelMatrices;
-	std::vector<vkcv::DrawcallInfo> drawcalls;
-	std::vector<vkcv::DrawcallInfo> shadowDrawcalls;
-	std::vector<vkcv::DrawcallInfo> voxelizationDrawcalls;
-	for (const auto& position : instancePositions) {
-		modelMatrices.push_back(glm::translate(glm::mat4(1.f), position));
-		drawcalls.push_back(vkcv::DrawcallInfo(loadedMesh, { descriptorUsage }));
-		shadowDrawcalls.push_back(vkcv::DrawcallInfo(loadedMesh, {}));
-		voxelizationDrawcalls.push_back(vkcv::DrawcallInfo(loadedMesh, { voxelizationDescriptorUsage }));
-	}
-	modelMatrices.back() *= glm::scale(glm::mat4(1.f), glm::vec3(10.f, 1.f, 10.f));
-
 	std::vector<std::array<glm::mat4, 2>> mainPassMatrices;
 	std::vector<glm::mat4> mvpLight;
 	std::vector<std::array<glm::mat4, 2>> voxelizationMatrices;
@@ -328,29 +302,43 @@ int main(int argc, const char** argv) {
 		}
 	});
 
+	vkcv::ShaderProgram resetVoxelShader;
+	resetVoxelShader.addShader(vkcv::ShaderStage::COMPUTE, "resources/shaders/voxelReset_comp.spv");
+	resetVoxelShader.reflectShader(vkcv::ShaderStage::COMPUTE);
+
+	vkcv::DescriptorSetHandle resetVoxelDescriptorSet = core.createDescriptorSet(resetVoxelShader.getReflectedDescriptors()[0]);
+	vkcv::PipelineHandle resetVoxelPipeline = core.createComputePipeline(
+		resetVoxelShader, 
+		{  core.getDescriptorSet(resetVoxelDescriptorSet).layout });
+
+	vkcv::DescriptorWrites resetVoxelWrites;
+	resetVoxelWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(0, voxelImage.getHandle()) };
+	core.writeDescriptorSet(resetVoxelDescriptorSet, resetVoxelWrites);
+
 	auto start = std::chrono::system_clock::now();
 	const auto appStartTime = start;
 	while (window.isWindowOpen()) {
 		vkcv::Window::pollEvents();
-		
+
 		uint32_t swapchainWidth, swapchainHeight;
 		if (!core.beginFrame(swapchainWidth, swapchainHeight)) {
 			continue;
 		}
-		
+
 		if ((swapchainWidth != windowWidth) || ((swapchainHeight != windowHeight))) {
 			depthBuffer = core.createImage(depthBufferFormat, swapchainWidth, swapchainHeight).getHandle();
-			
+
 			windowWidth = swapchainWidth;
 			windowHeight = swapchainHeight;
 		}
-		
+
 		auto end = std::chrono::system_clock::now();
 		auto deltatime = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
 		start = end;
 		cameraManager.getCamera().updateView(deltatime.count() * 0.000001);
 
-		const float sunTheta = std::chrono::duration_cast<std::chrono::milliseconds>(end - appStartTime).count() * 0.001f;
+		const float timeSinceStart = std::chrono::duration_cast<std::chrono::milliseconds>(end - appStartTime).count();
+		const float sunTheta = timeSinceStart * 0.001f;
 		lightInfo.direction = glm::normalize(glm::vec3(std::cos(sunTheta), 1, std::sin(sunTheta)));
 
 		const float shadowProjectionSize = 5.f;
@@ -377,18 +365,39 @@ int main(int argc, const char** argv) {
 		const float voxelizationHalfExtent = 0.5f * voxelizationExtent;
 		const glm::mat4 voxelizationProjection = glm::ortho(
 			-voxelizationHalfExtent,
-			 voxelizationHalfExtent,
+			voxelizationHalfExtent,
 			-voxelizationHalfExtent,
-			 voxelizationHalfExtent,
+			voxelizationHalfExtent,
 			-voxelizationHalfExtent,
-			 voxelizationHalfExtent);
+			voxelizationHalfExtent);
+
+		// compute positions and transform matrices
+		std::vector<glm::vec3> instancePositions = {
+		glm::vec3(0.f, -2.f, 0.f),
+		glm::vec3(3.f,  2 * glm::sin(timeSinceStart * 0.0025), 0.f),
+		glm::vec3(-3.f,  0.f, 0.f),
+		glm::vec3(0.f,  2.f, 0.f),
+		glm::vec3(0.f, -5.f, 0.f)
+		};
+
+		std::vector<glm::mat4> modelMatrices;
+		std::vector<vkcv::DrawcallInfo> drawcalls;
+		std::vector<vkcv::DrawcallInfo> shadowDrawcalls;
+		std::vector<vkcv::DrawcallInfo> voxelizationDrawcalls;
+		for (const auto& position : instancePositions) {
+			modelMatrices.push_back(glm::translate(glm::mat4(1.f), position));
+			drawcalls.push_back(vkcv::DrawcallInfo(loadedMesh, { descriptorUsage }));
+			shadowDrawcalls.push_back(vkcv::DrawcallInfo(loadedMesh, {}));
+			voxelizationDrawcalls.push_back(vkcv::DrawcallInfo(loadedMesh, { voxelizationDescriptorUsage }));
+		}
+		modelMatrices.back() *= glm::scale(glm::mat4(1.f), glm::vec3(10.f, 1.f, 10.f));
 
 		mainPassMatrices.clear();
 		mvpLight.clear();
 		voxelizationMatrices.clear();
 		for (const auto& m : modelMatrices) {
 			mainPassMatrices.push_back({ viewProjectionCamera * m, m });
-			mvpLight.push_back(lightInfo.lightMatrix* m);
+			mvpLight.push_back(lightInfo.lightMatrix * m);
 			voxelizationMatrices.push_back({ voxelizationProjection * m, m });
 		}
 
@@ -400,6 +409,7 @@ int main(int argc, const char** argv) {
 
 		auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics);
 
+		// shadow map
 		core.recordDrawcallsToCmdStream(
 			cmdStream,
 			shadowPass,
@@ -408,7 +418,23 @@ int main(int argc, const char** argv) {
 			shadowDrawcalls,
 			{ shadowMap.getHandle() });
 
+		// reset voxels
+		const uint32_t resetVoxelGroupSize[3] = { 4, 4, 4 };
+		uint32_t resetVoxelDispatchCount[3];
+		for(int i = 0; i < 3; i++) {
+			resetVoxelDispatchCount[i] = glm::ceil(voxelResolution / float(resetVoxelGroupSize[i]));
+		}
+
 		core.prepareImageForStorage(cmdStream, voxelImage.getHandle());
+		core.recordComputeDispatchToCmdStream(
+			cmdStream,
+			resetVoxelPipeline,
+			resetVoxelDispatchCount,
+			{ vkcv::DescriptorSetUsage(0, core.getDescriptorSet(resetVoxelDescriptorSet).vulkanHandle) },
+			vkcv::PushConstantData(nullptr, 0));
+		core.recordImageMemoryBarrier(cmdStream, voxelImage.getHandle());
+
+		// voxelization
 		core.recordDrawcallsToCmdStream(
 			cmdStream,
 			voxelizationPass,
@@ -419,6 +445,7 @@ int main(int argc, const char** argv) {
 
 		core.prepareImageForSampling(cmdStream, shadowMap.getHandle());
 
+		// main pass
 		core.recordDrawcallsToCmdStream(
 			cmdStream,
 			trianglePass,
@@ -440,6 +467,7 @@ int main(int argc, const char** argv) {
 				renderTargets);
 		}
 
+		// present and end
 		core.prepareSwapchainImageForPresent(cmdStream);
 		core.submitCommandStream(cmdStream);
 
-- 
GitLab