From aa337bd87b510334f30c91a34320879e6828350d Mon Sep 17 00:00:00 2001
From: Tobias Frisch <tfrisch@uni-koblenz.de>
Date: Mon, 19 Jul 2021 15:56:59 +0200
Subject: [PATCH] [#100] Added mip load bias and re-added slider for sharpness

Signed-off-by: Tobias Frisch <tfrisch@uni-koblenz.de>
---
 include/vkcv/Core.hpp                         |  4 +-
 .../include/vkcv/upscaling/FSRUpscaling.hpp   |  2 +
 .../src/vkcv/upscaling/FSRUpscaling.cpp       | 15 +++++++
 projects/voxelization/src/main.cpp            | 40 ++++++++++++++++---
 src/vkcv/Core.cpp                             |  5 ++-
 src/vkcv/SamplerManager.cpp                   |  5 ++-
 src/vkcv/SamplerManager.hpp                   |  3 +-
 7 files changed, 62 insertions(+), 12 deletions(-)

diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp
index 076e1a3e..bcca46d6 100644
--- a/include/vkcv/Core.hpp
+++ b/include/vkcv/Core.hpp
@@ -196,11 +196,13 @@ namespace vkcv
          * @param minFilter Minimizing filter
          * @param mipmapMode Mipmapping filter
          * @param addressMode Address mode
+         * @param mipLodBias Mip level of detail bias
          * @return Sampler handle
          */
         [[nodiscard]]
         SamplerHandle createSampler(SamplerFilterType magFilter, SamplerFilterType minFilter,
-									SamplerMipmapMode mipmapMode, SamplerAddressMode addressMode);
+									SamplerMipmapMode mipmapMode, SamplerAddressMode addressMode,
+									float mipLodBias = 0.0f);
 
         /**
          * Creates an #Image with a given format, width, height and depth.
diff --git a/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp b/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp
index 50f6eda3..8492029f 100644
--- a/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp
+++ b/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp
@@ -18,6 +18,8 @@ namespace vkcv::upscaling {
 						  uint32_t outputWidth, uint32_t outputHeight,
 						  uint32_t &inputWidth, uint32_t &inputHeight);
 	
+	float getFSRLodBias(FSRQualityMode mode);
+	
 	struct FSRConstants {
 		uint32_t Const0 [4];
 		uint32_t Const1 [4];
diff --git a/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp b/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp
index 44be1052..df7b8e8e 100644
--- a/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp
+++ b/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp
@@ -50,6 +50,21 @@ namespace vkcv::upscaling {
 		);
 	}
 	
+	float getFSRLodBias(FSRQualityMode mode) {
+		switch (mode) {
+			case FSRQualityMode::ULTRA_QUALITY:
+				return -0.38f;
+			case FSRQualityMode::QUALITY:
+				return -0.58f;
+			case FSRQualityMode::BALANCED:
+				return -0.79f;
+			case FSRQualityMode::PERFORMANCE:
+				return -1.0f;
+			default:
+				return 0.0f;
+		}
+	}
+	
 	static std::vector<DescriptorBinding> getDescriptorBindings() {
 		return std::vector<DescriptorBinding>({
 			DescriptorBinding(
diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp
index 8de24d2e..4d8d5d1e 100644
--- a/projects/voxelization/src/main.cpp
+++ b/projects/voxelization/src/main.cpp
@@ -454,7 +454,8 @@ int main(int argc, const char** argv) {
 		vkcv::SamplerFilterType::NEAREST,
 		vkcv::SamplerFilterType::NEAREST,
 		vkcv::SamplerMipmapMode::NEAREST,
-		vkcv::SamplerAddressMode::CLAMP_TO_EDGE);
+		vkcv::SamplerAddressMode::CLAMP_TO_EDGE
+	);
 
 	// model matrices per mesh
 	std::vector<glm::mat4> modelMatrices;
@@ -489,7 +490,8 @@ int main(int argc, const char** argv) {
 		vkcv::SamplerFilterType::LINEAR,
 		vkcv::SamplerFilterType::LINEAR,
 		vkcv::SamplerMipmapMode::LINEAR,
-		vkcv::SamplerAddressMode::CLAMP_TO_EDGE);
+		vkcv::SamplerAddressMode::CLAMP_TO_EDGE
+	);
 
 	ShadowMapping shadowMapping(&core, vertexLayout);
 
@@ -553,6 +555,9 @@ int main(int argc, const char** argv) {
 			"Performance"
 	};
 	
+	bool fsrMipLoadBiasFlag = true;
+	bool fsrMipLoadBiasFlagBackup = fsrMipLoadBiasFlag;
+	
 	vkcv::gui::GUI gui(core, window);
 
 	glm::vec2   lightAnglesDegree               = glm::vec2(90.f, 0.f);
@@ -588,18 +593,35 @@ int main(int argc, const char** argv) {
 				width, height
 		);
 
-		if ((width != fsrWidth) || ((height != fsrHeight))) {
+		if ((width != fsrWidth) || ((height != fsrHeight)) || (fsrMipLoadBiasFlagBackup != fsrMipLoadBiasFlag)) {
 			fsrWidth = width;
 			fsrHeight = height;
+			fsrMipLoadBiasFlagBackup = fsrMipLoadBiasFlag;
+			
+			colorSampler = core.createSampler(
+					vkcv::SamplerFilterType::LINEAR,
+					vkcv::SamplerFilterType::LINEAR,
+					vkcv::SamplerMipmapMode::LINEAR,
+					vkcv::SamplerAddressMode::REPEAT,
+					fsrMipLoadBiasFlag? vkcv::upscaling::getFSRLodBias(fsrMode) : 0.0f
+			);
 			
-			depthBuffer         = core.createImage(
+			for (size_t i = 0; i < scene.materials.size(); i++) {
+				vkcv::DescriptorWrites setWrites;
+				setWrites.samplerWrites = {
+						vkcv::SamplerDescriptorWrite(1, colorSampler),
+				};
+				core.writeDescriptorSet(materialDescriptorSets[i], setWrites);
+			}
+			
+			depthBuffer = core.createImage(
 					depthBufferFormat,
 					fsrWidth, fsrHeight, 1,
 					false, false, false,
 					msaa
 			).getHandle();
 			
-			colorBuffer         = core.createImage(
+			colorBuffer = core.createImage(
 					colorBufferFormat,
 					fsrWidth, fsrHeight, 1,
 					false, colorBufferRequiresStorage, true,
@@ -866,11 +888,17 @@ int main(int argc, const char** argv) {
 			ImGui::DragFloat("Absorption density", &absorptionDensity, 0.0001);
 			ImGui::DragFloat("Volumetric ambient", &volumetricAmbient, 0.002);
 			
-			ImGui::Combo("FidelityFX FSR Quality Mode", &fsrModeIndex, fsrModeNames.data(), fsrModeNames.size());
+			float fsrSharpness = upscaling.getSharpness();
+			
+			ImGui::Combo("FSR Quality Mode", &fsrModeIndex, fsrModeNames.data(), fsrModeNames.size());
+			ImGui::DragFloat("FSR Sharpness", &fsrSharpness, 0.01, 0.0f, 1.0f);
+			ImGui::Checkbox("FSR Mip Lod Bias", &fsrMipLoadBiasFlag);
 			
 			if ((fsrModeIndex >= 0) && (fsrModeIndex <= 4)) {
 				fsrMode = static_cast<vkcv::upscaling::FSRQualityMode>(fsrModeIndex);
 			}
+			
+			upscaling.setSharpness(fsrSharpness);
 
 			if (ImGui::Button("Reload forward pass")) {
 
diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp
index a50303bb..00b59da8 100644
--- a/src/vkcv/Core.cpp
+++ b/src/vkcv/Core.cpp
@@ -486,8 +486,9 @@ namespace vkcv
 	}
 
 	SamplerHandle Core::createSampler(SamplerFilterType magFilter, SamplerFilterType minFilter,
-									  SamplerMipmapMode mipmapMode, SamplerAddressMode addressMode) {
-		return m_SamplerManager->createSampler(magFilter, minFilter, mipmapMode, addressMode);
+									  SamplerMipmapMode mipmapMode, SamplerAddressMode addressMode,
+									  float mipLodBias) {
+		return m_SamplerManager->createSampler(magFilter, minFilter, mipmapMode, addressMode, mipLodBias);
 	}
 
 	Image Core::createImage(
diff --git a/src/vkcv/SamplerManager.cpp b/src/vkcv/SamplerManager.cpp
index ecc6de09..792e6f16 100644
--- a/src/vkcv/SamplerManager.cpp
+++ b/src/vkcv/SamplerManager.cpp
@@ -17,7 +17,8 @@ namespace vkcv {
 	SamplerHandle SamplerManager::createSampler(SamplerFilterType magFilter,
 												SamplerFilterType minFilter,
 												SamplerMipmapMode mipmapMode,
-												SamplerAddressMode addressMode) {
+												SamplerAddressMode addressMode,
+												float mipLodBias) {
 		vk::Filter vkMagFilter;
 		vk::Filter vkMinFilter;
 		vk::SamplerMipmapMode vkMipmapMode;
@@ -81,7 +82,7 @@ namespace vkcv {
 				vkAddressMode,
 				vkAddressMode,
 				vkAddressMode,
-				0.0f,
+				mipLodBias,
 				false,
 				16.0f,
 				false,
diff --git a/src/vkcv/SamplerManager.hpp b/src/vkcv/SamplerManager.hpp
index 511176d4..aea47a03 100644
--- a/src/vkcv/SamplerManager.hpp
+++ b/src/vkcv/SamplerManager.hpp
@@ -32,7 +32,8 @@ namespace vkcv {
 		SamplerHandle createSampler(SamplerFilterType magFilter,
 							  		SamplerFilterType minFilter,
 							  		SamplerMipmapMode mipmapMode,
-							  		SamplerAddressMode addressMode);
+							  		SamplerAddressMode addressMode,
+							  		float mipLodBias);
 		
 		[[nodiscard]]
 		vk::Sampler getVulkanSampler(const SamplerHandle& handle) const;
-- 
GitLab