Browse Source

Support VK_EXT_sampler_filter_minmax (not tested)

Panagiotis Christopoulos Charitos 4 years ago
parent
commit
0a1b684f01

+ 4 - 1
AnKi/Gr/Common.h

@@ -156,10 +156,13 @@ public:
 
 	/// 64 bit atomics.
 	Bool m_64bitAtomics = false;
+
+	/// Supports min/max texture filtering.
+	Bool m_samplingFilterMinMax = false;
 };
 ANKI_END_PACKED_STRUCT
 static_assert(sizeof(GpuDeviceCapabilities)
-				  == sizeof(PtrSize) * 4 + sizeof(U32) * 5 + sizeof(U8) * 3 + sizeof(Bool) * 2,
+				  == sizeof(PtrSize) * 4 + sizeof(U32) * 5 + sizeof(U8) * 3 + sizeof(Bool) * 3,
 			  "Should be packed");
 
 /// Bindless related info.

+ 1 - 0
AnKi/Gr/ConfigDefs.h

@@ -11,6 +11,7 @@ ANKI_CONFIG_OPTION(gr_maxBindlessTextures, 256, 8, 1024)
 ANKI_CONFIG_OPTION(gr_maxBindlessImages, 32, 8, 1024)
 ANKI_CONFIG_OPTION(gr_rayTracing, 0, 0, 1, "Try enabling ray tracing")
 ANKI_CONFIG_OPTION(gr_64bitAtomics, 1, 0, 1)
+ANKI_CONFIG_OPTION(gr_samplerFilterMinMax, 1, 0, 1)
 
 // Vulkan
 ANKI_CONFIG_OPTION(gr_diskShaderCacheMaxSize, 128_MB, 1_MB, 1_GB)

+ 3 - 1
AnKi/Gr/Enums.h

@@ -280,7 +280,9 @@ enum class SamplingFilter : U8
 {
 	NEAREST,
 	LINEAR,
-	BASE ///< Only for mipmaps
+	MIN, ///< It calculates the min of a 2x2 quad. Only if GpuDeviceCapabilities::m_samplingFilterMinMax is supported.
+	MAX, ///< It calculates the max of a 2x2 quad. Only if GpuDeviceCapabilities::m_samplingFilterMinMax is supported.
+	BASE ///< Only for mipmaps.
 };
 
 enum class SamplingAddressing : U8

+ 1 - 0
AnKi/Gr/Vulkan/Common.h

@@ -80,6 +80,7 @@ enum class VulkanExtensions : U32
 	KHR_SHADER_ATOMIC_INT64 = 1 << 18,
 	KHR_SPIRV_1_4 = 1 << 19,
 	KHR_SHADER_FLOAT_CONTROLS = 1 << 20,
+	EXT_SAMPLER_FILTER_MIN_MAX = 1 << 21,
 };
 ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(VulkanExtensions)
 

+ 16 - 0
AnKi/Gr/Vulkan/GrManagerImpl.cpp

@@ -678,6 +678,12 @@ Error GrManagerImpl::initDevice(const GrManagerInitInfo& init)
 				m_extensions |= VulkanExtensions::KHR_SHADER_FLOAT_CONTROLS;
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
 			}
+			else if(extensionName == VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME
+					&& init.m_config->getBool("gr_samplerFilterMinMax"))
+			{
+				m_extensions |= VulkanExtensions::EXT_SAMPLER_FILTER_MIN_MAX;
+				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
+			}
 		}
 
 		ANKI_VK_LOGI("Will enable the following device extensions:");
@@ -703,6 +709,16 @@ Error GrManagerImpl::initDevice(const GrManagerInitInfo& init)
 		ci.pEnabledFeatures = &m_devFeatures;
 	}
 
+	if(!!(m_extensions & VulkanExtensions::EXT_SAMPLER_FILTER_MIN_MAX))
+	{
+		m_capabilities.m_samplingFilterMinMax = true;
+	}
+	else
+	{
+		m_capabilities.m_samplingFilterMinMax = false;
+		ANKI_VK_LOGI(VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME " is not supported or disabled");
+	}
+
 	// Descriptor indexing
 	if(!(m_extensions & VulkanExtensions::EXT_DESCRIPTOR_INDEXING))
 	{

+ 28 - 3
AnKi/Gr/Vulkan/SamplerFactory.cpp

@@ -25,14 +25,21 @@ Error MicroSampler::init(const SamplerInitInfo& inf)
 
 	if(inf.m_minMagFilter == SamplingFilter::NEAREST)
 	{
-		ci.magFilter = ci.minFilter = VK_FILTER_NEAREST;
+		ci.minFilter = VK_FILTER_NEAREST;
+	}
+	else if(inf.m_minMagFilter == SamplingFilter::LINEAR)
+	{
+		ci.minFilter = VK_FILTER_LINEAR;
 	}
 	else
 	{
-		ANKI_ASSERT(inf.m_minMagFilter == SamplingFilter::LINEAR);
-		ci.magFilter = ci.minFilter = VK_FILTER_LINEAR;
+		ANKI_ASSERT(inf.m_minMagFilter == SamplingFilter::MAX || inf.m_minMagFilter == SamplingFilter::MIN);
+		ANKI_ASSERT(m_factory->m_gr->getDeviceCapabilities().m_samplingFilterMinMax);
+		ci.minFilter = VK_FILTER_LINEAR;
 	}
 
+	ci.magFilter = ci.minFilter;
+
 	if(inf.m_mipmapFilter == SamplingFilter::BASE || inf.m_mipmapFilter == SamplingFilter::NEAREST)
 	{
 		ci.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
@@ -81,6 +88,24 @@ Error MicroSampler::init(const SamplerInitInfo& inf)
 
 	ci.unnormalizedCoordinates = VK_FALSE;
 
+	// min/max
+	VkSamplerReductionModeCreateInfoEXT reductionCi = {};
+	if(inf.m_minMagFilter == SamplingFilter::MAX || inf.m_minMagFilter == SamplingFilter::MIN)
+	{
+		reductionCi.sType = VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT;
+		if(inf.m_minMagFilter == SamplingFilter::MAX)
+		{
+			reductionCi.reductionMode = VK_SAMPLER_REDUCTION_MODE_MAX_EXT;
+		}
+		else
+		{
+			ANKI_ASSERT(inf.m_minMagFilter == SamplingFilter::MIN);
+			reductionCi.reductionMode = VK_SAMPLER_REDUCTION_MODE_MIN_EXT;
+		}
+
+		ci.pNext = &reductionCi;
+	}
+
 	// Create
 	ANKI_VK_CHECK(vkCreateSampler(m_factory->m_gr->getDevice(), &ci, nullptr, &m_handle));
 	m_factory->m_gr->trySetVulkanHandleName(inf.getName(), VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT, m_handle);