diff --git a/include/vkcv/Context.hpp b/include/vkcv/Context.hpp
index 2ecd9203701510837f49d10c1879efd4890145e9..12e02e96a9e81b461495ce5c2a76e35e6d226eb6 100644
--- a/include/vkcv/Context.hpp
+++ b/include/vkcv/Context.hpp
@@ -39,9 +39,9 @@ namespace vkcv
         
         static Context create(const char *applicationName,
 							  uint32_t applicationVersion,
-							  std::vector<vk::QueueFlagBits> queueFlags,
-							  std::vector<const char *> instanceExtensions,
-							  std::vector<const char *> deviceExtensions);
+							  const std::vector<vk::QueueFlagBits>& queueFlags,
+							  const std::vector<const char *>& instanceExtensions,
+							  const std::vector<const char *>& deviceExtensions);
 
     private:
         /**
diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp
index cf36fa7a3072559cfaa83edd07e058431c50059b..076e1a3e7d28cf40d4d2e8fd439084a0de46db61 100644
--- a/include/vkcv/Core.hpp
+++ b/include/vkcv/Core.hpp
@@ -138,9 +138,9 @@ namespace vkcv
         static Core create(Window &window,
                            const char *applicationName,
                            uint32_t applicationVersion,
-                           std::vector<vk::QueueFlagBits> queueFlags    = {},
-                           std::vector<const char*> instanceExtensions  = {},
-                           std::vector<const char*> deviceExtensions    = {});
+                           const std::vector<vk::QueueFlagBits>& queueFlags    = {},
+                           const std::vector<const char*>& instanceExtensions  = {},
+                           const std::vector<const char*>& deviceExtensions    = {});
 
         /**
          * Creates a basic vulkan graphics pipeline using @p config from the pipeline config class and returns it using the @p handle.
diff --git a/include/vkcv/DescriptorConfig.hpp b/include/vkcv/DescriptorConfig.hpp
index 776322e6270431f9fa52fd7c3cb4551e5b4bf752..767492eb2b27bd8dff56ef2aeb4769c08eed7200 100644
--- a/include/vkcv/DescriptorConfig.hpp
+++ b/include/vkcv/DescriptorConfig.hpp
@@ -23,7 +23,9 @@ namespace vkcv
         STORAGE_BUFFER,
         SAMPLER,
         IMAGE_SAMPLED,
-		IMAGE_STORAGE
+		IMAGE_STORAGE,
+        UNIFORM_BUFFER_DYNAMIC,
+        STORAGE_BUFFER_DYNAMIC
     };    
     
     /*
diff --git a/include/vkcv/DescriptorWrites.hpp b/include/vkcv/DescriptorWrites.hpp
index f28a6c91e189b13413ffefec0f05e5a0a358ee26..00e2d9a0494aec08767ced3a12086c812f6f1451 100644
--- a/include/vkcv/DescriptorWrites.hpp
+++ b/include/vkcv/DescriptorWrites.hpp
@@ -21,15 +21,19 @@ namespace vkcv {
 	};
 
 	struct UniformBufferDescriptorWrite {
-		inline UniformBufferDescriptorWrite(uint32_t binding, BufferHandle buffer) : binding(binding), buffer(buffer) {};
+		inline UniformBufferDescriptorWrite(uint32_t binding, BufferHandle buffer, bool dynamic = false) :
+		binding(binding), buffer(buffer), dynamic(dynamic) {};
 		uint32_t		binding;
 		BufferHandle	buffer;
+		bool 			dynamic;
 	};
 
 	struct StorageBufferDescriptorWrite {
-		inline StorageBufferDescriptorWrite(uint32_t binding, BufferHandle buffer) : binding(binding), buffer(buffer) {};
+		inline StorageBufferDescriptorWrite(uint32_t binding, BufferHandle buffer, bool dynamic = false) :
+		binding(binding), buffer(buffer), dynamic(dynamic) {};
 		uint32_t		binding;
 		BufferHandle	buffer;
+		bool			dynamic;
 	};
 
 	struct SamplerDescriptorWrite {
diff --git a/include/vkcv/DrawcallRecording.hpp b/include/vkcv/DrawcallRecording.hpp
index 572fc2b6b51735bdcd7eb77c1dd9d4a3482a1640..2dfefab328a7cae395118c620ec6e5825b1cf63e 100644
--- a/include/vkcv/DrawcallRecording.hpp
+++ b/include/vkcv/DrawcallRecording.hpp
@@ -14,11 +14,13 @@ namespace vkcv {
     };
 
     struct DescriptorSetUsage {
-        inline DescriptorSetUsage(uint32_t setLocation, vk::DescriptorSet vulkanHandle) noexcept
-            : setLocation(setLocation), vulkanHandle(vulkanHandle) {}
+        inline DescriptorSetUsage(uint32_t setLocation, vk::DescriptorSet vulkanHandle,
+								  const std::vector<uint32_t>& dynamicOffsets = {}) noexcept
+            : setLocation(setLocation), vulkanHandle(vulkanHandle), dynamicOffsets(dynamicOffsets) {}
 
-        const uint32_t          setLocation;
-        const vk::DescriptorSet vulkanHandle;
+        const uint32_t          	setLocation;
+        const vk::DescriptorSet 	vulkanHandle;
+        const std::vector<uint32_t> dynamicOffsets;
     };
 
     struct Mesh {
diff --git a/include/vkcv/QueueManager.hpp b/include/vkcv/QueueManager.hpp
index ac043b2d351014ea79fcae0d0fc439bb64a87b72..0919d20d8e07fee67ceb2f393c29b4a53c51b857 100644
--- a/include/vkcv/QueueManager.hpp
+++ b/include/vkcv/QueueManager.hpp
@@ -32,8 +32,8 @@ namespace vkcv {
         const std::vector<Queue> &getTransferQueues() const;
 
         static void queueCreateInfosQueueHandles(vk::PhysicalDevice &physicalDevice,
-                std::vector<float> &queuePriorities,
-                std::vector<vk::QueueFlagBits> &queueFlags,
+                const std::vector<float> &queuePriorities,
+                const std::vector<vk::QueueFlagBits> &queueFlags,
                 std::vector<vk::DeviceQueueCreateInfo> &queueCreateInfos,
                 std::vector<std::pair<int, int>> &queuePairsGraphics,
                 std::vector<std::pair<int, int>> &queuePairsCompute,
diff --git a/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp b/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp
index 0d9a39ccacb8451440150b7752a04d36eaddab39..274e1b9901b585554a56e2e6f503e904f6489ba4 100644
--- a/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp
+++ b/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp
@@ -29,6 +29,18 @@ namespace vkcv::upscaling {
 		SamplerHandle m_sampler;
 		
 		bool m_hdr;
+		
+		/**
+		 * Sharpness will calculate the rcasAttenuation value
+		 * which should be between 0.0f and 2.0f (default: 0.25f).
+		 *
+		 * rcasAttenuation = (1.0f - sharpness) * 2.0f
+		 *
+		 * So the default value for sharpness should be 0.875f.
+		 *
+		 * Beware that 0.0f or any negative value of sharpness will
+		 * disable the rcas pass completely.
+		 */
 		float m_sharpness;
 	
 	public:
diff --git a/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp b/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp
index 0f499500f12e2778d1841f324717f2b66c2a721e..d028beceabd08ac8b1ae2aea13919477016b5cd1 100644
--- a/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp
+++ b/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp
@@ -18,6 +18,47 @@
 
 namespace vkcv::upscaling {
 	
+	static std::vector<DescriptorBinding> getDescriptorBindings() {
+		return std::vector<DescriptorBinding>({
+			DescriptorBinding(
+					0, DescriptorType::UNIFORM_BUFFER_DYNAMIC,
+					1, ShaderStage::COMPUTE
+			),
+			DescriptorBinding(
+					1, DescriptorType::IMAGE_SAMPLED,
+					1, ShaderStage::COMPUTE
+			),
+			DescriptorBinding(
+					2, DescriptorType::IMAGE_STORAGE,
+					1, ShaderStage::COMPUTE
+			),
+			DescriptorBinding(
+					3, DescriptorType::SAMPLER,
+					1, ShaderStage::COMPUTE
+			)
+		});
+	}
+	
+	template<typename T>
+	bool checkFeatures(const vk::BaseInStructure* base, vk::StructureType type, bool (*check)(const T& features)) {
+		if (base->sType == type) {
+			return check(*reinterpret_cast<const T*>(base));
+		} else
+		if (base->pNext) {
+			return checkFeatures<T>(base->pNext, type, check);
+		} else {
+			return false;
+		}
+	}
+	
+	static bool checkFloat16(const vk::PhysicalDeviceFloat16Int8FeaturesKHR& features) {
+		return features.shaderFloat16;
+	}
+	
+	static bool check16Storage(const vk::PhysicalDevice16BitStorageFeaturesKHR& features) {
+		return features.storageBuffer16BitAccess;
+	}
+	
 	static bool writeShaderCode(const std::filesystem::path &shaderPath, const std::string& code) {
 		std::ofstream file (shaderPath.string(), std::ios::out);
 		
@@ -67,8 +108,8 @@ namespace vkcv::upscaling {
 	m_core(core),
 	m_easuPipeline(),
 	m_rcasPipeline(),
-	m_easuDescriptorSet(),
-	m_rcasDescriptorSet(),
+	m_easuDescriptorSet(m_core.createDescriptorSet(getDescriptorBindings())),
+	m_rcasDescriptorSet(m_core.createDescriptorSet(getDescriptorBindings())),
 	m_constants(m_core.createBuffer<FSRConstants>(
 			BufferType::UNIFORM,1,
 			BufferMemoryType::HOST_VISIBLE
@@ -81,13 +122,29 @@ namespace vkcv::upscaling {
 			SamplerAddressMode::CLAMP_TO_EDGE
 	)),
 	m_hdr(false),
-	m_sharpness(0.0f) {
+	m_sharpness(0/*.875f*/) {
 		vkcv::shader::GLSLCompiler easuCompiler, rcasCompiler;
 		
-		easuCompiler.setDefine("SAMPLE_SLOW_FALLBACK", "1");
-		easuCompiler.setDefine("SAMPLE_EASU", "1");
+		const auto& features = m_core.getContext().getPhysicalDevice().getFeatures2();
+		const bool float16Support = (
+				checkFeatures<vk::PhysicalDeviceFloat16Int8FeaturesKHR>(
+						reinterpret_cast<const vk::BaseInStructure*>(&features),
+						vk::StructureType::ePhysicalDeviceShaderFloat16Int8FeaturesKHR,
+						checkFloat16
+				) &&
+				checkFeatures<vk::PhysicalDevice16BitStorageFeaturesKHR>(
+						reinterpret_cast<const vk::BaseInStructure*>(&features),
+						vk::StructureType::ePhysicalDevice16BitStorageFeaturesKHR,
+						check16Storage
+				)
+		) || (true); // check doesn't work because chain is empty
 		
-		rcasCompiler.setDefine("SAMPLE_SLOW_FALLBACK", "1");
+		if (!float16Support) {
+			easuCompiler.setDefine("SAMPLE_SLOW_FALLBACK", "1");
+			rcasCompiler.setDefine("SAMPLE_SLOW_FALLBACK", "1");
+		}
+		
+		easuCompiler.setDefine("SAMPLE_EASU", "1");
 		rcasCompiler.setDefine("SAMPLE_RCAS", "1");
 		
 		{
@@ -97,13 +154,12 @@ namespace vkcv::upscaling {
 				program.addShader(shaderStage, path);
 			});
 			
-			m_easuDescriptorSet = m_core.createDescriptorSet(program.getReflectedDescriptors()[0]);
 			m_easuPipeline = m_core.createComputePipeline(program, {
 				m_core.getDescriptorSet(m_easuDescriptorSet).layout
 			});
 			
 			DescriptorWrites writes;
-			writes.uniformBufferWrites.emplace_back(0, m_constants.getHandle());
+			writes.uniformBufferWrites.emplace_back(0, m_constants.getHandle(), true);
 			writes.samplerWrites.emplace_back(3, m_sampler);
 			
 			m_core.writeDescriptorSet(m_easuDescriptorSet, writes);
@@ -116,13 +172,12 @@ namespace vkcv::upscaling {
 				program.addShader(shaderStage, path);
 			});
 			
-			m_rcasDescriptorSet = m_core.createDescriptorSet(program.getReflectedDescriptors()[0]);
 			m_rcasPipeline = m_core.createComputePipeline(program, {
 				m_core.getDescriptorSet(m_rcasDescriptorSet).layout
 			});
 			
 			DescriptorWrites writes;
-			writes.uniformBufferWrites.emplace_back(0, m_constants.getHandle());
+			writes.uniformBufferWrites.emplace_back(0, m_constants.getHandle(), true);
 			writes.samplerWrites.emplace_back(3, m_sampler);
 			
 			m_core.writeDescriptorSet(m_rcasDescriptorSet, writes);
@@ -162,6 +217,7 @@ namespace vkcv::upscaling {
 			);
 			
 			consts.Sample[0] = (((m_hdr) && (m_sharpness <= +0.0f)) ? 1 : 0);
+			
 			m_constants.fill(&consts);
 		}
 		
@@ -172,7 +228,7 @@ namespace vkcv::upscaling {
 		dispatch[1] = (outputHeight + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
 		dispatch[2] = 1;
 		
-		m_core.recordMemoryBarrier(cmdStream);
+		m_core.recordBufferMemoryBarrier(cmdStream, m_constants.getHandle());
 		
 		if (m_sharpness > +0.0f) {
 			{
@@ -182,6 +238,13 @@ namespace vkcv::upscaling {
 				
 				m_core.writeDescriptorSet(m_easuDescriptorSet, writes);
 			}
+			{
+				DescriptorWrites writes;
+				writes.sampledImageWrites.emplace_back(1, m_intermediateImage);
+				writes.storageImageWrites.emplace_back(2, output);
+				
+				m_core.writeDescriptorSet(m_rcasDescriptorSet, writes);
+			}
 			
 			m_core.recordComputeDispatchToCmdStream(
 					cmdStream,
@@ -189,36 +252,29 @@ namespace vkcv::upscaling {
 					dispatch,
 					{DescriptorSetUsage(0, m_core.getDescriptorSet(
 							m_easuDescriptorSet
-					).vulkanHandle)},
+					).vulkanHandle, { 0 })},
 					PushConstants(0)
 			);
 			
 			{
 				FSRConstants consts = {};
 				
-				FsrRcasCon(consts.Const0, 1.0f / m_sharpness);
+				FsrRcasCon(consts.Const0, (1.0f - m_sharpness) * 2.0f);
 				consts.Sample[0] = (m_hdr ? 1 : 0);
 				
 				m_constants.fill(&consts);
 			}
 			
+			m_core.recordBufferMemoryBarrier(cmdStream, m_constants.getHandle());
 			m_core.prepareImageForSampling(cmdStream, m_intermediateImage);
 			
-			{
-				DescriptorWrites writes;
-				writes.sampledImageWrites.emplace_back(1, m_intermediateImage);
-				writes.storageImageWrites.emplace_back(2, output);
-				
-				m_core.writeDescriptorSet(m_rcasDescriptorSet, writes);
-			}
-			
 			m_core.recordComputeDispatchToCmdStream(
 					cmdStream,
 					m_rcasPipeline,
 					dispatch,
 					{DescriptorSetUsage(0, m_core.getDescriptorSet(
 							m_rcasDescriptorSet
-					).vulkanHandle)},
+					).vulkanHandle, { 0 })},
 					PushConstants(0)
 			);
 			
@@ -238,12 +294,10 @@ namespace vkcv::upscaling {
 					dispatch,
 					{DescriptorSetUsage(0, m_core.getDescriptorSet(
 							m_easuDescriptorSet
-					).vulkanHandle)},
+					).vulkanHandle, { 0 })},
 					PushConstants(0)
 			);
 		}
-		
-		m_core.recordMemoryBarrier(cmdStream);
 	}
 	
 	bool FSRUpscaling::isHdrEnabled() const {
@@ -259,7 +313,7 @@ namespace vkcv::upscaling {
 	}
 	
 	void FSRUpscaling::setSharpness(float sharpness) {
-		m_sharpness = sharpness;
+		m_sharpness = (sharpness < 0.0f ? 0.0f : (sharpness > 1.0f ? 1.0f : sharpness));
 	}
 	
 }
diff --git a/projects/particle_simulation/src/BloomAndFlares.cpp b/projects/particle_simulation/src/BloomAndFlares.cpp
index 98d53c2a1a2c08d40473858b47aacf34da30f7ed..5961aae664a39dfb9bd597ffa7648c9b67999af4 100644
--- a/projects/particle_simulation/src/BloomAndFlares.cpp
+++ b/projects/particle_simulation/src/BloomAndFlares.cpp
@@ -263,6 +263,10 @@ void BloomAndFlares::execWholePipeline(const vkcv::CommandStreamHandle &cmdStrea
 
 void BloomAndFlares::updateImageDimensions(uint32_t width, uint32_t height)
 {
+    if ((width == m_Width) && (height == m_Height)) {
+        return;
+    }
+    
     m_Width  = width;
     m_Height = height;
 
diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp
index 8d85dd99965797e34182e0f0da6a7e3b52773ea1..f707bb44625ad89c8831507901b03262779a8965 100644
--- a/projects/voxelization/src/main.cpp
+++ b/projects/voxelization/src/main.cpp
@@ -28,11 +28,11 @@ int main(int argc, const char** argv) {
 		true
 	);
 
-	bool    isFullscreen            = false;
-	int     windowedWidthBackup     = windowWidth;
-	int     windowedHeightBackup    = windowHeight;
-	int     windowedPosXBackup;
-	int     windowedPosYBackup;
+	bool     isFullscreen            = false;
+	uint32_t windowedWidthBackup     = windowWidth;
+	uint32_t windowedHeightBackup    = windowHeight;
+	int      windowedPosXBackup;
+	int      windowedPosYBackup;
     glfwGetWindowPos(window.getWindow(), &windowedPosXBackup, &windowedPosYBackup);
 
 	window.e_key.add([&](int key, int scancode, int action, int mods) {
@@ -86,7 +86,7 @@ int main(int argc, const char** argv) {
 		VK_MAKE_VERSION(0, 0, 1),
 		{ vk::QueueFlagBits::eTransfer,vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute },
 		{},
-		{ "VK_KHR_swapchain" }
+		{ "VK_KHR_swapchain", "VK_KHR_shader_float16_int8", "VK_KHR_16bit_storage" }
 	);
 
 	vkcv::asset::Scene mesh;
@@ -528,6 +528,9 @@ int main(int argc, const char** argv) {
 
 	vkcv::upscaling::FSRUpscaling upscaling (core);
 	
+	float fsrFactor = 1.5f;
+	float rcasSharpness = upscaling.getSharpness();
+	
 	vkcv::gui::GUI gui(core, window);
 
 	glm::vec2   lightAnglesDegree               = glm::vec2(90.f, 0.f);
@@ -555,24 +558,33 @@ int main(int argc, const char** argv) {
 		if (!core.beginFrame(swapchainWidth, swapchainHeight)) {
 			continue;
 		}
+		
+		if (fsrFactor < 1.0f) {
+			fsrFactor = 1.0f;
+		} else
+		if (fsrFactor > 2.0f) {
+			fsrFactor = 2.0f;
+		}
+		
+		const auto fsrWidth = static_cast<uint32_t>(std::round(static_cast<float>(swapchainWidth) / fsrFactor));
+		const auto fsrHeight = static_cast<uint32_t>(std::round(static_cast<float>(swapchainHeight) / fsrFactor));
 
-		if ((swapchainWidth != windowWidth) || ((swapchainHeight != windowHeight))) {
-			depthBuffer         = core.createImage(depthBufferFormat, swapchainWidth, swapchainHeight, 1, false, false, false, msaa).getHandle();
-			colorBuffer         = core.createImage(colorBufferFormat, swapchainWidth, swapchainHeight, 1, false, colorBufferRequiresStorage, true, msaa).getHandle();
+		if ((fsrWidth != windowWidth) || ((fsrHeight != windowHeight))) {
+			depthBuffer         = core.createImage(depthBufferFormat, fsrWidth, fsrHeight, 1, false, false, false, msaa).getHandle();
+			colorBuffer         = core.createImage(colorBufferFormat, fsrWidth, fsrHeight, 1, false, colorBufferRequiresStorage, true, msaa).getHandle();
 
 			if (usingMsaa) {
-				resolvedColorBuffer = core.createImage(colorBufferFormat, swapchainWidth, swapchainHeight, 1, false, true, true).getHandle();
-			}
-			else {
+				resolvedColorBuffer = core.createImage(colorBufferFormat, fsrWidth, fsrHeight, 1, false, true, true).getHandle();
+			} else {
 				resolvedColorBuffer = colorBuffer;
 			}
 			
-			swapBuffer = core.createImage(colorBufferFormat, swapchainWidth, swapchainHeight, 1, false, true).getHandle();
-
+			swapBuffer = core.createImage(colorBufferFormat, fsrWidth, fsrHeight, 1, false, true).getHandle();
+			
 			windowWidth = swapchainWidth;
 			windowHeight = swapchainHeight;
-
-			bloomFlares.updateImageDimensions(windowWidth, windowHeight);
+			
+			bloomFlares.updateImageDimensions(swapchainWidth, swapchainHeight);
 		}
 
 		auto end = std::chrono::system_clock::now();
@@ -687,8 +699,8 @@ int main(int argc, const char** argv) {
 
 		const uint32_t fullscreenLocalGroupSize = 8;
 		const uint32_t fulsscreenDispatchCount[3] = {
-			static_cast<uint32_t>(glm::ceil(windowWidth  / static_cast<float>(fullscreenLocalGroupSize))),
-			static_cast<uint32_t>(glm::ceil(windowHeight / static_cast<float>(fullscreenLocalGroupSize))),
+			static_cast<uint32_t>(glm::ceil(fsrWidth  / static_cast<float>(fullscreenLocalGroupSize))),
+			static_cast<uint32_t>(glm::ceil(fsrHeight / static_cast<float>(fullscreenLocalGroupSize))),
 			1
 		};
 
@@ -713,7 +725,7 @@ int main(int argc, const char** argv) {
 			}
 		}
 
-		bloomFlares.execWholePipeline(cmdStream, resolvedColorBuffer, windowWidth, windowHeight, 
+		bloomFlares.execWholePipeline(cmdStream, resolvedColorBuffer, fsrWidth, fsrHeight,
 			glm::normalize(cameraManager.getActiveCamera().getFront())
 		);
 
@@ -738,7 +750,16 @@ int main(int argc, const char** argv) {
 		
 		core.prepareImageForStorage(cmdStream, swapchainInput);
 		core.prepareImageForSampling(cmdStream, swapBuffer);
+		
+		if (fsrFactor <= 1.0f) {
+			upscaling.setSharpness(0.0f);
+		}
+		
 		upscaling.recordUpscaling(cmdStream, swapBuffer, swapchainInput);
+		
+		if (fsrFactor <= 1.0f) {
+			upscaling.setSharpness(rcasSharpness);
+		}
 
 		// present and end
 		core.prepareSwapchainImageForPresent(cmdStream);
@@ -766,12 +787,16 @@ int main(int argc, const char** argv) {
 			ImGui::DragFloat("Voxelization extent", &voxelizationExtent, 1.f, 0.f);
 			voxelizationExtent = std::max(voxelizationExtent, 1.f);
 			voxelVisualisationMip = std::max(voxelVisualisationMip, 0);
-
+			
 			ImGui::ColorEdit3("Scattering color", &scatteringColor.x);
 			ImGui::DragFloat("Scattering density", &scatteringDensity, 0.0001);
 			ImGui::ColorEdit3("Absorption color", &absorptionColor.x);
 			ImGui::DragFloat("Absorption density", &absorptionDensity, 0.0001);
 			ImGui::DragFloat("Volumetric ambient", &volumetricAmbient, 0.002);
+			ImGui::DragFloat("FidelityFX FSR Factor", &fsrFactor, 0.01f, 1.0f, 2.0f);
+			ImGui::DragFloat("RCAS Sharpness", &rcasSharpness, 0.01f, 0.0f, 1.0f);
+			
+			upscaling.setSharpness(rcasSharpness);
 
 			if (ImGui::Button("Reload forward pass")) {
 
diff --git a/src/vkcv/Context.cpp b/src/vkcv/Context.cpp
index 5db50869498600fa8e926c0feff2cb5fda1eb22e..fb863f9d223fc091da924e27ebee4981a2afa110 100644
--- a/src/vkcv/Context.cpp
+++ b/src/vkcv/Context.cpp
@@ -151,7 +151,7 @@ namespace vkcv
 	 * @param check The elements to be checked
 	 * @return True, if all elements in "check" are supported
 	*/
-	bool checkSupport(std::vector<const char*>& supported, std::vector<const char*>& check)
+	bool checkSupport(const std::vector<const char*>& supported, const std::vector<const char*>& check)
 	{
 		for (auto checkElem : check) {
 			bool found = false;
@@ -182,9 +182,9 @@ namespace vkcv
 	
 	Context Context::create(const char *applicationName,
 							uint32_t applicationVersion,
-							std::vector<vk::QueueFlagBits> queueFlags,
-							std::vector<const char *> instanceExtensions,
-							std::vector<const char *> deviceExtensions) {
+							const std::vector<vk::QueueFlagBits>& queueFlags,
+							const std::vector<const char *>& instanceExtensions,
+							const std::vector<const char *>& deviceExtensions) {
 		// check for layer support
 		
 		const std::vector<vk::LayerProperties>& layerProperties = vk::enumerateInstanceLayerProperties();
@@ -223,7 +223,7 @@ namespace vkcv
 		
 		// for GLFW: get all required extensions
 		std::vector<const char*> requiredExtensions = getRequiredExtensions();
-		instanceExtensions.insert(instanceExtensions.end(), requiredExtensions.begin(), requiredExtensions.end());
+		requiredExtensions.insert(requiredExtensions.end(), instanceExtensions.begin(), instanceExtensions.end());
 		
 		const vk::ApplicationInfo applicationInfo(
 				applicationName,
@@ -238,8 +238,8 @@ namespace vkcv
 				&applicationInfo,
 				0,
 				nullptr,
-				static_cast<uint32_t>(instanceExtensions.size()),
-				instanceExtensions.data()
+				static_cast<uint32_t>(requiredExtensions.size()),
+				requiredExtensions.data()
 		);
 
 #ifndef NDEBUG
@@ -286,13 +286,31 @@ namespace vkcv
 		deviceCreateInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
 		deviceCreateInfo.ppEnabledLayerNames = validationLayers.data();
 #endif
-
+		const bool shaderFloat16 = checkSupport(deviceExtensions, { "VK_KHR_shader_float16_int8" });
+		const bool storage16bit  = checkSupport(deviceExtensions, { "VK_KHR_16bit_storage" });
+		
 		// FIXME: check if device feature is supported
-		vk::PhysicalDeviceFeatures deviceFeatures;
-		deviceFeatures.fragmentStoresAndAtomics = true;
-		deviceFeatures.geometryShader = true;
-		deviceFeatures.depthClamp = true;
-		deviceCreateInfo.pEnabledFeatures = &deviceFeatures;
+		vk::PhysicalDeviceShaderFloat16Int8Features deviceShaderFloat16Int8Features;
+		deviceShaderFloat16Int8Features.shaderFloat16 = shaderFloat16;
+		
+		vk::PhysicalDevice16BitStorageFeatures device16BitStorageFeatures;
+		device16BitStorageFeatures.storageBuffer16BitAccess = storage16bit;
+		
+		vk::PhysicalDeviceFeatures2 deviceFeatures2;
+		deviceFeatures2.features.fragmentStoresAndAtomics = true;
+		deviceFeatures2.features.geometryShader = true;
+		deviceFeatures2.features.depthClamp = true;
+		deviceFeatures2.features.shaderInt16 = true;
+		
+		if (shaderFloat16) {
+			deviceFeatures2.setPNext(&deviceShaderFloat16Int8Features);
+		}
+		
+		if (storage16bit) {
+			deviceShaderFloat16Int8Features.setPNext(&device16BitStorageFeatures);
+		}
+		
+		deviceCreateInfo.setPNext(&deviceFeatures2);
 
 		// Ablauf
 		// qCreateInfos erstellen --> braucht das Device
diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp
index c9da14fbd6ba54b5682e68c4508776da00b1ae6d..a50303bbe64f559ca62dd3d5672d4b6ecadf97e5 100644
--- a/src/vkcv/Core.cpp
+++ b/src/vkcv/Core.cpp
@@ -53,9 +53,9 @@ namespace vkcv
     Core Core::create(Window &window,
                       const char *applicationName,
                       uint32_t applicationVersion,
-                      std::vector<vk::QueueFlagBits> queueFlags,
-                      std::vector<const char *> instanceExtensions,
-                      std::vector<const char *> deviceExtensions)
+                      const std::vector<vk::QueueFlagBits>& queueFlags,
+                      const std::vector<const char *>& instanceExtensions,
+                      const std::vector<const char *>& deviceExtensions)
     {
         Context context = Context::create(
         		applicationName, applicationVersion,
@@ -90,8 +90,8 @@ namespace vkcv
     Core::Core(Context &&context, Window &window, const Swapchain& swapChain,  std::vector<vk::ImageView> swapchainImageViews,
         const CommandResources& commandResources, const SyncResources& syncResources) noexcept :
             m_Context(std::move(context)),
+			m_swapchain(swapChain),
             m_window(window),
-            m_swapchain(swapChain),
             m_PassManager{std::make_unique<PassManager>(m_Context.m_Device)},
             m_PipelineManager{std::make_unique<PipelineManager>(m_Context.m_Device)},
             m_DescriptorManager(std::make_unique<DescriptorManager>(m_Context.m_Device)),
@@ -118,7 +118,8 @@ namespace vkcv
 			swapchainImageViews, 
 			swapChain.getExtent().width,
 			swapChain.getExtent().height,
-			swapChain.getFormat());
+			swapChain.getFormat()
+		);
 	}
 
 	Core::~Core() noexcept {
@@ -373,7 +374,8 @@ namespace vkcv
 					pipelineLayout,
 					usage.setLocation,
 					{ usage.vulkanHandle },
-					{});
+					usage.dynamicOffsets
+				);
 			}
 			if (pushConstants.getSizePerDrawcall() > 0) {
 				cmdBuffer.pushConstants(
diff --git a/src/vkcv/DescriptorManager.cpp b/src/vkcv/DescriptorManager.cpp
index 07ca97b5ade9b69eed724000d9c7b388818d6725..226cf50817fc347a5c8db5f250b1e0af9a2e4fde 100644
--- a/src/vkcv/DescriptorManager.cpp
+++ b/src/vkcv/DescriptorManager.cpp
@@ -105,7 +105,6 @@ namespace vkcv
 		const ImageManager		&imageManager, 
 		const BufferManager		&bufferManager,
 		const SamplerManager	&samplerManager) {
-
 		vk::DescriptorSet set = m_DescriptorSets[handle.getId()].vulkanHandle;
 
 		std::vector<vk::DescriptorImageInfo> imageInfos;
@@ -165,6 +164,8 @@ namespace vkcv
 					0,
 					bufferInfos.size(),
 					write.binding,
+					write.dynamic?
+					vk::DescriptorType::eUniformBufferDynamic :
 					vk::DescriptorType::eUniformBuffer
 			};
 			
@@ -184,6 +185,8 @@ namespace vkcv
 					0,
 					bufferInfos.size(),
 					write.binding,
+					write.dynamic?
+					vk::DescriptorType::eStorageBufferDynamic :
 					vk::DescriptorType::eStorageBuffer
 			};
 			
@@ -239,8 +242,12 @@ namespace vkcv
         {
             case DescriptorType::UNIFORM_BUFFER:
                 return vk::DescriptorType::eUniformBuffer;
+			case DescriptorType::UNIFORM_BUFFER_DYNAMIC:
+				return vk::DescriptorType::eUniformBufferDynamic;
             case DescriptorType::STORAGE_BUFFER:
                 return vk::DescriptorType::eStorageBuffer;
+			case DescriptorType::STORAGE_BUFFER_DYNAMIC:
+				return vk::DescriptorType::eStorageBufferDynamic;
             case DescriptorType::SAMPLER:
                 return vk::DescriptorType::eSampler;
             case DescriptorType::IMAGE_SAMPLED:
diff --git a/src/vkcv/QueueManager.cpp b/src/vkcv/QueueManager.cpp
index b4891c6be387b817b87f059f4155f5708d4f4710..15e958b0de929e53170324ade27a9b3663a15d6a 100644
--- a/src/vkcv/QueueManager.cpp
+++ b/src/vkcv/QueueManager.cpp
@@ -27,8 +27,8 @@ namespace vkcv {
      * @throws std::runtime_error If the requested queues from @p queueFlags are not creatable due to insufficient availability.
      */
     void QueueManager::queueCreateInfosQueueHandles(vk::PhysicalDevice &physicalDevice,
-                                      std::vector<float> &queuePriorities,
-                                      std::vector<vk::QueueFlagBits> &queueFlags,
+                                      const std::vector<float> &queuePriorities,
+                                      const std::vector<vk::QueueFlagBits> &queueFlags,
                                       std::vector<vk::DeviceQueueCreateInfo> &queueCreateInfos,
                                       std::vector<std::pair<int, int>> &queuePairsGraphics,
                                       std::vector<std::pair<int, int>> &queuePairsCompute,