Use a finite maxSamplerLodBias limit
We previously set this device limit to infinity to avoid having to
clamp the sum of the sampler and shader provided bias values to the
[-maxSamplerLodBias, maxSamplerLodBias] range. Unfortunately infinity
is not supported/allowed by JSON and the android.graphics.cts.VulkanFeaturesTest
tests which parse the output of the vkjson tool produce a failure.
This change works around it by setting maxSamplerLodBias to a finite
value (15, which is very common according to https://vulkan.gpuinfo.org/),
and performing the clamping required by Vulkan 1.1.117 section 15.6.7.
Fortunately this cost only has to be incurred when an optional Bias
operand is used in the SPIR-V image sampling instruction. When an Lod
operand is used, which is mutually exclusive with Bias because the
former is for explicit-lod instructions and the latter for implicit-lod,
no clamping is required because the explicit LOD is not part of this
clamping equation and the sampler LOD bias must already be clamped as
specified by the spec: "The absolute value of mipLodBias must be less
than or equal to VkPhysicalDeviceLimits::maxSamplerLodBias".
Bug: b/138670766
Change-Id: Iebd6a1fef1c993ec86ac8cc38f8d9a992ba9bc47
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/34510
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Pipeline/SamplerCore.cpp b/src/Pipeline/SamplerCore.cpp
index 85c3783..d832bcb 100644
--- a/src/Pipeline/SamplerCore.cpp
+++ b/src/Pipeline/SamplerCore.cpp
@@ -92,14 +92,21 @@
computeLod3D(texture, sampler, lod, uuuu, vvvv, wwww, dsx, dsy, function);
}
+ Float bias = *Pointer<Float>(sampler + OFFSET(vk::Sampler, mipLodBias));
+
if(function == Bias)
{
- lod += lodOrBias;
+ // Add SPIR-V Bias operand to the sampler provided bias and clamp to maxSamplerLodBias limit.
+ bias = Min(Max(bias + lodOrBias, -vk::MAX_SAMPLER_LOD_BIAS), vk::MAX_SAMPLER_LOD_BIAS);
}
+
+ lod += bias;
}
else if(function == Lod)
{
- lod = lodOrBias;
+ // Vulkan 1.1: "The absolute value of mipLodBias must be less than or equal to VkPhysicalDeviceLimits::maxSamplerLodBias"
+ // Hence no explicit clamping to maxSamplerLodBias is required in this case.
+ lod = lodOrBias + *Pointer<Float>(sampler + OFFSET(vk::Sampler, mipLodBias));
}
else if(function == Fetch)
{
@@ -114,8 +121,6 @@
if(function != Base && function != Fetch && function != Gather)
{
- lod += *Pointer<Float>(sampler + OFFSET(vk::Sampler, mipLodBias));
-
if(function == Query)
{
c.y = Float4(lod); // Unclamped LOD.
diff --git a/src/Vulkan/VkConfig.h b/src/Vulkan/VkConfig.h
index 157f34e..8d0b57d 100644
--- a/src/Vulkan/VkConfig.h
+++ b/src/Vulkan/VkConfig.h
@@ -54,6 +54,7 @@
MAX_IMAGE_LEVELS_3D = 11,
MAX_IMAGE_LEVELS_CUBE = 14,
MAX_IMAGE_ARRAY_LAYERS = 2048,
+ MAX_SAMPLER_LOD_BIAS = 15,
};
enum
diff --git a/src/Vulkan/VkPhysicalDevice.cpp b/src/Vulkan/VkPhysicalDevice.cpp
index 323d644..14476a5 100644
--- a/src/Vulkan/VkPhysicalDevice.cpp
+++ b/src/Vulkan/VkPhysicalDevice.cpp
@@ -205,7 +205,7 @@
4, // mipmapPrecisionBits
UINT32_MAX, // maxDrawIndexedIndexValue
UINT32_MAX, // maxDrawIndirectCount
- std::numeric_limits<float>::infinity(), // maxSamplerLodBias (no clamping takes place)
+ vk::MAX_SAMPLER_LOD_BIAS, // maxSamplerLodBias
16, // maxSamplerAnisotropy
16, // maxViewports
{ 4096, 4096 }, // maxViewportDimensions[2]