Răsfoiți Sursa

Make non-DLSS path work

Panagiotis Christopoulos Charitos 3 ani în urmă
părinte
comite
9e02ca9e22

+ 1 - 1
AnKi/Config.h.cmake

@@ -23,7 +23,7 @@
 #define ANKI_TESTS ${ANKI_TESTS}
 #define ANKI_ENABLE_TRACE ${_ANKI_ENABLE_TRACE}
 #define ANKI_SOURCE_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
-#define ANKI_DLSS ${_ANKI_DLSS_SUPPORTED}
+#define ANKI_DLSS ${_ANKI_DLSS_ENABLED}
 
 // Compiler
 #if defined(__clang__)

+ 28 - 3
AnKi/Gr/CMakeLists.txt

@@ -131,8 +131,33 @@ add_library(AnKiGrCommon ${common_sources} ${common_headers})
 target_compile_definitions(AnKiGrCommon PRIVATE -DANKI_SOURCE_FILE)
 target_link_libraries(AnKiGrCommon AnKiUtil) # Only depend on Util
 
+if(ANKI_DLSS)
+	set(extra_libs AnKiNgx)
+endif()
+
 add_library(AnKiGr ${backend_sources} ${backend_headers})
 target_compile_definitions(AnKiGr PRIVATE -DANKI_SOURCE_FILE)
-target_link_libraries(AnKiGr AnKiCore AnKiSpirvCross AnKiGrCommon)
-# Add dynamic dependencies for AnkiNgx
-add_AnkiNgx_dependencies(AnKiGr)
+target_link_libraries(AnKiGr AnKiCore AnKiSpirvCross AnKiGrCommon ${extra_libs})
+
+# Copy DLSS files to Bin
+if(ANKI_DLSS)
+	get_target_property(lib_type AnkiNgx TYPE)
+	if("${lib_type}" STREQUAL "SHARED_LIBRARY")
+		get_target_property(ANKINGX_DLL AnkiNgx IMPORTED_LOCATION)
+		add_custom_command(
+			TARGET AnKiGr
+			COMMENT "Dependant DLLs copy ${ANKINGX_DLL} ${CMAKE_BINARY_DIR}/Bin"
+			COMMAND ${CMAKE_COMMAND} -E copy_if_different "${ANKINGX_DLL}" "${CMAKE_BINARY_DIR}/Bin")
+	else()
+		get_property(__NGX_DLLS_LIST TARGET AnkiNgx PROPERTY ANKINGX_EXTRA_DLLS)
+		foreach(dll_path ${__NGX_DLLS_LIST})
+			file(GLOB dll_files "${dll_path}")
+			foreach(dll_file ${dll_files})
+				add_custom_command(
+				TARGET AnKiGr
+				COMMENT "NGX DLL copy ${dll_file} ${CMAKE_BINARY_DIR}/Bin\n"
+				COMMAND ${CMAKE_COMMAND} -E copy_if_different "${dll_file}" "${CMAKE_BINARY_DIR}/Bin")
+			endforeach()
+		endforeach()
+	endif()
+endif()

+ 3 - 3
AnKi/Gr/CommandBuffer.h

@@ -417,11 +417,11 @@ public:
 	/// @param[out] outUpscaledColor Destination HighRes RenderTarget
 	/// @param[in] motionVectors Motion Vectors
 	/// @param[in] depth Depth attachment
-	/// @param[in] exposure 1x1 texture containing exposure
-	/// @param[in] resetAccumulation whether to clean or not any temporal history
+	/// @param[in] exposure 1x1 Texture containing exposure
+	/// @param[in] resetAccumulation Whether to clean or not any temporal history
 	/// @param[in] jitterOffset Jittering offset that was applied during the generation of sourceTexture
 	/// @param[in] motionVectorsScale Any scale factor that might need to be applied to the motionVectorsTexture (i.e UV
-	/// space to Pixel space conversion)
+	///                               space to Pixel space conversion)
 	void upscale(const GrUpscalerPtr& upscaler, const TextureViewPtr& inColor, const TextureViewPtr& outUpscaledColor,
 				 const TextureViewPtr& motionVectors, const TextureViewPtr& depth, const TextureViewPtr& exposure,
 				 const Bool resetAccumulation, const Vec2& jitterOffset, const Vec2& motionVectorsScale);

+ 0 - 3
AnKi/Gr/Common.h

@@ -188,9 +188,6 @@ public:
 	Bool m_dlss = false;
 };
 ANKI_END_PACKED_STRUCT
-static_assert(sizeof(GpuDeviceCapabilities)
-				  == sizeof(PtrSize) * 5 + sizeof(U32) * 8 + sizeof(U8) * 3 + sizeof(Bool) * 7,
-			  "Should be packed");
 
 /// The type of the allocator for heap allocations
 template<typename T>

+ 3 - 1
AnKi/Gr/Enums.h

@@ -240,7 +240,9 @@ enum class TextureUsageBit : U32
 	ALL_READ = ALL_SAMPLED | IMAGE_GEOMETRY_READ | IMAGE_FRAGMENT_READ | IMAGE_COMPUTE_READ | IMAGE_TRACE_RAYS_READ
 			   | FRAMEBUFFER_ATTACHMENT_READ | FRAMEBUFFER_SHADING_RATE | PRESENT | GENERATE_MIPMAPS,
 	ALL_WRITE = IMAGE_GEOMETRY_WRITE | IMAGE_FRAGMENT_WRITE | IMAGE_COMPUTE_WRITE | IMAGE_TRACE_RAYS_WRITE
-				| FRAMEBUFFER_ATTACHMENT_WRITE | TRANSFER_DESTINATION | GENERATE_MIPMAPS
+				| FRAMEBUFFER_ATTACHMENT_WRITE | TRANSFER_DESTINATION | GENERATE_MIPMAPS,
+
+	GR_UPSCALING = ALL_IMAGE
 };
 ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(TextureUsageBit)
 

+ 11 - 24
AnKi/Gr/GrUpscaler.h

@@ -15,19 +15,19 @@ namespace anki {
 /// @{
 
 /// Different upscalers supported internally by GrUpscaler
-enum class GrUpscalerType : I8
+enum class GrUpscalerType : U8
 {
-	INVALID = -1,
-	DLSS_2 = 0
+	DLSS_2 = 0,
+	COUNT
 };
 
 /// Quality preset to be used by the upscaler if available
 enum class GrUpscalerQualityMode : U8
 {
-	DISABLED = 0,
 	PERFORMANCE,
 	BALANCED,
 	QUALITY,
+
 	COUNT
 };
 ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(GrUpscalerQualityMode)
@@ -36,23 +36,10 @@ ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(GrUpscalerQualityMode)
 class GrUpscalerInitInfo : public GrBaseInitInfo
 {
 public:
-	UVec2 m_sourceImageResolution = UVec2(0, 0);
-	UVec2 m_targetImageResolution = UVec2(0, 0);
-	GrUpscalerType m_upscalerType = GrUpscalerType::INVALID;
+	UVec2 m_sourceTextureResolution = UVec2(0u);
+	UVec2 m_targetTextureResolution = UVec2(0u);
+	GrUpscalerType m_upscalerType = GrUpscalerType::COUNT;
 	GrUpscalerQualityMode m_qualityMode = GrUpscalerQualityMode::PERFORMANCE;
-
-	GrUpscalerInitInfo()
-		: GrBaseInitInfo()
-	{
-	}
-
-	GrUpscalerInitInfo(const UVec2& srcRes, const UVec2& dstRes, const GrUpscalerType type, const GrUpscalerQualityMode qualityMode)
-		: m_sourceImageResolution(srcRes)
-		, m_targetImageResolution(dstRes)
-		, m_upscalerType(type)
-		, m_qualityMode(qualityMode)
-	{
-	}
 };
 
 class GrUpscaler : public GrObject
@@ -64,10 +51,13 @@ public:
 
 	GrUpscalerType getUpscalerType() const
 	{
+		ANKI_ASSERT(m_upscalerType != GrUpscalerType::COUNT);
 		return m_upscalerType;
 	}
 
 protected:
+	GrUpscalerType m_upscalerType = GrUpscalerType::COUNT;
+
 	/// Construct.
 	GrUpscaler(GrManager* manager, CString name)
 		: GrObject(manager, CLASS_TYPE, name)
@@ -79,12 +69,9 @@ protected:
 	{
 	}
 
-	GrUpscalerType m_upscalerType;
-
 private:
-
 	/// Allocate and initialize a new instance.
-	static GrUpscaler* newInstance(GrManager* manager, const GrUpscalerInitInfo& initInfo);
+	[[nodiscard]] static GrUpscaler* newInstance(GrManager* manager, const GrUpscalerInitInfo& initInfo);
 };
 /// @}
 

+ 9 - 3
AnKi/Gr/RenderGraph.h

@@ -127,6 +127,15 @@ public:
 	void getRenderTargetState(RenderTargetHandle handle, const TextureSubresourceInfo& subresource,
 							  TexturePtr& tex) const;
 
+	/// Create a whole texture view from a handle
+	TextureViewPtr createTextureView(RenderTargetHandle handle)
+	{
+		TexturePtr tex = getTexture(handle);
+		TextureViewInitInfo viewInit(tex, "TmpRenderGraph"); // Use the whole texture
+		getRenderTargetState(handle, viewInit, tex);
+		return m_commandBuffer->getManager().newTextureView(viewInit);
+	}
+
 	/// Convenience method.
 	void bindTextureAndSampler(U32 set, U32 binding, RenderTargetHandle handle,
 							   const TextureSubresourceInfo& subresource, const SamplerPtr& sampler)
@@ -214,9 +223,6 @@ public:
 	/// Convenience method.
 	void bindAccelerationStructure(U32 set, U32 binding, AccelerationStructureHandle handle);
 
-	/// Convenience method. Use it carefully (i.e access the resource for an external plugin)
-	const TexturePtr getTargetTexture(RenderTargetHandle handle) const;
-
 private:
 	const RenderGraph* m_rgraph ANKI_DEBUG_CODE(= nullptr);
 	U32 m_passIdx ANKI_DEBUG_CODE(= MAX_U32);

+ 0 - 5
AnKi/Gr/RenderGraph.inl.h

@@ -26,11 +26,6 @@ inline void RenderPassWorkContext::getRenderTargetState(RenderTargetHandle handl
 	tex = m_rgraph->getTexture(handle);
 }
 
-inline const TexturePtr RenderPassWorkContext::getTargetTexture(RenderTargetHandle handle) const
-{
-	return getTexture(handle);
-}
-
 inline TexturePtr RenderPassWorkContext::getTexture(RenderTargetHandle handle) const
 {
 	return m_rgraph->getTexture(handle);

+ 82 - 71
AnKi/Gr/Vulkan/CommandBufferImpl.cpp

@@ -3,21 +3,19 @@
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 
-#include <AnKi/Gr/GrManager.h>
 #include <AnKi/Gr/Vulkan/CommandBufferImpl.h>
+#include <AnKi/Gr/GrManager.h>
 #include <AnKi/Gr/Vulkan/GrManagerImpl.h>
-
 #include <AnKi/Gr/Framebuffer.h>
 #include <AnKi/Gr/Vulkan/GrUpscalerImpl.h>
 #include <AnKi/Gr/Vulkan/AccelerationStructureImpl.h>
 #include <AnKi/Gr/Vulkan/FramebufferImpl.h>
 
 #if ANKI_DLSS
-// Ngx specific
-#	include <ThirdParty/nvngx_dlss_sdk/sdk/include/nvsdk_ngx.h>
-#	include <ThirdParty/nvngx_dlss_sdk/sdk/include/nvsdk_ngx_helpers.h>
-#	include <ThirdParty/nvngx_dlss_sdk/sdk/include/nvsdk_ngx_vk.h>
-#	include <ThirdParty/nvngx_dlss_sdk/sdk/include/nvsdk_ngx_helpers_vk.h>
+#	include <ThirdParty/DlssSdk/sdk/include/nvsdk_ngx.h>
+#	include <ThirdParty/DlssSdk/sdk/include/nvsdk_ngx_helpers.h>
+#	include <ThirdParty/DlssSdk/sdk/include/nvsdk_ngx_vk.h>
+#	include <ThirdParty/DlssSdk/sdk/include/nvsdk_ngx_helpers_vk.h>
 #endif
 
 #include <algorithm>
@@ -798,18 +796,20 @@ void CommandBufferImpl::buildAccelerationStructureInternal(const AccelerationStr
 #if ANKI_DLSS
 /// Utility function to get the NGX's resource structure for a texture
 /// @param[in] tex the texture to generate the NVSDK_NGX_Resource_VK from
-/// @param[in] isUAV whether IMAGE READ/WRITE access is allowed for this image
-static NVSDK_NGX_Resource_VK getNGXResourceFromAnkiTexture(const TextureViewImpl& tex, const Bool isUAV)
+static NVSDK_NGX_Resource_VK getNGXResourceFromAnkiTexture(const TextureViewImpl& view)
 {
+	const TextureImpl& tex = view.getTextureImpl();
+
 	NVSDK_NGX_Resource_VK resourceVK = {};
-	const VkImageView imageView = tex.getHandle();
-	const VkFormat format = tex.getTextureImpl().m_vkFormat;
-	const VkImage image = tex.getTextureImpl().m_imageHandle;
-	const VkImageSubresourceRange subresourceRange = tex.getVkImageSubresourceRange();
-
-	return NVSDK_NGX_Create_ImageView_Resource_VK(imageView, image, subresourceRange, format,
-												  tex.getTextureImpl().getWidth(), tex.getTextureImpl().getHeight(),
-												  isUAV);
+	const VkImageView imageView = view.getHandle();
+	const VkFormat format = tex.m_vkFormat;
+	const VkImage image = tex.m_imageHandle;
+	const VkImageSubresourceRange subresourceRange = view.getVkImageSubresourceRange();
+	const Bool isUAV = !!(tex.m_vkUsageFlags & VK_IMAGE_USAGE_STORAGE_BIT);
+
+	// TODO Not sure if I should pass the width,height of the image or the view
+	return NVSDK_NGX_Create_ImageView_Resource_VK(imageView, image, subresourceRange, format, tex.getWidth(),
+												  tex.getHeight(), isUAV);
 }
 #endif
 
@@ -819,63 +819,74 @@ void CommandBufferImpl::upscaleInternal(const GrUpscalerPtr& upscaler, const Tex
 										const Bool resetAccumulation, const Vec2& jitterOffset,
 										const Vec2& motionVectorsScale)
 {
+#if ANKI_DLSS
+	ANKI_ASSERT(getGrManagerImpl().getDeviceCapabilities().m_dlss);
+	ANKI_ASSERT(upscaler->getUpscalerType() == GrUpscalerType::DLSS_2);
+
 	commandCommon();
 	flushBatches(CommandBufferCommandType::ANY_OTHER_COMMAND);
 
-#if ANKI_DLSS
-	if(upscaler->getUpscalerType() == GrUpscalerType::DLSS_2)
-	{
-		const GrUpscalerImpl& upscalerImpl = static_cast<const GrUpscalerImpl&>(*upscaler);
-
-		const TextureViewImpl& srcViewImpl = static_cast<const TextureViewImpl&>(*inColor);
-		const TextureViewImpl& dstViewImpl = static_cast<const TextureViewImpl&>(*outUpscaledColor);
-		const TextureViewImpl& mvViewImpl = static_cast<const TextureViewImpl&>(*motionVectors);
-		const TextureViewImpl& depthViewImpl = static_cast<const TextureViewImpl&>(*depth);
-		const TextureViewImpl& exposureViewImpl = static_cast<const TextureViewImpl&>(*exposure);
-
-		NVSDK_NGX_Resource_VK srcResVk = getNGXResourceFromAnkiTexture(srcViewImpl, false);
-		NVSDK_NGX_Resource_VK dstResVk = getNGXResourceFromAnkiTexture(dstViewImpl, true);
-		NVSDK_NGX_Resource_VK mvResVk = getNGXResourceFromAnkiTexture(mvViewImpl, false);
-		NVSDK_NGX_Resource_VK depthResVk = getNGXResourceFromAnkiTexture(depthViewImpl, false);
-		NVSDK_NGX_Resource_VK exposureResVk = getNGXResourceFromAnkiTexture(exposureViewImpl, false);
-
-		const U32 mipLevel = srcViewImpl.getSubresource().m_firstMipmap;
-		const NVSDK_NGX_Coordinates renderingOffset = {0, 0};
-		const NVSDK_NGX_Dimensions renderingSize = {srcViewImpl.getTextureImpl().getWidth() >> mipLevel,
-													srcViewImpl.getTextureImpl().getHeight() >> mipLevel};
-
-		NVSDK_NGX_VK_DLSS_Eval_Params vkDlssEvalParams;
-		memset(&vkDlssEvalParams, 0, sizeof(vkDlssEvalParams));
-		vkDlssEvalParams.Feature.pInColor = &srcResVk;
-		vkDlssEvalParams.Feature.pInOutput = &dstResVk;
-		vkDlssEvalParams.pInDepth = &depthResVk;
-		vkDlssEvalParams.pInMotionVectors = &mvResVk;
-		vkDlssEvalParams.pInExposureTexture = &exposureResVk;
-		vkDlssEvalParams.InJitterOffsetX = jitterOffset.x();
-		vkDlssEvalParams.InJitterOffsetY = jitterOffset.y();
-		vkDlssEvalParams.Feature.InSharpness = upscalerImpl.getRecommendedSettings().m_recommendedSharpness;
-		vkDlssEvalParams.InReset = resetAccumulation;
-		vkDlssEvalParams.InMVScaleX = motionVectorsScale.x();
-		vkDlssEvalParams.InMVScaleY = motionVectorsScale.y();
-		vkDlssEvalParams.InColorSubrectBase = renderingOffset;
-		vkDlssEvalParams.InDepthSubrectBase = renderingOffset;
-		vkDlssEvalParams.InTranslucencySubrectBase = renderingOffset;
-		vkDlssEvalParams.InMVSubrectBase = renderingOffset;
-		vkDlssEvalParams.InRenderSubrectDimensions = renderingSize;
-
-		getGrManagerImpl().beginMarker(m_handle, "DLSS");
-		NVSDK_NGX_Parameter* dlssParameters(&upscalerImpl.getParameters());
-		NVSDK_NGX_Handle* dlssFeature(&upscalerImpl.getFeature());
-		const NVSDK_NGX_Result result =
-			NGX_VULKAN_EVALUATE_DLSS_EXT(m_handle, dlssFeature, dlssParameters, &vkDlssEvalParams);
-		getGrManagerImpl().endMarker(m_handle);
-
-		if(NVSDK_NGX_FAILED(result))
-		{
-			ANKI_VK_LOGF("Failed to NVSDK_NGX_VULKAN_EvaluateFeature for DLSS, code = 0x%08x, info: %ls", result,
-					  GetNGXResultAsString(result));
-		}
-	}
+	const GrUpscalerImpl& upscalerImpl = static_cast<const GrUpscalerImpl&>(*upscaler);
+
+	const TextureViewImpl& srcViewImpl = static_cast<const TextureViewImpl&>(*inColor);
+	const TextureViewImpl& dstViewImpl = static_cast<const TextureViewImpl&>(*outUpscaledColor);
+	const TextureViewImpl& mvViewImpl = static_cast<const TextureViewImpl&>(*motionVectors);
+	const TextureViewImpl& depthViewImpl = static_cast<const TextureViewImpl&>(*depth);
+	const TextureViewImpl& exposureViewImpl = static_cast<const TextureViewImpl&>(*exposure);
+
+	NVSDK_NGX_Resource_VK srcResVk = getNGXResourceFromAnkiTexture(srcViewImpl);
+	NVSDK_NGX_Resource_VK dstResVk = getNGXResourceFromAnkiTexture(dstViewImpl);
+	NVSDK_NGX_Resource_VK mvResVk = getNGXResourceFromAnkiTexture(mvViewImpl);
+	NVSDK_NGX_Resource_VK depthResVk = getNGXResourceFromAnkiTexture(depthViewImpl);
+	NVSDK_NGX_Resource_VK exposureResVk = getNGXResourceFromAnkiTexture(exposureViewImpl);
+
+	const U32 mipLevel = srcViewImpl.getSubresource().m_firstMipmap;
+	const NVSDK_NGX_Coordinates renderingOffset = {0, 0};
+	const NVSDK_NGX_Dimensions renderingSize = {srcViewImpl.getTextureImpl().getWidth() >> mipLevel,
+												srcViewImpl.getTextureImpl().getHeight() >> mipLevel};
+
+	NVSDK_NGX_VK_DLSS_Eval_Params vkDlssEvalParams;
+	memset(&vkDlssEvalParams, 0, sizeof(vkDlssEvalParams));
+	vkDlssEvalParams.Feature.pInColor = &srcResVk;
+	vkDlssEvalParams.Feature.pInOutput = &dstResVk;
+	vkDlssEvalParams.pInDepth = &depthResVk;
+	vkDlssEvalParams.pInMotionVectors = &mvResVk;
+	vkDlssEvalParams.pInExposureTexture = &exposureResVk;
+	vkDlssEvalParams.InJitterOffsetX = jitterOffset.x();
+	vkDlssEvalParams.InJitterOffsetY = jitterOffset.y();
+	vkDlssEvalParams.Feature.InSharpness = upscalerImpl.getRecommendedSettings().m_sharpness;
+	vkDlssEvalParams.InReset = resetAccumulation;
+	vkDlssEvalParams.InMVScaleX = motionVectorsScale.x();
+	vkDlssEvalParams.InMVScaleY = motionVectorsScale.y();
+	vkDlssEvalParams.InColorSubrectBase = renderingOffset;
+	vkDlssEvalParams.InDepthSubrectBase = renderingOffset;
+	vkDlssEvalParams.InTranslucencySubrectBase = renderingOffset;
+	vkDlssEvalParams.InMVSubrectBase = renderingOffset;
+	vkDlssEvalParams.InRenderSubrectDimensions = renderingSize;
+
+	getGrManagerImpl().beginMarker(m_handle, "DLSS");
+	NVSDK_NGX_Parameter* dlssParameters = &upscalerImpl.getParameters();
+	NVSDK_NGX_Handle* dlssFeature = &upscalerImpl.getFeature();
+	const NVSDK_NGX_Result result =
+		NGX_VULKAN_EVALUATE_DLSS_EXT(m_handle, dlssFeature, dlssParameters, &vkDlssEvalParams);
+	getGrManagerImpl().endMarker(m_handle);
+
+	if(NVSDK_NGX_FAILED(result))
+	{
+		ANKI_VK_LOGF("Failed to NVSDK_NGX_VULKAN_EvaluateFeature for DLSS, code = 0x%08x, info: %ls", result,
+					 GetNGXResultAsString(result));
+	}
+#else
+	ANKI_ASSERT(0 && "Not supported");
+	(void)upscaler;
+	(void)inColor;
+	(void)outUpscaledColor;
+	(void)motionVectors;
+	(void)depth;
+	(void)exposure;
+	(void)resetAccumulation;
+	(void)jitterOffset;
+	(void)motionVectorsScale;
 #endif
 }
 

+ 4 - 11
AnKi/Gr/Vulkan/GrManagerImpl.cpp

@@ -548,12 +548,7 @@ Error GrManagerImpl::initInstance()
 #endif
 
 	// DLSS checks
-#if ANKI_DLSS
-	if(m_capabilities.m_gpuVendor == GpuVendor::NVIDIA)
-	{
-		m_capabilities.m_dlss = true;
-	}
-#endif
+	m_capabilities.m_dlss = ANKI_DLSS && m_capabilities.m_gpuVendor == GpuVendor::NVIDIA;
 
 	return Error::NONE;
 }
@@ -766,23 +761,21 @@ Error GrManagerImpl::initDevice(const GrManagerInitInfo& init)
 				m_extensions |= VulkanExtensions::EXT_TEXTURE_COMPRESSION_ASTC_HDR;
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
 			}
-			else if(extensionName == VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME)
+			else if(m_capabilities.m_dlss && extensionName == VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME)
 			{
 				m_extensions |= VulkanExtensions::KHR_PUSH_DESCRIPTOR;
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
 			}
-#if ANKI_DLSS
-			else if(extensionName == ANKI_VK_NVX_BINARY_IMPORT)
+			else if(m_capabilities.m_dlss && extensionName == ANKI_VK_NVX_BINARY_IMPORT)
 			{
 				m_extensions |= VulkanExtensions::NVX_BINARY_IMPORT;
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
 			}
-			else if(extensionName == VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME)
+			else if(m_capabilities.m_dlss && extensionName == VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME)
 			{
 				m_extensions |= VulkanExtensions::NVX_IMAGE_VIEW_HANDLE;
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
 			}
-#endif
 		}
 
 		ANKI_VK_LOGI("Will enable the following device extensions:");

+ 1 - 6
AnKi/Gr/Vulkan/GrUpscaler.cpp

@@ -5,19 +5,14 @@
 
 #include <AnKi/Gr/GrUpscaler.h>
 #include <AnKi/Gr/GrManager.h>
-#include <AnKi/Gr/Texture.h>
 #include <AnKi/Gr/Vulkan/GrUpscalerImpl.h>
 
 namespace anki {
 
 GrUpscaler* GrUpscaler::newInstance(GrManager* manager, const GrUpscalerInitInfo& initInfo)
 {
-	GrUpscalerImpl* impl(nullptr);
-	impl = manager->getAllocator().newInstance<GrUpscalerImpl>(manager, "");
-	ANKI_ASSERT(impl);
-	impl->m_upscalerType = initInfo.m_upscalerType;
+	GrUpscalerImpl* impl = manager->getAllocator().newInstance<GrUpscalerImpl>(manager, initInfo.getName());
 	const Error err = impl->initInternal(initInfo);
-
 	if(err)
 	{
 		manager->getAllocator().deleteInstance(impl);

+ 77 - 200
AnKi/Gr/Vulkan/GrUpscalerImpl.cpp

@@ -10,193 +10,121 @@
 
 // Ngx specific
 #if ANKI_DLSS
-#include <ThirdParty/nvngx_dlss_sdk/sdk/include/nvsdk_ngx.h>
-#include <ThirdParty/nvngx_dlss_sdk/sdk/include/nvsdk_ngx_helpers.h>
-#include <ThirdParty/nvngx_dlss_sdk/sdk/include/nvsdk_ngx_vk.h>
-#include <ThirdParty/nvngx_dlss_sdk/sdk/include/nvsdk_ngx_helpers_vk.h>
+#	include <ThirdParty/DlssSdk/sdk/include/nvsdk_ngx.h>
+#	include <ThirdParty/DlssSdk/sdk/include/nvsdk_ngx_helpers.h>
+#	include <ThirdParty/DlssSdk/sdk/include/nvsdk_ngx_vk.h>
+#	include <ThirdParty/DlssSdk/sdk/include/nvsdk_ngx_helpers_vk.h>
 #endif
 
 namespace anki {
 
 GrUpscalerImpl::~GrUpscalerImpl()
-{
-	shutdown();
-}
-
-Error GrUpscalerImpl::initInternal(const GrUpscalerInitInfo& initInfo)
 {
 #if ANKI_DLSS
-	if(initInfo.m_upscalerType != GrUpscalerType::DLSS_2)
+	if(m_upscalerType == GrUpscalerType::DLSS_2)
 	{
-		ANKI_VK_LOGE("Currently only DLSS supported");
-		return Error::FUNCTION_FAILED;
+		destroyDlss();
 	}
-	return initAsDLSS(initInfo);
-#else
-	return Error::FUNCTION_FAILED;
 #endif
 }
 
-void GrUpscalerImpl::shutdown()
+Error GrUpscalerImpl::initInternal(const GrUpscalerInitInfo& initInfo)
 {
+	m_upscalerType = initInfo.m_upscalerType;
+
 #if ANKI_DLSS
-	shutdownDLSS();
+	ANKI_ASSERT(initInfo.m_upscalerType == GrUpscalerType::DLSS_2);
+	ANKI_CHECK(initDlss(initInfo));
+#else
+	ANKI_ASSERT(!"Not supported");
 #endif
+
+	return Error::NONE;
 }
 
-// NGX related logic
+// ==== DLSS ====
 #if ANKI_DLSS
 
-// Use random ID
-#	define ANKI_NGX_APP_ID 231313132
-#	define ANKI_RW_LOGS_DIR L"./"
-
-// See enum DLSSQualityMode
-static NVSDK_NGX_PerfQuality_Value g_NVQUALITYMODES[] = {
-	NVSDK_NGX_PerfQuality_Value_MaxPerf, // DISABLED
-	NVSDK_NGX_PerfQuality_Value_MaxPerf, NVSDK_NGX_PerfQuality_Value_Balanced, NVSDK_NGX_PerfQuality_Value_MaxQuality};
-
-static inline NVSDK_NGX_PerfQuality_Value getDlssQualityModeToNVQualityMode(GrUpscalerQualityMode mode)
+#	define ANKI_NGX_CHECK(x_) \
+		do \
+		{ \
+			const NVSDK_NGX_Result result = x_; \
+			if(NVSDK_NGX_FAILED(result)) \
+			{ \
+				ANKI_VK_LOGE("DLSS failed to initialize %ls", GetNGXResultAsString(result)); \
+				return Error::FUNCTION_FAILED; \
+			} \
+		} while(0)
+
+static NVSDK_NGX_PerfQuality_Value getDlssQualityModeToNVQualityMode(GrUpscalerQualityMode mode)
 {
-	return g_NVQUALITYMODES[static_cast<U32>(mode)];
+	static Array<NVSDK_NGX_PerfQuality_Value, U32(GrUpscalerQualityMode::COUNT)> nvQualityModes = {
+		NVSDK_NGX_PerfQuality_Value_MaxPerf, NVSDK_NGX_PerfQuality_Value_Balanced,
+		NVSDK_NGX_PerfQuality_Value_MaxQuality};
+
+	return nvQualityModes[mode];
 }
 
-Error GrUpscalerImpl::initAsDLSS(const GrUpscalerInitInfo& initInfo)
+Error GrUpscalerImpl::initDlss(const GrUpscalerInitInfo& initInfo)
 {
 	NVSDK_NGX_Result result = NVSDK_NGX_Result_Fail;
 
 	const VkDevice vkdevice = getGrManagerImpl().getDevice();
 	const VkPhysicalDevice vkphysicaldevice = getGrManagerImpl().getPhysicalDevice();
 	const VkInstance vkinstance = getGrManagerImpl().getInstance();
-	result = NVSDK_NGX_VULKAN_Init(ANKI_NGX_APP_ID, ANKI_RW_LOGS_DIR, vkinstance, vkphysicaldevice, vkdevice);
+	const U32 ngxAppId = 231313132; // Something random
+	const WChar* appLogs = L"./";
+	ANKI_NGX_CHECK(NVSDK_NGX_VULKAN_Init(ngxAppId, appLogs, vkinstance, vkphysicaldevice, vkdevice));
+	m_ngxInitialized = true;
 
-	m_ngxInitialized = !NVSDK_NGX_FAILED(result);
-	if(!isNgxInitialized())
-	{
-		if(result == NVSDK_NGX_Result_FAIL_FeatureNotSupported || result == NVSDK_NGX_Result_FAIL_PlatformError)
-		{
-			ANKI_VK_LOGE("NVIDIA NGX not available on this hardware/platform., code = 0x%08x, info: %ls", result,
-						 GetNGXResultAsString(result));
-		}
-		else
-		{
-			ANKI_VK_LOGE("Failed to initialize NGX, error code = 0x%08x, info: %ls", result,
-						 GetNGXResultAsString(result));
-		}
-
-		return Error::FUNCTION_FAILED;
-	}
-
-	result = NVSDK_NGX_VULKAN_GetCapabilityParameters(&m_ngxParameters);
-
-	if(NVSDK_NGX_FAILED(result))
-	{
-		ANKI_VK_LOGE("NVSDK_NGX_GetCapabilityParameters failed, code = 0x%08x, info: %ls", result,
-					 GetNGXResultAsString(result));
-		return Error::FUNCTION_FAILED;
-	}
+	ANKI_NGX_CHECK(NVSDK_NGX_VULKAN_GetCapabilityParameters(&m_ngxParameters));
+	ANKI_ASSERT(m_ngxParameters);
 
 	// Currently, the SDK and this sample are not in sync.  The sample is a bit forward looking,
 	// in this case.  This will likely be resolved very shortly, and therefore, the code below
 	// should be thought of as needed for a smooth user experience.
-#if defined(NVSDK_NGX_Parameter_SuperSampling_NeedsUpdatedDriver) \
-	&& defined(NVSDK_NGX_Parameter_SuperSampling_MinDriverVersionMajor) \
-	&& defined(NVSDK_NGX_Parameter_SuperSampling_MinDriverVersionMinor)
+#	if defined(NVSDK_NGX_Parameter_SuperSampling_NeedsUpdatedDriver) \
+		&& defined(NVSDK_NGX_Parameter_SuperSampling_MinDriverVersionMajor) \
+		&& defined(NVSDK_NGX_Parameter_SuperSampling_MinDriverVersionMinor)
 
 	// If NGX Successfully initialized then it should set those flags in return
 	I32 needsUpdatedDriver = 0;
-	U32 minDriverVersionMajor = 0;
-	U32 minDriverVersionMinor = 0;
-	const NVSDK_NGX_Result resultUpdatedDriver =
-		m_ngxParameters->Get(NVSDK_NGX_Parameter_SuperSampling_NeedsUpdatedDriver, &needsUpdatedDriver);
-	const NVSDK_NGX_Result resultMinDriverVersionMajor =
-		m_ngxParameters->Get(NVSDK_NGX_Parameter_SuperSampling_MinDriverVersionMajor, &minDriverVersionMajor);
-	const NVSDK_NGX_Result resultMinDriverVersionMinor =
-		m_ngxParameters->Get(NVSDK_NGX_Parameter_SuperSampling_MinDriverVersionMinor, &minDriverVersionMinor);
-	if(resultUpdatedDriver == NVSDK_NGX_Result_Success && resultMinDriverVersionMajor == NVSDK_NGX_Result_Success
-	   && resultMinDriverVersionMinor == NVSDK_NGX_Result_Success)
-	{
-		if(needsUpdatedDriver)
-		{
-			ANKI_VK_LOGE("NVIDIA DLSS cannot be loaded due to outdated driver. Minimum Driver Version required : %u.%u",
-						 minDriverVersionMajor, minDriverVersionMinor);
+	ANKI_NGX_CHECK(m_ngxParameters->Get(NVSDK_NGX_Parameter_SuperSampling_NeedsUpdatedDriver, &needsUpdatedDriver));
 
-			return Error::FUNCTION_FAILED;
-		}
-		else
-		{
-			ANKI_VK_LOGI("NVIDIA DLSS Minimum driver version was reported as : %u.%u", minDriverVersionMajor,
-						 minDriverVersionMinor);
-		}
-	}
-	else
+	if(needsUpdatedDriver)
 	{
-		ANKI_VK_LOGI("NVIDIA DLSS Minimum driver version was not reported.");
+		ANKI_VK_LOGE("DLSS cannot be loaded due to outdated driver");
+		return Error::FUNCTION_FAILED;
 	}
-
-#endif
+#	endif
 
 	I32 dlssAvailable = 0;
-	const NVSDK_NGX_Result resultDLSS =
-		m_ngxParameters->Get(NVSDK_NGX_Parameter_SuperSampling_Available, &dlssAvailable);
-	if(resultDLSS != NVSDK_NGX_Result_Success || !dlssAvailable)
+	ANKI_NGX_CHECK(m_ngxParameters->Get(NVSDK_NGX_Parameter_SuperSampling_Available, &dlssAvailable));
+	if(!dlssAvailable)
 	{
-		// More details about what failed (per feature init result)
-		I32 featureInitResult = NVSDK_NGX_Result_Fail;
-		NVSDK_NGX_Parameter_GetI(m_ngxParameters, NVSDK_NGX_Parameter_SuperSampling_FeatureInitResult,
-								 &featureInitResult);
-		ANKI_VK_LOGE("NVIDIA DLSS not available on this hardware/platform., FeatureInitResult = 0x%08x, info: %ls",
-					 featureInitResult, GetNGXResultAsString(static_cast<NVSDK_NGX_Result>(featureInitResult)));
+		ANKI_VK_LOGE("NVIDIA DLSS not available on this hardware/platform");
 		return Error::FUNCTION_FAILED;
 	}
 
 	// Create the feature
-	if(createDLSSFeature(initInfo.m_sourceImageResolution, initInfo.m_targetImageResolution,
-						 initInfo.m_qualityMode)
-	   != Error::NONE)
-	{
-		ANKI_VK_LOGE("Failed to create DLSS feature");
-		return Error::FUNCTION_FAILED;
-	}
+	ANKI_CHECK(createDlssFeature(initInfo.m_sourceTextureResolution, initInfo.m_targetTextureResolution,
+								 initInfo.m_qualityMode));
 
 	return Error::NONE;
 }
 
-void GrUpscalerImpl::shutdownDLSS()
-{
-	if(isNgxInitialized())
-	{
-		// WaitForIdle
-		getManager().finish();
-
-		if(m_dlssFeature != nullptr)
-		{
-			releaseDLSSFeature();
-		}
-		NVSDK_NGX_VULKAN_DestroyParameters(m_ngxParameters);
-		NVSDK_NGX_VULKAN_Shutdown();
-		m_ngxInitialized = false;
-	}
-}
-
-Error GrUpscalerImpl::createDLSSFeature(const UVec2& srcRes, const UVec2& dstRes, const GrUpscalerQualityMode mode)
+Error GrUpscalerImpl::createDlssFeature(const UVec2& srcRes, const UVec2& dstRes, const GrUpscalerQualityMode quality)
 {
-	ANKI_ASSERT(isNgxInitialized());
+	NVSDK_NGX_PerfQuality_Value nvQuality = getDlssQualityModeToNVQualityMode(quality);
+	ANKI_NGX_CHECK(NGX_DLSS_GET_OPTIMAL_SETTINGS(
+		m_ngxParameters, dstRes.x(), dstRes.y(), nvQuality, &m_recommendedSettings.m_optimalRenderSize.x(),
+		&m_recommendedSettings.m_optimalRenderSize.y(), &m_recommendedSettings.m_dynamicMaximumRenderSize.x(),
+		&m_recommendedSettings.m_dynamicMaximumRenderSize.y(), &m_recommendedSettings.m_dynamicMinimumRenderSize.x(),
+		&m_recommendedSettings.m_dynamicMinimumRenderSize.y(), &m_recommendedSettings.m_sharpness));
 
-	const U32 creationNodeMask = 1;
-	const U32 visibilityNodeMask = 1;
 	// Next create features	(See NVSDK_NGX_DLSS_Feature_Flags in nvsdk_ngx_defs.h)
 	const I32 dlssCreateFeatureFlags =
-		NVSDK_NGX_DLSS_Feature_Flags_None | NVSDK_NGX_DLSS_Feature_Flags_MVLowRes | NVSDK_NGX_DLSS_Feature_Flags_IsHDR;
-
-	const Error querySettingsResult = queryOptimalSettings(dstRes, mode, m_recommendedSettings);
-	if(querySettingsResult != Error::NONE
-	   || (srcRes < m_recommendedSettings.m_dynamicMinimumRenderSize
-		   || srcRes > m_recommendedSettings.m_dynamicMaximumRenderSize))
-	{
-		ANKI_VK_LOGE("Selected DLSS mode or render resolution is not supported");
-		return Error::FUNCTION_FAILED;
-	}
+		NVSDK_NGX_DLSS_Feature_Flags_MVLowRes | NVSDK_NGX_DLSS_Feature_Flags_IsHDR; // TODO
 
 	NVSDK_NGX_DLSS_Create_Params dlssCreateParams;
 	memset(&dlssCreateParams, 0, sizeof(dlssCreateParams));
@@ -204,95 +132,44 @@ Error GrUpscalerImpl::createDLSSFeature(const UVec2& srcRes, const UVec2& dstRes
 	dlssCreateParams.Feature.InHeight = srcRes.y();
 	dlssCreateParams.Feature.InTargetWidth = dstRes.x();
 	dlssCreateParams.Feature.InTargetHeight = dstRes.y();
-	dlssCreateParams.Feature.InPerfQualityValue =
-		getDlssQualityModeToNVQualityMode(m_recommendedSettings.m_qualityMode);
+	dlssCreateParams.Feature.InPerfQualityValue = nvQuality;
 	dlssCreateParams.InFeatureCreateFlags = dlssCreateFeatureFlags;
 
 	// Create the feature with a tmp CmdBuffer
 	CommandBufferInitInfo cmdbinit;
 	cmdbinit.m_flags = CommandBufferFlag::GENERAL_WORK | CommandBufferFlag::SMALL_BATCH;
-	const CommandBufferPtr cmdb = getManager().newCommandBuffer(cmdbinit);
+	CommandBufferPtr cmdb = getManager().newCommandBuffer(cmdbinit);
 	CommandBufferImpl& cmdbImpl = static_cast<CommandBufferImpl&>(*cmdb);
 
 	cmdbImpl.beginRecordingExt();
-	const NVSDK_NGX_Result resultDLSS = NGX_VULKAN_CREATE_DLSS_EXT(cmdbImpl.getHandle(), creationNodeMask, visibilityNodeMask,
-															 &m_dlssFeature,
-											m_ngxParameters, &dlssCreateParams);
-	if(NVSDK_NGX_FAILED(resultDLSS))
-	{
-		ANKI_VK_LOGE("Failed to create DLSS Features = 0x%08x, info: %ls", resultDLSS,
-					 GetNGXResultAsString(resultDLSS));
-		return Error::FUNCTION_FAILED;
-	}
+	const U32 creationNodeMask = 1;
+	const U32 visibilityNodeMask = 1;
+	ANKI_NGX_CHECK(NGX_VULKAN_CREATE_DLSS_EXT(cmdbImpl.getHandle(), creationNodeMask, visibilityNodeMask,
+											  &m_dlssFeature, m_ngxParameters, &dlssCreateParams));
 	cmdb->flush();
 
 	return Error::NONE;
 }
 
-void GrUpscalerImpl::releaseDLSSFeature()
+void GrUpscalerImpl::destroyDlss()
 {
-	ANKI_ASSERT(isNgxInitialized());
-
-	getManager().finish();
-
-	const NVSDK_NGX_Result resultDLSS =
-		(m_dlssFeature != nullptr) ? NVSDK_NGX_VULKAN_ReleaseFeature(m_dlssFeature) : NVSDK_NGX_Result_Success;
-	if(NVSDK_NGX_FAILED(resultDLSS))
+	if(m_dlssFeature)
 	{
-		ANKI_VK_LOGE("Failed to NVSDK_NGX_D3D12_ReleaseFeature, code = 0x%08x, info: %ls", resultDLSS,
-					 GetNGXResultAsString(resultDLSS));
+		NVSDK_NGX_VULKAN_ReleaseFeature(m_dlssFeature);
+		m_dlssFeature = nullptr;
 	}
 
-	m_dlssFeature = nullptr;
-}
-
-static Error queryNgxQualitySettings(const UVec2& displayRes, const NVSDK_NGX_PerfQuality_Value quality,
-									 NVSDK_NGX_Parameter& parameters, DLSSRecommendedSettings& outSettings)
-{
-	const NVSDK_NGX_Result result = NGX_DLSS_GET_OPTIMAL_SETTINGS(
-		&parameters, displayRes.x(), displayRes.y(), quality, &outSettings.m_recommendedOptimalRenderSize[0],
-		&outSettings.m_recommendedOptimalRenderSize[1], &outSettings.m_dynamicMaximumRenderSize[0],
-		&outSettings.m_dynamicMaximumRenderSize[1], &outSettings.m_dynamicMinimumRenderSize[0],
-		&outSettings.m_dynamicMinimumRenderSize[1], &outSettings.m_recommendedSharpness);
-
-	if(NVSDK_NGX_FAILED(result))
+	if(m_ngxParameters)
 	{
-		outSettings.m_recommendedOptimalRenderSize = displayRes;
-		outSettings.m_dynamicMaximumRenderSize = displayRes;
-		outSettings.m_dynamicMinimumRenderSize = displayRes;
-		outSettings.m_recommendedSharpness = 0.0f;
-
-		ANKI_VK_LOGW("Querying Settings failed! code = 0x%08x, info: %ls", result, GetNGXResultAsString(result));
-		return Error::FUNCTION_FAILED;
+		NVSDK_NGX_VULKAN_DestroyParameters(m_ngxParameters);
+		m_ngxParameters = nullptr;
 	}
-	return Error::NONE;
-}
 
-Error GrUpscalerImpl::queryOptimalSettings(const UVec2& displayRes, const GrUpscalerQualityMode mode,
-										   DLSSRecommendedSettings& outRecommendedSettings)
-{
-	ANKI_ASSERT(mode < GrUpscalerQualityMode::COUNT);
-
-	outRecommendedSettings.m_qualityMode = mode;
-	Error err(Error::FUNCTION_FAILED);
-	switch(mode)
+	if(m_ngxInitialized)
 	{
-	case GrUpscalerQualityMode::PERFORMANCE:
-		err = queryNgxQualitySettings(displayRes, NVSDK_NGX_PerfQuality_Value_MaxPerf, *m_ngxParameters,
-									  outRecommendedSettings);
-		break;
-	case GrUpscalerQualityMode::BALANCED:
-		err = queryNgxQualitySettings(displayRes, NVSDK_NGX_PerfQuality_Value_Balanced, *m_ngxParameters,
-									  outRecommendedSettings);
-		break;
-	case GrUpscalerQualityMode::QUALITY:
-		err = queryNgxQualitySettings(displayRes, NVSDK_NGX_PerfQuality_Value_MaxQuality, *m_ngxParameters,
-									  outRecommendedSettings);
-		break;
-	default:
-		break;
+		NVSDK_NGX_VULKAN_Shutdown();
+		m_ngxInitialized = false;
 	}
-	return err;
 }
 #endif // ANKI_DLSS
 

+ 11 - 26
AnKi/Gr/Vulkan/GrUpscalerImpl.h

@@ -21,11 +21,10 @@ namespace anki {
 class DLSSRecommendedSettings
 {
 public:
-	F32 m_recommendedSharpness = 0.01f;
-	UVec2 m_recommendedOptimalRenderSize = UVec2(MAX_U32, MAX_U32);
-	UVec2 m_dynamicMaximumRenderSize = UVec2(MAX_U32, MAX_U32);
-	UVec2 m_dynamicMinimumRenderSize = UVec2(MAX_U32, MAX_U32);
-	GrUpscalerQualityMode m_qualityMode;
+	F32 m_sharpness = 0.01f;
+	UVec2 m_optimalRenderSize = UVec2(MAX_U32);
+	UVec2 m_dynamicMaximumRenderSize = UVec2(MAX_U32);
+	UVec2 m_dynamicMinimumRenderSize = UVec2(MAX_U32);
 };
 
 class GrUpscalerImpl final : public GrUpscaler, public VulkanObject<GrUpscaler, GrUpscalerImpl>
@@ -42,7 +41,7 @@ public:
 
 	/// @name DLSS data accessors
 	/// @{
-
+#if ANKI_DLSS
 	NVSDK_NGX_Parameter& getParameters() const
 	{
 		return *m_ngxParameters;
@@ -57,36 +56,22 @@ public:
 	{
 		return m_recommendedSettings;
 	}
-
+#endif
 	/// @}
 
 private:
-
-	// DLSS related
-	Bool m_ngxInitialized = false;
+#if ANKI_DLSS
 	NVSDK_NGX_Parameter* m_ngxParameters = nullptr;
 	NVSDK_NGX_Handle* m_dlssFeature = nullptr;
 	DLSSRecommendedSettings m_recommendedSettings;
+	Bool m_ngxInitialized = false;
 
-	void shutdown();
-
-#if ANKI_DLSS
-	Error initAsDLSS(const GrUpscalerInitInfo& initInfo);
-
-	void shutdownDLSS();
-
-	Error createDLSSFeature(const UVec2& srcRes, const UVec2& dstRes, const GrUpscalerQualityMode mode);
+	Error initDlss(const GrUpscalerInitInfo& initInfo);
 
-	void releaseDLSSFeature();
+	void destroyDlss();
 
-	Error queryOptimalSettings(const UVec2& displayRes, const GrUpscalerQualityMode mode,
-							   DLSSRecommendedSettings& outRecommendedSettings);
+	Error createDlssFeature(const UVec2& srcRes, const UVec2& dstRes, const GrUpscalerQualityMode mode);
 #endif
-
-	Bool isNgxInitialized() const
-	{
-		return m_ngxInitialized;
-	}
 };
 /// @}
 

+ 1 - 0
AnKi/Gr/Vulkan/TextureImpl.cpp

@@ -277,6 +277,7 @@ Error TextureImpl::initImage(const TextureInitInfo& init)
 	ci.samples = VK_SAMPLE_COUNT_1_BIT;
 	ci.tiling = VK_IMAGE_TILING_OPTIMAL;
 	ci.usage = convertTextureUsage(init.m_usage, init.m_format);
+	m_vkUsageFlags = ci.usage;
 	ci.queueFamilyIndexCount = getGrManagerImpl().getQueueFamilies().getSize();
 	ci.pQueueFamilyIndices = &getGrManagerImpl().getQueueFamilies()[0];
 	ci.sharingMode = (ci.queueFamilyIndexCount > 1) ? VK_SHARING_MODE_CONCURRENT : VK_SHARING_MODE_EXCLUSIVE;

+ 1 - 1
AnKi/Gr/Vulkan/TextureImpl.h

@@ -84,7 +84,7 @@ public:
 	GpuMemoryHandle m_memHandle;
 
 	VkFormat m_vkFormat = VK_FORMAT_UNDEFINED;
-
+	VkImageUsageFlags m_vkUsageFlags = 0;
 	VkImageViewCreateInfo m_viewCreateInfoTemplate;
 	VkImageViewASTCDecodeModeEXT m_astcDecodeMode;
 

+ 1 - 1
AnKi/Renderer/Bloom.cpp

@@ -147,7 +147,7 @@ void Bloom::populateRenderGraph(RenderingContext& ctx)
 			const Vec4 uniforms(getConfig().getRBloomThreshold(), getConfig().getRBloomScale(), 0.0f, 0.0f);
 			cmdb->setPushConstants(&uniforms, sizeof(uniforms));
 
-			rgraphCtx.bindImage(0, 2, m_r->getTonemapping().getExposureLuminanceRT());
+			rgraphCtx.bindImage(0, 2, m_r->getTonemapping().getRt());
 
 			if(getConfig().getRPreferCompute())
 			{

+ 5 - 11
AnKi/Renderer/DownscaleBlur.cpp

@@ -5,9 +5,8 @@
 
 #include <AnKi/Renderer/DownscaleBlur.h>
 #include <AnKi/Renderer/Renderer.h>
-#include <AnKi/Renderer/TemporalAA.h>
-#include <AnKi/Renderer/LightShading.h>
 #include <AnKi/Renderer/Scale.h>
+#include <AnKi/Renderer/Tonemapping.h>
 #include <AnKi/Core/ConfigSet.h>
 
 namespace anki {
@@ -90,10 +89,6 @@ void DownscaleBlur::populateRenderGraph(RenderingContext& ctx)
 	// Create passes
 	static const Array<CString, 8> passNames = {"DownBlur #0",  "Down/Blur #1", "Down/Blur #2", "Down/Blur #3",
 												"Down/Blur #4", "Down/Blur #5", "Down/Blur #6", "Down/Blur #7"};
-
-	const RenderTargetHandle srcTarget =
-		m_r->getScale().getUsingDLSS() ? m_r->getLightShading().getRt() : m_r->getTemporalAA().getHdrRt();
-
 	if(getConfig().getRPreferCompute())
 	{
 		for(U32 i = 0; i < m_passCount; ++i)
@@ -119,7 +114,7 @@ void DownscaleBlur::populateRenderGraph(RenderingContext& ctx)
 				TextureSubresourceInfo renderSubresource;
 
 				pass.newDependency({m_runCtx.m_rt, TextureUsageBit::IMAGE_COMPUTE_WRITE, renderSubresource});
-				pass.newDependency({srcTarget, TextureUsageBit::SAMPLED_COMPUTE});
+				pass.newDependency({m_r->getScale().getRt(), TextureUsageBit::SAMPLED_COMPUTE});
 			}
 		}
 	}
@@ -149,7 +144,7 @@ void DownscaleBlur::populateRenderGraph(RenderingContext& ctx)
 				TextureSubresourceInfo renderSubresource;
 
 				pass.newDependency({m_runCtx.m_rt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE, renderSubresource});
-				pass.newDependency({srcTarget, TextureUsageBit::SAMPLED_FRAGMENT});
+				pass.newDependency({m_r->getScale().getRt(), TextureUsageBit::SAMPLED_FRAGMENT});
 			}
 		}
 	}
@@ -174,11 +169,10 @@ void DownscaleBlur::run(U32 passIdx, RenderPassWorkContext& rgraphCtx)
 	}
 	else
 	{
-		rgraphCtx.bindColorTexture(
-			0, 1, m_r->getScale().getUsingDLSS() ? m_r->getLightShading().getRt() : m_r->getTemporalAA().getHdrRt());
+		rgraphCtx.bindColorTexture(0, 1, m_r->getScale().getRt());
 	}
 
-	rgraphCtx.bindUniformBuffer(0, 2, m_r->getTonemapping().getAverageLuminanceBuffer());
+	rgraphCtx.bindImage(0, 2, m_r->getTonemapping().getRt());
 
 	const Bool revertTonemap = passIdx == 0;
 	const UVec4 fbSize(vpWidth, vpHeight, revertTonemap, 0);

+ 1 - 13
AnKi/Renderer/FinalComposite.cpp

@@ -48,7 +48,6 @@ Error FinalComposite::initInternal()
 	variantInitInfo.addConstant("LUT_SIZE", U32(LUT_SIZE));
 	variantInitInfo.addConstant("FB_SIZE", m_r->getPostProcessResolution());
 	variantInitInfo.addConstant("MOTION_BLUR_SAMPLES", getConfig().getRMotionBlurSamples());
-	variantInitInfo.addMutation("APPLY_TONEMAPPING", m_r->getScale().getUsingDLSS() ? 1 : 0);
 
 	for(U32 dbg = 0; dbg < 2; ++dbg)
 	{
@@ -114,12 +113,6 @@ void FinalComposite::populateRenderGraph(RenderingContext& ctx)
 		RenderPassDependency(m_r->getMotionVectors().getMotionVectorsRt(), TextureUsageBit::SAMPLED_FRAGMENT));
 	pass.newDependency(RenderPassDependency(m_r->getGBuffer().getDepthRt(), TextureUsageBit::SAMPLED_FRAGMENT));
 
-	if(m_r->getScale().getUsingDLSS())
-	{
-		pass.newDependency(
-			RenderPassDependency(m_r->getTonemapping().getExposureLuminanceRT(), TextureUsageBit::IMAGE_FRAGMENT_READ));
-	}
-
 	RenderTargetHandle dbgRt;
 	Bool dbgRtValid;
 	ShaderProgramPtr debugProgram;
@@ -169,14 +162,9 @@ void FinalComposite::run(RenderingContext& ctx, RenderPassWorkContext& rgraphCtx
 		rgraphCtx.bindTexture(0, 8, m_r->getGBuffer().getDepthRt(),
 							  TextureSubresourceInfo(DepthStencilAspectBit::DEPTH));
 
-		if(m_r->getScale().getUsingDLSS())
-		{
-			rgraphCtx.bindImage(0, 9, m_r->getTonemapping().getExposureLuminanceRT());
-		}
-
 		if(dbgEnabled)
 		{
-			rgraphCtx.bindColorTexture(0, 10, m_r->getDbg().getRt());
+			rgraphCtx.bindColorTexture(0, 9, m_r->getDbg().getRt());
 		}
 
 		const UVec4 frameCount(m_r->getFrameCount() & MAX_U32);

+ 11 - 6
AnKi/Renderer/Renderer.cpp

@@ -188,9 +188,6 @@ Error Renderer::initInternal(UVec2 swapchainResolution)
 	m_temporalAA.reset(getAllocator().newInstance<TemporalAA>(this));
 	ANKI_CHECK(m_temporalAA->init());
 
-	m_scale.reset(m_alloc.newInstance<Scale>(this));
-	ANKI_CHECK(m_scale->init());
-
 	m_bloom.reset(m_alloc.newInstance<Bloom>(this));
 	ANKI_CHECK(m_bloom->init());
 
@@ -203,6 +200,9 @@ Error Renderer::initInternal(UVec2 swapchainResolution)
 	m_uiStage.reset(m_alloc.newInstance<UiStage>(this));
 	ANKI_CHECK(m_uiStage->init());
 
+	m_scale.reset(m_alloc.newInstance<Scale>(this));
+	ANKI_CHECK(m_scale->init());
+
 	m_indirectDiffuse.reset(m_alloc.newInstance<IndirectDiffuse>(this));
 	ANKI_CHECK(m_indirectDiffuse->init());
 
@@ -244,8 +244,13 @@ Error Renderer::initInternal(UVec2 swapchainResolution)
 		sinit.m_anisotropyLevel = m_config->getRTextureAnisotropy();
 		m_samplers.m_trilinearRepeatAniso = m_gr->newSampler(sinit);
 
-		const F32 scalingMipBias =
-			log2(F32(m_internalResolution.x()) / F32(m_postProcessResolution.x())) - (getScale().getUsingDLSS() ? 1 : 0);
+		F32 scalingMipBias = log2(F32(m_internalResolution.x()) / F32(m_postProcessResolution.x()));
+		if(getScale().getUsingGrUpscaler())
+		{
+			// DLSS wants more bias
+			scalingMipBias -= 1.0f;
+		}
+
 		sinit.m_lodBias = scalingMipBias;
 		m_samplers.m_trilinearRepeatAnisoResolutionScalingBias = m_gr->newSampler(sinit);
 	}
@@ -363,7 +368,7 @@ Error Renderer::populateRenderGraph(RenderingContext& ctx)
 	m_indirectSpecular->populateRenderGraph(ctx);
 	m_indirectDiffuse->populateRenderGraph(ctx);
 	m_lightShading->populateRenderGraph(ctx);
-	if(!getScale().getUsingDLSS())
+	if(!getScale().getUsingGrUpscaler())
 	{
 		m_temporalAA->populateRenderGraph(ctx);
 	}

+ 144 - 108
AnKi/Renderer/Scale.cpp

@@ -36,12 +36,6 @@ Scale::~Scale()
 {
 }
 
-Bool Scale::getUsingDLSS() const
-{
-	Bool needsScaling = m_r->getPostProcessResolution() != m_r->getInternalResolution();
-	return needsScaling && (getConfig().getRDlss() != 0) && m_r->getGrManager().getDeviceCapabilities().m_dlss;
-}
-
 Error Scale::init()
 {
 	ANKI_R_LOGV("Initializing scale");
@@ -54,59 +48,83 @@ Error Scale::init()
 	}
 
 	const Bool preferCompute = getConfig().getRPreferCompute();
+	const U32 dlssQuality = getConfig().getRDlss();
 	const U32 fsrQuality = getConfig().getRFsr();
-	// Dlss and FSR are mutually exclusive
-	const Bool useDlss = getUsingDLSS();
-	m_fsr = (fsrQuality != 0) && !useDlss;
 
-	// Program
 	if(needsScaling)
 	{
-		CString shaderFname;
-		if(m_fsr && preferCompute)
-		{
-			shaderFname = "ShaderBinaries/FsrCompute.ankiprogbin";
-		}
-		else if(m_fsr)
+		if(dlssQuality > 0 && getGrManager().getDeviceCapabilities().m_dlss)
 		{
-			shaderFname = "ShaderBinaries/FsrRaster.ankiprogbin";
+			m_upscalingMethod = UpscalingMethod::GR;
 		}
-		else if(preferCompute)
+		else if(fsrQuality > 0)
 		{
-			shaderFname = "ShaderBinaries/BlitCompute.ankiprogbin";
+			m_upscalingMethod = UpscalingMethod::FSR;
 		}
-		else if(!useDlss)
+		else
 		{
-			shaderFname = "ShaderBinaries/BlitRaster.ankiprogbin";
+			m_upscalingMethod = UpscalingMethod::BILINEAR;
 		}
+	}
+	else
+	{
+		m_upscalingMethod = UpscalingMethod::NONE;
+	}
 
-		if(useDlss)
+	if(needsSharpening)
+	{
+		if(m_upscalingMethod == UpscalingMethod::GR)
 		{
-			const GrUpscalerInitInfo init(m_r->getInternalResolution(), m_r->getPostProcessResolution(),
-									GrUpscalerType::DLSS_2,
-									static_cast<GrUpscalerQualityMode>(getConfig().getRDlss()));
-			// Do not need to load shaders
-			m_grUpscaler = getGrManager().newGrUpscaler(init);
+			m_sharpenMethod = SharpenMethod::GR;
 		}
 		else
 		{
-			ANKI_CHECK(getResourceManager().loadResource(shaderFname, m_scaleProg));
-			const ShaderProgramResourceVariant* variant;
-			if(m_fsr)
-			{
-				ShaderProgramResourceVariantInitInfo variantInitInfo(m_scaleProg);
-				variantInitInfo.addMutation("SHARPEN", 0);
-				variantInitInfo.addMutation("FSR_QUALITY", fsrQuality - 1);
-				m_scaleProg->getOrCreateVariant(variantInitInfo, variant);
-			}
-			else
-			{
-				m_scaleProg->getOrCreateVariant(variant);
-			}
-			m_scaleGrProg = variant->getProgram();
+			m_sharpenMethod = SharpenMethod::RCAS;
 		}
 	}
+	else
+	{
+		m_sharpenMethod = SharpenMethod::NONE;
+	}
 
+	// Scale programs
+	if(m_upscalingMethod == UpscalingMethod::BILINEAR)
+	{
+		const CString shaderFname =
+			(preferCompute) ? "ShaderBinaries/BlitCompute.ankiprogbin" : "ShaderBinaries/BlitRaster.ankiprogbin";
+
+		ANKI_CHECK(getResourceManager().loadResource(shaderFname, m_scaleProg));
+
+		const ShaderProgramResourceVariant* variant;
+		m_scaleProg->getOrCreateVariant(variant);
+		m_scaleGrProg = variant->getProgram();
+	}
+	else if(m_upscalingMethod == UpscalingMethod::FSR)
+	{
+		const CString shaderFname =
+			(preferCompute) ? "ShaderBinaries/FsrCompute.ankiprogbin" : "ShaderBinaries/FsrRaster.ankiprogbin";
+
+		ANKI_CHECK(getResourceManager().loadResource(shaderFname, m_scaleProg));
+
+		ShaderProgramResourceVariantInitInfo variantInitInfo(m_scaleProg);
+		variantInitInfo.addMutation("SHARPEN", 0);
+		variantInitInfo.addMutation("FSR_QUALITY", fsrQuality - 1);
+		const ShaderProgramResourceVariant* variant;
+		m_scaleProg->getOrCreateVariant(variantInitInfo, variant);
+		m_scaleGrProg = variant->getProgram();
+	}
+	else if(m_upscalingMethod == UpscalingMethod::GR)
+	{
+		GrUpscalerInitInfo inf;
+		inf.m_sourceTextureResolution = m_r->getInternalResolution();
+		inf.m_targetTextureResolution = m_r->getPostProcessResolution();
+		inf.m_upscalerType = GrUpscalerType::DLSS_2;
+		inf.m_qualityMode = GrUpscalerQualityMode(dlssQuality - 1);
+
+		m_grUpscaler = getGrManager().newGrUpscaler(inf);
+	}
+
+	// Sharpen programs
 	if(needsSharpening)
 	{
 		ANKI_CHECK(getResourceManager().loadResource((preferCompute) ? "ShaderBinaries/FsrCompute.ankiprogbin"
@@ -121,13 +139,22 @@ Error Scale::init()
 	}
 
 	// Descriptors
-	Format desiredScaledFormat =
-		useDlss ? m_r->getHdrFormat()
-				: ((getGrManager().getDeviceCapabilities().m_unalignedBbpTextureFormats) ? Format::R8G8B8_UNORM
-																						 : Format::R8G8B8A8_UNORM);
-	const char* rtName = useDlss ? "Scaled (DLSS)" : (m_fsr ? "Scaled (FSR)" : "Scaled");
+	Format format;
+	if(m_upscalingMethod == UpscalingMethod::GR)
+	{
+		format = m_r->getHdrFormat();
+	}
+	else if(getGrManager().getDeviceCapabilities().m_unalignedBbpTextureFormats)
+	{
+		format = Format::R8G8B8_UNORM;
+	}
+	else
+	{
+		format = Format::R8G8B8A8_UNORM;
+	}
+
 	m_rtDesc = m_r->create2DRenderTargetDescription(m_r->getPostProcessResolution().x(),
-													m_r->getPostProcessResolution().y(), desiredScaledFormat, rtName);
+													m_r->getPostProcessResolution().y(), format, "Scaling");
 	m_rtDesc.bake();
 
 	m_fbDescr.m_colorAttachmentCount = 1;
@@ -138,7 +165,7 @@ Error Scale::init()
 
 void Scale::populateRenderGraph(RenderingContext& ctx)
 {
-	if(!doScaling() && !doSharpening())
+	if(m_upscalingMethod == UpscalingMethod::NONE && m_sharpenMethod == SharpenMethod::NONE)
 	{
 		m_runCtx.m_scaledRt = m_r->getTemporalAA().getRt();
 		m_runCtx.m_sharpenedRt = m_r->getTemporalAA().getRt();
@@ -148,68 +175,72 @@ void Scale::populateRenderGraph(RenderingContext& ctx)
 	RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
 	const Bool preferCompute = getConfig().getRPreferCompute();
 
-	if(doScaling())
+	// Scaling
+	if(m_upscalingMethod == UpscalingMethod::GR)
 	{
 		m_runCtx.m_scaledRt = rgraph.newRenderTarget(m_rtDesc);
-		if(doDLSS())
+
+		ComputeRenderPassDescription& pass = ctx.m_renderGraphDescr.newComputeRenderPass("DLSS");
+		pass.newDependency(RenderPassDependency(m_r->getLightShading().getRt(), TextureUsageBit::ALL_READ));
+		pass.newDependency(
+			RenderPassDependency(m_r->getMotionVectors().getMotionVectorsRt(), TextureUsageBit::ALL_READ));
+		pass.newDependency(RenderPassDependency(m_r->getTonemapping().getRt(), TextureUsageBit::ALL_READ));
+		pass.newDependency(RenderPassDependency(m_r->getGBuffer().getDepthRt(), TextureUsageBit::ALL_READ,
+												TextureSubresourceInfo(DepthStencilAspectBit::DEPTH)));
+		pass.newDependency(RenderPassDependency(m_runCtx.m_scaledRt, TextureUsageBit::ALL_WRITE));
+
+		pass.setWork([this, &ctx](RenderPassWorkContext& rgraphCtx) {
+			runGrUpscaling(ctx, rgraphCtx);
+		});
+	}
+	else if(m_upscalingMethod == UpscalingMethod::FSR || m_upscalingMethod == UpscalingMethod::BILINEAR)
+	{
+		m_runCtx.m_scaledRt = rgraph.newRenderTarget(m_rtDesc);
+
+		if(preferCompute)
 		{
-			ComputeRenderPassDescription& pass = ctx.m_renderGraphDescr.newComputeRenderPass("DLSS");
-			pass.newDependency(RenderPassDependency(m_r->getLightShading().getRt(), TextureUsageBit::SAMPLED_COMPUTE));
-			pass.newDependency(
-				RenderPassDependency(m_r->getMotionVectors().getMotionVectorsRt(), TextureUsageBit::SAMPLED_COMPUTE));
-			pass.newDependency(
-				RenderPassDependency(m_r->getTonemapping().getExposureLuminanceRT(), TextureUsageBit::IMAGE_COMPUTE_READ));
-			pass.newDependency(RenderPassDependency(m_r->getGBuffer().getDepthRt(), TextureUsageBit::SAMPLED_COMPUTE,
-													TextureSubresourceInfo(DepthStencilAspectBit::DEPTH)));
+			ComputeRenderPassDescription& pass = ctx.m_renderGraphDescr.newComputeRenderPass("Scale");
+			pass.newDependency(RenderPassDependency(m_r->getTemporalAA().getRt(), TextureUsageBit::SAMPLED_COMPUTE));
 			pass.newDependency(RenderPassDependency(m_runCtx.m_scaledRt, TextureUsageBit::IMAGE_COMPUTE_WRITE));
 
-			pass.setWork([this, &ctx](RenderPassWorkContext& rgraphCtx) {
-				runDLSS(ctx, rgraphCtx);
+			pass.setWork([this](RenderPassWorkContext& rgraphCtx) {
+				runFsrOrBilinearScaling(rgraphCtx);
 			});
 		}
 		else
 		{
-			if(preferCompute)
-			{
-				ComputeRenderPassDescription& pass = ctx.m_renderGraphDescr.newComputeRenderPass("Scale");
-				pass.newDependency(
-					RenderPassDependency(m_r->getTemporalAA().getTonemappedRt(), TextureUsageBit::SAMPLED_COMPUTE));
-				pass.newDependency(RenderPassDependency(m_runCtx.m_scaledRt, TextureUsageBit::IMAGE_COMPUTE_WRITE));
-
-				pass.setWork([this](RenderPassWorkContext& rgraphCtx) {
-					runScaling(rgraphCtx);
-				});
-			}
-			else
-			{
-				GraphicsRenderPassDescription& pass = ctx.m_renderGraphDescr.newGraphicsRenderPass("Scale");
-				pass.setFramebufferInfo(m_fbDescr, {m_runCtx.m_scaledRt});
-
-				pass.newDependency(
-					RenderPassDependency(m_r->getTemporalAA().getTonemappedRt(), TextureUsageBit::SAMPLED_FRAGMENT));
-				pass.newDependency(
-					RenderPassDependency(m_runCtx.m_scaledRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE));
-
-				pass.setWork([this](RenderPassWorkContext& rgraphCtx) {
-					runScaling(rgraphCtx);
-				});
-			}
+			GraphicsRenderPassDescription& pass = ctx.m_renderGraphDescr.newGraphicsRenderPass("Scale");
+			pass.setFramebufferInfo(m_fbDescr, {m_runCtx.m_scaledRt});
+
+			pass.newDependency(RenderPassDependency(m_r->getTemporalAA().getRt(), TextureUsageBit::SAMPLED_FRAGMENT));
+			pass.newDependency(
+				RenderPassDependency(m_runCtx.m_scaledRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE));
+
+			pass.setWork([this](RenderPassWorkContext& rgraphCtx) {
+				runFsrOrBilinearScaling(rgraphCtx);
+			});
 		}
 	}
+	else
+	{
+		ANKI_ASSERT(m_upscalingMethod == UpscalingMethod::NONE);
+	}
 
-	if(doSharpening())
+	// Sharpenning
+	if(m_sharpenMethod == SharpenMethod::RCAS)
 	{
 		m_runCtx.m_sharpenedRt = rgraph.newRenderTarget(m_rtDesc);
+		const RenderTargetHandle inRt =
+			(m_upscalingMethod == UpscalingMethod::NONE) ? m_r->getTemporalAA().getRt() : m_runCtx.m_scaledRt;
 
 		if(preferCompute)
 		{
 			ComputeRenderPassDescription& pass = ctx.m_renderGraphDescr.newComputeRenderPass("Sharpen");
-			pass.newDependency(RenderPassDependency((!doScaling()) ? m_r->getTemporalAA().getRt() : m_runCtx.m_scaledRt,
-													TextureUsageBit::SAMPLED_COMPUTE));
+			pass.newDependency(RenderPassDependency(inRt, TextureUsageBit::SAMPLED_COMPUTE));
 			pass.newDependency(RenderPassDependency(m_runCtx.m_sharpenedRt, TextureUsageBit::IMAGE_COMPUTE_WRITE));
 
 			pass.setWork([this](RenderPassWorkContext& rgraphCtx) {
-				runSharpening(rgraphCtx);
+				runRcasSharpening(rgraphCtx);
 			});
 		}
 		else
@@ -217,19 +248,26 @@ void Scale::populateRenderGraph(RenderingContext& ctx)
 			GraphicsRenderPassDescription& pass = ctx.m_renderGraphDescr.newGraphicsRenderPass("Sharpen");
 			pass.setFramebufferInfo(m_fbDescr, {m_runCtx.m_sharpenedRt});
 
-			pass.newDependency(RenderPassDependency((!doScaling()) ? m_r->getTemporalAA().getRt() : m_runCtx.m_scaledRt,
-													TextureUsageBit::SAMPLED_FRAGMENT));
+			pass.newDependency(RenderPassDependency(inRt, TextureUsageBit::SAMPLED_FRAGMENT));
 			pass.newDependency(
 				RenderPassDependency(m_runCtx.m_sharpenedRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE));
 
 			pass.setWork([this](RenderPassWorkContext& rgraphCtx) {
-				runSharpening(rgraphCtx);
+				runRcasSharpening(rgraphCtx);
 			});
 		}
 	}
+	else if(m_sharpenMethod == SharpenMethod::GR)
+	{
+		m_runCtx.m_sharpenedRt = m_runCtx.m_scaledRt;
+	}
+	else
+	{
+		ANKI_ASSERT(m_sharpenMethod == SharpenMethod::NONE);
+	}
 }
 
-void Scale::runScaling(RenderPassWorkContext& rgraphCtx)
+void Scale::runFsrOrBilinearScaling(RenderPassWorkContext& rgraphCtx)
 {
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 	const Bool preferCompute = getConfig().getRPreferCompute();
@@ -244,7 +282,7 @@ void Scale::runScaling(RenderPassWorkContext& rgraphCtx)
 		rgraphCtx.bindImage(0, 2, m_runCtx.m_scaledRt);
 	}
 
-	if(m_fsr)
+	if(m_upscalingMethod == UpscalingMethod::FSR)
 	{
 		class
 		{
@@ -291,7 +329,7 @@ void Scale::runScaling(RenderPassWorkContext& rgraphCtx)
 	}
 }
 
-void Scale::runSharpening(RenderPassWorkContext& rgraphCtx)
+void Scale::runRcasSharpening(RenderPassWorkContext& rgraphCtx)
 {
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 	const Bool preferCompute = getConfig().getRPreferCompute();
@@ -299,7 +337,8 @@ void Scale::runSharpening(RenderPassWorkContext& rgraphCtx)
 	cmdb->bindShaderProgram(m_sharpenGrProg);
 
 	cmdb->bindSampler(0, 0, m_r->getSamplers().m_trilinearClamp);
-	rgraphCtx.bindColorTexture(0, 1, (!doScaling()) ? m_r->getTemporalAA().getRt() : m_runCtx.m_scaledRt);
+	rgraphCtx.bindColorTexture(
+		0, 1, (m_upscalingMethod == UpscalingMethod::NONE) ? m_r->getTemporalAA().getRt() : m_runCtx.m_scaledRt);
 
 	if(preferCompute)
 	{
@@ -334,26 +373,23 @@ void Scale::runSharpening(RenderPassWorkContext& rgraphCtx)
 	}
 }
 
-void Scale::runDLSS(RenderingContext& ctx, RenderPassWorkContext& rgraphCtx)
+void Scale::runGrUpscaling(RenderingContext& ctx, RenderPassWorkContext& rgraphCtx)
 {
-	const Vec2 srcRes = static_cast<Vec2>(m_r->getInternalResolution());
+	const Vec2 srcRes(m_r->getInternalResolution());
 	const Bool reset = m_r->getFrameCount() == 0;
 	const Vec2 mvScale = srcRes; // UV space to Pixel space factor
 	// In [-texSize / 2, texSize / 2] -> sub-pixel space {-0.5, 0.5}
 	const Vec2 jitterOffset = ctx.m_matrices.m_jitter.getTranslationPart().xy() * srcRes * 0.5f;
 
-	const TexturePtr srcRT(rgraphCtx.getTargetTexture(m_r->getLightShading().getRt()));
-	const TexturePtr mvRT(rgraphCtx.getTargetTexture(m_r->getMotionVectors().getMotionVectorsRt()));
-	const TexturePtr depthRT(rgraphCtx.getTargetTexture(m_r->getGBuffer().getDepthRt()));
-	const TexturePtr dstRT(rgraphCtx.getTargetTexture(m_runCtx.m_scaledRt));
-	const TexturePtr exposureRT(rgraphCtx.getTargetTexture(m_r->getTonemapping().getExposureLuminanceRT()));
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 
-	cmdb->upscale(m_grUpscaler, getGrManager().newTextureView(TextureViewInitInfo(srcRT, "DLSS_Src")),
-				  getGrManager().newTextureView(TextureViewInitInfo(dstRT, "DLSS_Dst")),
-				  getGrManager().newTextureView(TextureViewInitInfo(mvRT, "DLSS_MV")),
-				  getGrManager().newTextureView(TextureViewInitInfo(depthRT, "DLSS_Depth")),
-				  getGrManager().newTextureView(TextureViewInitInfo(exposureRT, "DLSS_Exposure")), reset, jitterOffset,
+	TextureViewPtr srcView = rgraphCtx.createTextureView(m_r->getLightShading().getRt());
+	TextureViewPtr motionVectorsView = rgraphCtx.createTextureView(m_r->getMotionVectors().getMotionVectorsRt());
+	TextureViewPtr depthView = rgraphCtx.createTextureView(m_r->getGBuffer().getDepthRt());
+	TextureViewPtr exposureView = rgraphCtx.createTextureView(m_r->getTonemapping().getRt());
+	TextureViewPtr dstView = rgraphCtx.createTextureView(m_runCtx.m_scaledRt);
+
+	cmdb->upscale(m_grUpscaler, srcView, dstView, motionVectorsView, depthView, exposureView, reset, jitterOffset,
 				  mvScale);
 }
 

+ 26 - 21
AnKi/Renderer/Scale.h

@@ -29,10 +29,13 @@ public:
 
 	RenderTargetHandle getRt() const
 	{
-		return (doSharpening()) ? m_runCtx.m_sharpenedRt : m_runCtx.m_scaledRt;
+		return (m_sharpenMethod != SharpenMethod::NONE) ? m_runCtx.m_sharpenedRt : m_runCtx.m_scaledRt;
 	}
 
-	Bool getUsingDLSS() const;
+	Bool getUsingGrUpscaler() const
+	{
+		return m_grUpscaler.isCreated();
+	}
 
 private:
 	ShaderProgramResourcePtr m_scaleProg;
@@ -45,7 +48,24 @@ private:
 	FramebufferDescription m_fbDescr;
 	RenderTargetDescription m_rtDesc;
 
-	Bool m_fsr = false;
+	enum class UpscalingMethod : U8
+	{
+		NONE,
+		BILINEAR,
+		FSR,
+		GR
+	};
+
+	UpscalingMethod m_upscalingMethod = UpscalingMethod::NONE;
+
+	enum class SharpenMethod : U8
+	{
+		NONE,
+		RCAS,
+		GR
+	};
+
+	SharpenMethod m_sharpenMethod = SharpenMethod::NONE;
 
 	class
 	{
@@ -54,24 +74,9 @@ private:
 		RenderTargetHandle m_sharpenedRt;
 	} m_runCtx;
 
-	void runScaling(RenderPassWorkContext& rgraphCtx);
-	void runSharpening(RenderPassWorkContext& rgraphCtx);
-	void runDLSS(RenderingContext& ctx, RenderPassWorkContext& rgraphCtx);
-
-	Bool doSharpening() const
-	{
-		return m_sharpenProg.isCreated();
-	}
-
-	Bool doDLSS() const
-	{
-		return m_grUpscaler.isCreated();
-	}
-
-	Bool doScaling() const
-	{
-		return m_scaleProg.isCreated() || doDLSS();
-	}
+	void runFsrOrBilinearScaling(RenderPassWorkContext& rgraphCtx);
+	void runRcasSharpening(RenderPassWorkContext& rgraphCtx);
+	void runGrUpscaling(RenderingContext& ctx, RenderPassWorkContext& rgraphCtx);
 };
 /// @}
 

+ 1 - 1
AnKi/Renderer/TemporalAA.cpp

@@ -153,7 +153,7 @@ void TemporalAA::populateRenderGraph(RenderingContext& ctx)
 		rgraphCtx.bindColorTexture(0, 2, m_r->getLightShading().getRt());
 		rgraphCtx.bindColorTexture(0, 3, m_runCtx.m_historyRt);
 		rgraphCtx.bindColorTexture(0, 4, m_r->getMotionVectors().getMotionVectorsRt());
-		rgraphCtx.bindImage(0, 5, m_r->getTonemapping().getExposureLuminanceRT());
+		rgraphCtx.bindImage(0, 5, m_r->getTonemapping().getRt());
 
 		if(getConfig().getRPreferCompute())
 		{

+ 13 - 29
AnKi/Renderer/Tonemapping.cpp

@@ -38,40 +38,24 @@ Error Tonemapping::initInternal()
 	m_prog->getOrCreateVariant(variantInitInfo, variant);
 	m_grProg = variant->getProgram();
 
-	// Create exposure texture
-	TextureUsageBit usage =
-		TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::SAMPLED_COMPUTE | TextureUsageBit::IMAGE_COMPUTE_WRITE;
-	TextureInitInfo texinit = m_r->create2DRenderTargetInitInfo(1, 1, Format::R16G16_SFLOAT, usage, "Exposure 1x1");
-	m_exposureLuminance1x1 = m_r->createAndClearRenderTarget(texinit, TextureUsageBit::TRANSFER_DESTINATION);
-
-	CommandBufferInitInfo cmdbinit;
-	cmdbinit.m_flags = CommandBufferFlag::SMALL_BATCH | CommandBufferFlag::GENERAL_WORK;
-	CommandBufferPtr cmdb = getGrManager().newCommandBuffer(cmdbinit);
-
-	TransferGpuAllocatorHandle handle;
-	ANKI_CHECK(m_r->getResourceManager().getTransferGpuAllocator().allocate(sizeof(Vec4), handle));
-	void* data = handle.getMappedMemory();
-	*static_cast<Vec4*>(data) = Vec4(0.5);
-	TextureSubresourceInfo subresource;
-	subresource = TextureSubresourceInfo(TextureSurfaceInfo(0, 0, 0, 0));
-	TextureViewPtr tmpView =
-		getGrManager().newTextureView(TextureViewInitInfo(m_exposureLuminance1x1, subresource, "ExposureTmpView"));
-	cmdb->copyBufferToTextureView(handle.getBuffer(), handle.getOffset(), 2*sizeof(F32), tmpView);
-
-	FencePtr fence;
-	cmdb->flush({}, &fence);
-
-	m_r->getResourceManager().getTransferGpuAllocator().release(handle, fence);
+	// Create exposure texture.
+	// WARNING: Use it only as IMAGE and nothing else. It will not be tracked by the rendergraph. No tracking means no
+	// automatic image transitions
+	const TextureUsageBit usage = TextureUsageBit::ALL_IMAGE;
+	const TextureInitInfo texinit =
+		m_r->create2DRenderTargetInitInfo(1, 1, Format::R16G16_SFLOAT, usage, "ExposureAndAvgLum1x1");
+	ClearValue clearValue;
+	clearValue.m_colorf = {0.5f, 0.5f, 0.5f, 0.5f};
+	m_exposureAndAvgLuminance1x1 = m_r->createAndClearRenderTarget(texinit, TextureUsageBit::ALL_IMAGE, clearValue);
 
 	return Error::NONE;
 }
 
 void Tonemapping::importRenderTargets(RenderingContext& ctx)
 {
-	// Computation of the AVG luminance will run first in the frame and it will use the m_exposureLuminance1x1 as storage
-	// read/write. To skip the barrier import it as read/write as well.
-	m_runCtx.m_exposureLuminanceHandle = ctx.m_renderGraphDescr.importRenderTarget(
-		m_exposureLuminance1x1, TextureUsageBit::IMAGE_COMPUTE_READ | TextureUsageBit::IMAGE_COMPUTE_WRITE);
+	// Just import it. It will not be used in resource tracking
+	m_runCtx.m_exposureLuminanceHandle =
+		ctx.m_renderGraphDescr.importRenderTarget(m_exposureAndAvgLuminance1x1, TextureUsageBit::ALL_IMAGE);
 }
 
 void Tonemapping::populateRenderGraph(RenderingContext& ctx)
@@ -79,7 +63,7 @@ void Tonemapping::populateRenderGraph(RenderingContext& ctx)
 	RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
 
 	// Create the pass
-	ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("Avg lum");
+	ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("AvgLuminance");
 
 	pass.setWork([this](RenderPassWorkContext& rgraphCtx) {
 		CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;

+ 4 - 2
AnKi/Renderer/Tonemapping.h

@@ -28,7 +28,8 @@ public:
 	/// Populate the rendergraph.
 	void populateRenderGraph(RenderingContext& ctx);
 
-	RenderTargetHandle getExposureLuminanceRT() const
+	/// @copydoc m_exposureAndAvgLuminance1x1
+	RenderTargetHandle getRt() const
 	{
 		return m_runCtx.m_exposureLuminanceHandle;
 	}
@@ -38,7 +39,8 @@ private:
 	ShaderProgramPtr m_grProg;
 	U32 m_inputTexMip;
 
-	TexturePtr m_exposureLuminance1x1;
+	/// This is a 1x1 2 component texture where R is the exposure and G the average luminance
+	TexturePtr m_exposureAndAvgLuminance1x1;
 
 	class
 	{

+ 2 - 16
AnKi/Renderer/VrsSriGeneration.cpp

@@ -5,10 +5,7 @@
 
 #include <AnKi/Renderer/VrsSriGeneration.h>
 #include <AnKi/Renderer/Renderer.h>
-#include <AnKi/Renderer/TemporalAA.h>
 #include <AnKi/Renderer/LightShading.h>
-#include <AnKi/Renderer/Tonemapping.h>
-#include <Anki/Renderer/Scale.h>
 #include <AnKi/Core/ConfigSet.h>
 
 namespace anki {
@@ -81,7 +78,6 @@ Error VrsSriGeneration::initInternal()
 		variantInit.addMutation("SHARED_MEMORY", 1);
 	}
 
-	variantInit.addMutation("HDR_INPUT", m_r->getScale().getUsingDLSS() ? 1 : 0);
 	variantInit.addMutation("LIMIT_RATE_TO_2X2", getConfig().getRVrsLimitTo2x2());
 
 	const ShaderProgramResourceVariant* variant;
@@ -153,26 +149,16 @@ void VrsSriGeneration::populateRenderGraph(RenderingContext& ctx)
 		ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("VRS SRI generation");
 
 		pass.newDependency(RenderPassDependency(m_runCtx.m_rt, TextureUsageBit::IMAGE_COMPUTE_WRITE));
-		const Bool useTonemappedRT = !m_r->getScale().getUsingDLSS();
-		pass.newDependency(RenderPassDependency(useTonemappedRT ? m_r->getTemporalAA().getTonemappedRt()
-																: m_r->getLightShading().getRt(),
-												TextureUsageBit::SAMPLED_COMPUTE));
+		pass.newDependency(RenderPassDependency(m_r->getLightShading().getRt(), TextureUsageBit::SAMPLED_COMPUTE));
 
 		pass.setWork([this](RenderPassWorkContext& rgraphCtx) {
 			CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 
 			cmdb->bindShaderProgram(m_grProg);
 
-			const Bool useTonemappedRT = !m_r->getScale().getUsingDLSS();
-			rgraphCtx.bindColorTexture(
-				0, 0, useTonemappedRT ? m_r->getTemporalAA().getTonemappedRt() : m_r->getLightShading().getRt());
-
+			rgraphCtx.bindColorTexture(0, 0, m_r->getLightShading().getRt());
 			cmdb->bindSampler(0, 1, m_r->getSamplers().m_nearestNearestClamp);
 			rgraphCtx.bindImage(0, 2, m_runCtx.m_rt);
-			if(m_r->getScale().getUsingDLSS())
-			{
-				rgraphCtx.bindImage(0, 3, m_r->getTonemapping().getExposureLuminanceRT());
-			}
 			const Vec4 pc(1.0f / Vec2(m_r->getInternalResolution()), getConfig().getRVrsThreshold(), 0.0f);
 			cmdb->setPushConstants(&pc, sizeof(pc));
 

+ 1 - 1
AnKi/Shaders/Bloom.glsl

@@ -50,7 +50,7 @@ void main()
 	color += textureLodOffset(sampler2D(u_tex, u_linearAnyClampSampler), uv, 0.0, IVec2(-1, +1)).rgb * weight;
 	color += textureLodOffset(sampler2D(u_tex, u_linearAnyClampSampler), uv, 0.0, IVec2(+1, -1)).rgb * weight;
 
-	color = tonemap(color, getExposureLuminance().x, u_thresholdScalePad2.x) * u_thresholdScalePad2.y;
+	color = tonemap(color, readExposureAndAverageLuminance().y, u_thresholdScalePad2.x) * u_thresholdScalePad2.y;
 
 #if defined(ANKI_COMPUTE_SHADER)
 	imageStore(u_outImg, IVec2(gl_GlobalInvocationID.xy), Vec4(color, 0.0));

+ 1 - 1
AnKi/Shaders/DownscaleBlur.glsl

@@ -55,7 +55,7 @@ void main()
 	{
 		out_color = saturate(out_color);
 		out_color = sRgbToLinear(out_color);
-		out_color = invertTonemap(out_color, u_exposureThreshold0);
+		out_color = invertTonemap(out_color, readExposureAndAverageLuminance().x);
 	}
 
 #if defined(ANKI_COMPUTE_SHADER)

+ 0 - 13
AnKi/Shaders/FinalComposite.ankiprog

@@ -5,7 +5,6 @@
 
 #pragma anki mutator BLUE_NOISE 0 1
 #pragma anki mutator BLOOM_ENABLED 0 1
-#pragma anki mutator APPLY_TONEMAPPING 0 1
 #pragma anki mutator DBG_ENABLED 0 1
 
 ANKI_SPECIALIZATION_CONSTANT_U32(LUT_SIZE, 0u);
@@ -31,13 +30,6 @@ layout(set = 0, binding = 5) uniform ANKI_RP texture3D u_lut;
 layout(set = 0, binding = 6) uniform ANKI_RP texture2D u_blueNoise;
 layout(set = 0, binding = 7) uniform texture2D u_motionVectorsRt;
 layout(set = 0, binding = 8) uniform texture2D u_depthRt;
-#if APPLY_TONEMAPPING
-#	include <AnKi/Shaders/TonemappingFunctions.glsl>
-const U32 TONEMAPPING_SET = 0u;
-const U32 TONEMAPPING_BINDING = 9u;
-#	include <AnKi/Shaders/TonemappingResources.glsl>
-#endif
-
 #if DBG_ENABLED
 layout(set = 0, binding = 9) uniform ANKI_RP texture2D u_dbgOutlineRt;
 #endif
@@ -75,11 +67,6 @@ void main()
 		out_color = textureLod(u_lightShadingRt, u_linearAnyClampSampler, uv, 0.0).rgb;
 	}
 
-#if APPLY_TONEMAPPING
-	const Vec2 prevExposureLuminance = getExposureLuminance();
-	out_color = linearToSRgb(tonemap(out_color, prevExposureLuminance.x));
-#endif
-
 #if BLOOM_ENABLED
 	const ANKI_RP Vec3 bloom = textureLod(u_ppsBloomLfRt, u_linearAnyClampSampler, uv, 0.0).rgb;
 	out_color += bloom;

+ 1 - 2
AnKi/Shaders/TemporalAA.glsl

@@ -110,8 +110,7 @@ void main()
 #if YCBCR
 	outColor = yCbCrToRgb(outColor);
 #endif
-	const Vec2 prevExposureLuminance = getExposureLuminance();
-	const Vec3 tonemapped = linearToSRgb(tonemap(outColor, prevExposureLuminance.x));
+	const Vec3 tonemapped = linearToSRgb(tonemap(outColor, readExposureAndAverageLuminance().x));
 #if defined(ANKI_COMPUTE_SHADER)
 	imageStore(u_outImg, IVec2(gl_GlobalInvocationID.xy), Vec4(outColor, 0.0));
 	imageStore(u_tonemappedImg, IVec2(gl_GlobalInvocationID.xy), Vec4(tonemapped, 0.0));

+ 2 - 5
AnKi/Shaders/TonemappingAverageLuminance.ankiprog

@@ -24,8 +24,6 @@ layout(set = 0, binding = 0) uniform ANKI_RP texture2D u_tex;
 #define TONEMAPPING_BINDING 1
 #include <AnKi/Shaders/TonemappingResources.glsl>
 
-// Needed for DLSS
-
 shared F32 s_avgLum[WORKGROUP_SIZE.x * WORKGROUP_SIZE.y];
 
 void main()
@@ -87,8 +85,7 @@ void main()
 #endif
 
 #if 1
-		const Vec2 prevExposureLuminance = getExposureLuminance();
-		const F32 prevLum = prevExposureLuminance.y;
+		const F32 prevLum = readExposureAndAverageLuminance().y;
 
 		// Lerp between previous and new L value
 		const F32 INTERPOLATION_FACTOR = 0.05;
@@ -100,7 +97,7 @@ void main()
 		// This is a workaround because sometimes the avg lum becomes nan
 		finalAvgLum = clamp(finalAvgLum, EPSILON, MAX_F32);
 
-		writeExposureAndLuminance(computeExposure(finalAvgLum, 0.0), finalAvgLum);
+		writeExposureAndAverageLuminance(computeExposure(finalAvgLum, 0.0), finalAvgLum);
 	}
 }
 #pragma anki end

+ 9 - 9
AnKi/Shaders/TonemappingResources.glsl

@@ -9,24 +9,24 @@
 
 #include <AnKi/Shaders/Common.glsl>
 
-#ifndef TONEMAPPING_RESOURCE_AS_WRITE_IMAGE
+#if !defined(TONEMAPPING_RESOURCE_AS_WRITE_IMAGE)
 #	define TONEMAPPING_RESOURCE_AS_WRITE_IMAGE 0
 #endif
 
 #if TONEMAPPING_RESOURCE_AS_WRITE_IMAGE
-layout(set = 0, binding = TONEMAPPING_BINDING) uniform image2D b_tonemapping;
+layout(set = 0, binding = TONEMAPPING_BINDING) ANKI_RP uniform coherent image2D u_tonemappingImage;
 #else
-layout(set = 0, binding = TONEMAPPING_BINDING) uniform readonly image2D b_tonemapping;
+layout(set = 0, binding = TONEMAPPING_BINDING) ANKI_RP uniform readonly image2D u_tonemappingImage;
 #endif
 
-void writeExposureAndLuminance(float exposure, float luminance)
-{
 #if TONEMAPPING_RESOURCE_AS_WRITE_IMAGE
-	imageStore(b_tonemapping, IVec2(0, 0), Vec4(exposure, luminance, 0.0f, 0.0f));
-#endif
+void writeExposureAndAverageLuminance(ANKI_RP F32 exposure, ANKI_RP F32 avgLuminance)
+{
+	imageStore(u_tonemappingImage, IVec2(0), Vec4(exposure, avgLuminance, 0.0f, 0.0f));
 }
+#endif
 
-Vec2 getExposureLuminance()
+ANKI_RP Vec2 readExposureAndAverageLuminance()
 {
-	return imageLoad(b_tonemapping, IVec2(0, 0)).xy;
+	return imageLoad(u_tonemappingImage, IVec2(0)).xy;
 }

+ 8 - 16
AnKi/Shaders/VrsSriGenerationCompute.ankiprog

@@ -6,7 +6,6 @@
 #pragma anki mutator SRI_TEXEL_DIMENSION 8 16
 #pragma anki mutator SHARED_MEMORY 0 1
 #pragma anki mutator LIMIT_RATE_TO_2X2 0 1
-#pragma anki mutator HDR_INPUT 0 1
 
 #pragma anki start comp
 
@@ -16,11 +15,6 @@
 // Find the maximum luma derivative in x and y, relative to the average luma of the block.
 // Each thread handles a 2x2 region when using 8x8 VRS tiles and a 2x4 region when using 16x16 VRS tiles.
 
-#if HDR_INPUT
-const U32 TONEMAPPING_SET = 0u;
-const U32 TONEMAPPING_BINDING = 3u;
-#	include <AnKi/Shaders/TonemappingResources.glsl>
-#endif
 layout(set = 0, binding = 0) uniform ANKI_RP texture2D u_inputTex;
 layout(set = 0, binding = 1) uniform sampler u_nearestClampSampler;
 
@@ -51,16 +45,14 @@ shared F32 s_averageLuma[SHARED_MEMORY_ENTRIES];
 shared Vec2 s_maxDerivative[SHARED_MEMORY_ENTRIES];
 #endif
 
-#if HDR_INPUT
-#	define sampleLuma(offsetX, offsetY) \
-		computeLuminance(linearToSRgb(tonemap( \
-			textureLodOffset(sampler2D(u_inputTex, u_nearestClampSampler), uv, 0.0, IVec2(offsetX, offsetY)).xyz, \
-			getExposureLuminance().x)))
-#else
-#	define sampleLuma(offsetX, offsetY) \
-		computeLuminance( \
-			textureLodOffset(sampler2D(u_inputTex, u_nearestClampSampler), uv, 0.0, IVec2(offsetX, offsetY)).xyz)
-#endif
+F32 computeLuma(Vec3 color)
+{
+	const F32 l = computeLuminance(color);
+	return l / (1.0f + l);
+}
+
+#define sampleLuma(offsetX, offsetY) \
+	computeLuma(textureLodOffset(sampler2D(u_inputTex, u_nearestClampSampler), uv, 0.0, IVec2(offsetX, offsetY)).xyz)
 
 void main()
 {

+ 1 - 0
AnKi/Util/StdTypes.h

@@ -74,6 +74,7 @@ static_assert(sizeof(bool) == 1, "Wrong size for bool");
 
 using Bool32 = I32;
 using Char = char;
+using WChar = wchar_t;
 
 using Second = F64; ///< The base time unit is second.
 constexpr Second MAX_SECOND = MAX_F64;

+ 5 - 34
CMakeLists.txt

@@ -34,34 +34,6 @@ macro(anki_new_executable)
 	endif()
 endmacro()
 
-macro(add_AnkiNgx_dependencies)
-    if(ANKI_DLSS)
-        # Copy required DLLs
-        get_target_property(lib_type AnkiNgx TYPE)
-        if ("${lib_type}" STREQUAL "SHARED_LIBRARY")
-            get_target_property(ANKINGX_DLL AnkiNgx IMPORTED_LOCATION)
-            add_custom_command(TARGET ${ARGV}
-                COMMENT "Dependant DLLs copy ${ANKINGX_DLL} ${CMAKE_BINARY_DIR}/Bin"
-                COMMAND ${CMAKE_COMMAND} -E copy_if_different "${ANKINGX_DLL}" "${CMAKE_BINARY_DIR}/Bin")
-            STRING(REGEX REPLACE "\\\\" "/" ANKINGX_DLL ${ANKINGX_DLL})
-            install(FILES ${ANKINGX_DLL} DESTINATION ${CMAKE_INSTALL_BINDIR})
-        else()
-            get_property(__NGX_DLLS_LIST TARGET AnkiNgx PROPERTY ANKINGX_EXTRA_DLLS)
-            foreach(dll_path ${__NGX_DLLS_LIST})
-                file(GLOB dll_files "${dll_path}")
-                foreach(dll_file ${dll_files})
-                    add_custom_command(TARGET ${ARGV}
-                        COMMENT "NGX DLL copy ${dll_file} ${CMAKE_BINARY_DIR}/Bin\n"
-                        COMMAND ${CMAKE_COMMAND} -E copy_if_different "${dll_file}" "${CMAKE_BINARY_DIR}/Bin")
-                    STRING(REGEX REPLACE "\\\\" "/" dll_file ${dll_file})
-                    install(FILES ${dll_file} DESTINATION ${CMAKE_INSTALL_BINDIR})
-                endforeach()
-            endforeach()
-        endif()
-    endif()
-
-endmacro()
-
 ################################################################################
 # Determin the system to build for. Do that first                              #
 ################################################################################
@@ -155,7 +127,7 @@ option(ANKI_ADDRESS_SANITIZER "Enable address sanitizer (-fsanitize=address)" OF
 option(ANKI_HEADLESS "Build a headless application" OFF)
 option(ANKI_SHADER_FULL_PRECISION "Build shaders with full precision" OFF)
 set(ANKI_OVERRIDE_SHADER_COMPILER "" CACHE FILEPATH "Set the ShaderCompiler to be used to compile all shaders")
-option(ANKI_DLSS "Integrate DLSS if supported" ON)
+option(ANKI_DLSS "Integrate DLSS if supported" OFF)
 
 # Take a wild guess on the windowing system
 if(ANKI_HEADLESS)
@@ -326,12 +298,11 @@ if(ANDROID)
 endif()
 
 # DLSS
-if(ANKI_DLSS AND (LINUX OR WINDOWS) AND VULKAN)
-	add_subdirectory(ThirdParty/nvngx_dlss_sdk)
-	set(_ANKI_DLSS_SUPPORTED 1)
+if(ANKI_DLSS)
+	add_subdirectory(ThirdParty/DlssSdk)
+	set(_ANKI_DLSS_ENABLED 1)
 else()
-	set(ANKI_DLSS OFF CACHE BOOL "Disable DLSS support" FORCE)
-	set(_ANKI_DLSS_SUPPORTED 0)
+	set(_ANKI_DLSS_ENABLED 0)
 endif()
 
 ################################################################################

+ 25 - 26
ThirdParty/DlssSdk/CMakeLists.txt

@@ -1,29 +1,28 @@
-# Create AnkiNgx
+# Create AnkiNgx. Inspired by the DLSS example
 if(ANKI_DLSS)
-    set(NGX_SDK_ROOT "${CMAKE_CURRENT_LIST_DIR}/sdk")
-    # Only Linux and Windows support working with Nvidia SDK (NGX)
-    if (WINDOWS)
-        add_library(AnkiNgx IMPORTED SHARED GLOBAL)
-        set_property(TARGET AnkiNgx APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
-        set_property(TARGET AnkiNgx APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
-        set_target_properties(AnkiNgx PROPERTIES IMPORTED_IMPLIB_DEBUG ${NGX_SDK_ROOT}/lib/Windows_x86_64/x86_64/nvsdk_ngx_d_dbg.lib)
-        set_target_properties(AnkiNgx PROPERTIES IMPORTED_IMPLIB_RELEASE ${NGX_SDK_ROOT}/lib/Windows_x86_64/x86_64/nvsdk_ngx_d.lib)
-        set_target_properties(AnkiNgx PROPERTIES
-            MAP_IMPORTED_CONFIG_MINSIZEREL Release
-            MAP_IMPORTED_CONFIG_RELWITHDEBINFO Release
-        )
-        set_target_properties(AnkiNgx PROPERTIES IMPORTED_LOCATION "${NGX_SDK_ROOT}/lib/Windows_x86_64/rel/nvngx_dlss.dll")
-    elseif (LINUX)
-        add_library(AnkiNgx IMPORTED STATIC GLOBAL)
-        set_property(TARGET AnkiNgx APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
-        set_property(TARGET AnkiNgx APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
-        set_property(TARGET AnkiNgx PROPERTY IMPORTED_LOCATION ${NGX_SDK_ROOT}/lib/Linux_x86_64/libnvsdk_ngx.a)
-        # set the list of DLLs that need copying to target folder of application
-        set(__NGX_DLLS_LIST "${NGX_SDK_ROOT}/lib/Linux_x86_64/rel/libnvidia-ngx-*.so.*")
-    else()
+	set(NGX_SDK_ROOT "${CMAKE_CURRENT_LIST_DIR}/sdk")
+	# Only Linux and Windows support working with Nvidia SDK (NGX)
+	if(WINDOWS)
+		add_library(AnkiNgx IMPORTED SHARED GLOBAL)
+		set_property(TARGET AnkiNgx APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
+		set_property(TARGET AnkiNgx APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
+		set_target_properties(AnkiNgx PROPERTIES IMPORTED_IMPLIB_DEBUG ${NGX_SDK_ROOT}/lib/Windows_x86_64/x86_64/nvsdk_ngx_d_dbg.lib)
+		set_target_properties(AnkiNgx PROPERTIES IMPORTED_IMPLIB_RELEASE ${NGX_SDK_ROOT}/lib/Windows_x86_64/x86_64/nvsdk_ngx_d.lib)
+		set_target_properties(AnkiNgx PROPERTIES
+			MAP_IMPORTED_CONFIG_MINSIZEREL Release
+			MAP_IMPORTED_CONFIG_RELWITHDEBINFO Release
+		)
+		set_target_properties(AnkiNgx PROPERTIES IMPORTED_LOCATION "${NGX_SDK_ROOT}/lib/Windows_x86_64/rel/nvngx_dlss.dll")
+	elseif(LINUX)
+		add_library(AnkiNgx IMPORTED STATIC GLOBAL)
+		set_property(TARGET AnkiNgx APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
+		set_property(TARGET AnkiNgx APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
+		set_property(TARGET AnkiNgx PROPERTY IMPORTED_LOCATION ${NGX_SDK_ROOT}/lib/Linux_x86_64/libnvsdk_ngx.a)
+		# set the list of DLLs that need copying to target folder of application
+		set(__NGX_DLLS_LIST "${NGX_SDK_ROOT}/lib/Linux_x86_64/rel/libnvidia-ngx-*.so.*")
+	else()
 		message(FATAL_ERROR "Trying to use NGX for invalid platform")
-    endif()
+	endif()
 
-    set_property(TARGET AnkiNgx APPEND PROPERTY ANKINGX_EXTRA_DLLS "${__NGX_DLLS_LIST}")
-    target_include_directories(AnkiNgx INTERFACE ${NGX_SDK_ROOT}/include)
-endif()
+	set_property(TARGET AnkiNgx APPEND PROPERTY ANKINGX_EXTRA_DLLS "${__NGX_DLLS_LIST}")
+endif()