From fa9a7f2efd1ceb51deb6942ac875b07cc59d3fa4 Mon Sep 17 00:00:00 2001
From: Alexander Gauggel <agauggel@uni-koblenz.de>
Date: Sat, 19 Jun 2021 16:45:49 +0200
Subject: [PATCH] [#81] Add option to visualize different voxel mips

---
 include/vkcv/DescriptorWrites.hpp          |  4 ++-
 include/vkcv/Image.hpp                     |  2 +-
 projects/voxelization/src/Voxelization.cpp | 29 ++++++++++++++--------
 projects/voxelization/src/Voxelization.hpp |  3 ++-
 projects/voxelization/src/main.cpp         |  5 +++-
 src/vkcv/DescriptorManager.cpp             |  2 +-
 src/vkcv/Image.cpp                         |  6 ++++-
 src/vkcv/ImageManager.cpp                  | 16 ++++++++++++
 src/vkcv/ImageManager.hpp                  |  3 +++
 9 files changed, 53 insertions(+), 17 deletions(-)

diff --git a/include/vkcv/DescriptorWrites.hpp b/include/vkcv/DescriptorWrites.hpp
index d67e8e32..016bdab7 100644
--- a/include/vkcv/DescriptorWrites.hpp
+++ b/include/vkcv/DescriptorWrites.hpp
@@ -10,9 +10,11 @@ namespace vkcv {
 	};
 
 	struct StorageImageDescriptorWrite {
-		inline StorageImageDescriptorWrite(uint32_t binding, ImageHandle image) : binding(binding), image(image) {};
+		inline StorageImageDescriptorWrite(uint32_t binding, ImageHandle image, uint32_t mipLevel = 0) 
+			: binding(binding), image(image), mipLevel(mipLevel) {};
 		uint32_t	binding;
 		ImageHandle	image;
+		uint32_t	mipLevel;
 	};
 
 	struct UniformBufferDescriptorWrite {
diff --git a/include/vkcv/Image.hpp b/include/vkcv/Image.hpp
index f8e35ccb..9e1f9708 100644
--- a/include/vkcv/Image.hpp
+++ b/include/vkcv/Image.hpp
@@ -34,7 +34,7 @@ namespace vkcv {
 		vkcv::ImageHandle getHandle() const;
 
 		[[nodiscard]]
-		uint32_t getMipCount();
+		uint32_t getMipCount() const;
 
 		void switchLayout(vk::ImageLayout newLayout);
 		
diff --git a/projects/voxelization/src/Voxelization.cpp b/projects/voxelization/src/Voxelization.cpp
index a101a03a..12b179e7 100644
--- a/projects/voxelization/src/Voxelization.cpp
+++ b/projects/voxelization/src/Voxelization.cpp
@@ -1,6 +1,7 @@
 #include "Voxelization.hpp"
 #include <vkcv/shader/GLSLCompiler.hpp>
 #include <glm/gtc/matrix_transform.hpp>
+#include <algorithm>
 
 vkcv::ShaderProgram loadVoxelizationShader() {
 	vkcv::shader::GLSLCompiler compiler;
@@ -153,13 +154,6 @@ Voxelization::Voxelization(
 		voxelIndexData.push_back(i);
 	}
 
-	vkcv::DescriptorWrites voxelVisualisationDescriptorWrite;
-	voxelVisualisationDescriptorWrite.storageImageWrites = 
-	{ vkcv::StorageImageDescriptorWrite(0, m_voxelImage.getHandle()) };
-	voxelVisualisationDescriptorWrite.uniformBufferWrites = 
-	{ vkcv::UniformBufferDescriptorWrite(1, m_voxelInfoBuffer.getHandle()) };
-	m_corePtr->writeDescriptorSet(m_visualisationDescriptorSet, voxelVisualisationDescriptorWrite);
-
 	const vkcv::DescriptorSetUsage voxelizationDescriptorUsage(0, m_corePtr->getDescriptorSet(m_visualisationDescriptorSet).vulkanHandle);
 
 	vkcv::ShaderProgram resetVoxelShader = loadVoxelResetShader();
@@ -277,14 +271,27 @@ void Voxelization::voxelizeMeshes(
 }
 
 void Voxelization::renderVoxelVisualisation(
-	vkcv::CommandStreamHandle cmdStream, 
-	const glm::mat4& viewProjectin,
-	const std::vector<vkcv::ImageHandle>& renderTargets) {
+	vkcv::CommandStreamHandle               cmdStream, 
+	const glm::mat4&                        viewProjectin,
+	const std::vector<vkcv::ImageHandle>&   renderTargets,
+	uint32_t                                mipLevel) {
 
 	const vkcv::PushConstantData voxelVisualisationPushConstantData((void*)&viewProjectin, sizeof(glm::mat4));
 
+	mipLevel = std::clamp(mipLevel, (uint32_t)0, m_voxelImage.getMipCount()-1);
+
+	// write descriptor set
+	vkcv::DescriptorWrites voxelVisualisationDescriptorWrite;
+	voxelVisualisationDescriptorWrite.storageImageWrites =
+	{ vkcv::StorageImageDescriptorWrite(0, m_voxelImage.getHandle(), mipLevel) };
+	voxelVisualisationDescriptorWrite.uniformBufferWrites =
+	{ vkcv::UniformBufferDescriptorWrite(1, m_voxelInfoBuffer.getHandle()) };
+	m_corePtr->writeDescriptorSet(m_visualisationDescriptorSet, voxelVisualisationDescriptorWrite);
+
+	uint32_t drawVoxelCount = voxelCount / exp2(mipLevel);
+
 	const auto drawcall = vkcv::DrawcallInfo(
-		vkcv::Mesh({}, nullptr, voxelCount),
+		vkcv::Mesh({}, nullptr, drawVoxelCount),
 		{ vkcv::DescriptorSetUsage(0, m_corePtr->getDescriptorSet(m_visualisationDescriptorSet).vulkanHandle) });
 
 	m_corePtr->recordDrawcallsToCmdStream(
diff --git a/projects/voxelization/src/Voxelization.hpp b/projects/voxelization/src/Voxelization.hpp
index 0e62b059..81039e5e 100644
--- a/projects/voxelization/src/Voxelization.hpp
+++ b/projects/voxelization/src/Voxelization.hpp
@@ -26,7 +26,8 @@ public:
 	void renderVoxelVisualisation(
 		vkcv::CommandStreamHandle               cmdStream,
 		const glm::mat4&                        viewProjectin,
-		const std::vector<vkcv::ImageHandle>&   renderTargets);
+		const std::vector<vkcv::ImageHandle>&   renderTargets,
+		uint32_t                                mipLevel);
 
 private:
 	vkcv::Core* m_corePtr;
diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp
index 53c25e6d..b37f6869 100644
--- a/projects/voxelization/src/main.cpp
+++ b/projects/voxelization/src/main.cpp
@@ -329,6 +329,7 @@ int main(int argc, const char** argv) {
 	vkcv::gui::GUI gui(core, window);
 
 	glm::vec2 lightAngles(90.f, 0.f);
+	int voxelVisualisationMip = 0;
 
 	auto start = std::chrono::system_clock::now();
 	const auto appStartTime = start;
@@ -429,7 +430,7 @@ int main(int argc, const char** argv) {
 			renderTargets);
 
 		if (renderVoxelVis) {
-			voxelization.renderVoxelVisualisation(cmdStream, viewProjectionCamera, renderTargets);
+			voxelization.renderVoxelVisualisation(cmdStream, viewProjectionCamera, renderTargets, voxelVisualisationMip);
 		}
 
 		const uint32_t tonemappingLocalGroupSize = 8;
@@ -459,6 +460,8 @@ int main(int argc, const char** argv) {
 		ImGui::DragFloat2("Light angles",   &lightAngles.x);
 		ImGui::ColorEdit3("Sun color",      &lightInfo.sunColor.x);
 		ImGui::DragFloat("Sun strength",    &lightInfo.sunStrength);
+		ImGui::SliderInt("Visualisation mip", &voxelVisualisationMip, 0, 7);
+		voxelVisualisationMip = std::max(voxelVisualisationMip, 0);
 		ImGui::End();
 
 		gui.endGUI();
diff --git a/src/vkcv/DescriptorManager.cpp b/src/vkcv/DescriptorManager.cpp
index f591daf9..26553223 100644
--- a/src/vkcv/DescriptorManager.cpp
+++ b/src/vkcv/DescriptorManager.cpp
@@ -128,7 +128,7 @@ namespace vkcv
 		for (const auto& write : writes.storageImageWrites) {
 			const vk::DescriptorImageInfo imageInfo(
 				nullptr,
-				imageManager.getVulkanImageView(write.image),
+				imageManager.getVulkanImageView(write.image, write.mipLevel),
 				vk::ImageLayout::eGeneral
 			);
 			
diff --git a/src/vkcv/Image.cpp b/src/vkcv/Image.cpp
index 0a3353f7..c48b0153 100644
--- a/src/vkcv/Image.cpp
+++ b/src/vkcv/Image.cpp
@@ -56,7 +56,11 @@ namespace vkcv{
 	vkcv::ImageHandle Image::getHandle() const {
 		return m_handle;
 	}
-	
+
+	uint32_t Image::getMipCount() const {
+		return m_manager->getImageMipCount(m_handle);
+	}
+
 	void Image::fill(void *data, size_t size) {
 		m_manager->fillImage(m_handle, data, size);
 	}
diff --git a/src/vkcv/ImageManager.cpp b/src/vkcv/ImageManager.cpp
index 14d7c506..a3364ce0 100644
--- a/src/vkcv/ImageManager.cpp
+++ b/src/vkcv/ImageManager.cpp
@@ -605,6 +605,22 @@ namespace vkcv {
 		return isSwapchainFormat ? m_swapchainImages[m_currentSwapchainInputImage].m_format : m_images[id].m_format;
 	}
 
+	uint32_t ImageManager::getImageMipCount(const ImageHandle& handle) const {
+		const uint64_t id = handle.getId();
+		const bool isSwapchainFormat = handle.isSwapchainImage();
+
+		if (handle.isSwapchainImage()) {
+			return 1;
+		}
+
+		if (id >= m_images.size()) {
+			vkcv_log(LogLevel::ERROR, "Invalid handle");
+			return 0;
+		}
+
+		return m_images[id].m_viewPerMip.size();
+	}
+
 	void ImageManager::setCurrentSwapchainImageIndex(int index) {
 		m_currentSwapchainInputImage = index;
 	}
diff --git a/src/vkcv/ImageManager.hpp b/src/vkcv/ImageManager.hpp
index 9cd1a8de..ecba7eb5 100644
--- a/src/vkcv/ImageManager.hpp
+++ b/src/vkcv/ImageManager.hpp
@@ -117,6 +117,9 @@ namespace vkcv {
 		[[nodiscard]]
 		vk::Format getImageFormat(const ImageHandle& handle) const;
 
+		[[nodiscard]]
+		uint32_t getImageMipCount(const ImageHandle& handle) const;
+
 		void setCurrentSwapchainImageIndex(int index);
 		void setSwapchainImages(const std::vector<vk::Image>& images, std::vector<vk::ImageView> views,
 			uint32_t width, uint32_t height, vk::Format format);
-- 
GitLab