Optimize OpImageFetch for single-level mipmaps
The initial implementation of single-level mipmap LOD optimization left
out Fetch operations due to causing test failures. The root cause is
that minLod == maxLod is being used to indicate during sampling routine
generation that the image has only a single mipmap level, but this is
also true when we have no sampler object, which leaves these fields
both initialized at 0.
This change changes their initial value to [-1000, 1000]. While any
arbitrary non-equal values could be used, this is inspired by OpenGL's
defaults for GL_TEXTURE_MIN_LOD and GL_TEXTURE_MAX_LOD.
We then set them both to 0 for Fetch operations if the image view has a
single level.
Bug: b/151263485
Change-Id: I2ab565f5126cc8f8137f051704a6350853396e50
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/56112
Tested-by: Nicolas Capens <nicolascapens@google.com>
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Sean Risser <srisser@google.com>
diff --git a/src/Device/Sampler.hpp b/src/Device/Sampler.hpp
index 712977d..e42fb30 100644
--- a/src/Device/Sampler.hpp
+++ b/src/Device/Sampler.hpp
@@ -111,8 +111,8 @@
float mipLodBias = 0.0f;
float maxAnisotropy = 0.0f;
- float minLod = 0.0f;
- float maxLod = 0.0f;
+ float minLod = -1000.0f;
+ float maxLod = 1000.0f;
bool is1D() const
{
diff --git a/src/Pipeline/SamplerCore.cpp b/src/Pipeline/SamplerCore.cpp
index 2239ca9..655ec3f 100644
--- a/src/Pipeline/SamplerCore.cpp
+++ b/src/Pipeline/SamplerCore.cpp
@@ -57,7 +57,7 @@
// Determine if we can skip the LOD computation. This is the case when the mipmap has only one level, except for LOD query,
// where we have to return the computed value. Anisotropic filtering requires computing the anisotropy factor even for a single mipmap level.
bool singleMipLevel = (state.minLod == state.maxLod);
- bool requiresLodComputation = (function == Query) || (function == Fetch) || (state.textureFilter == FILTER_ANISOTROPIC);
+ bool requiresLodComputation = (function == Query) || (state.textureFilter == FILTER_ANISOTROPIC);
bool skipLodComputation = singleMipLevel && !requiresLodComputation;
if(skipLodComputation)
diff --git a/src/Pipeline/SpirvShaderSampling.cpp b/src/Pipeline/SpirvShaderSampling.cpp
index beca443..fd6dc70 100644
--- a/src/Pipeline/SpirvShaderSampling.cpp
+++ b/src/Pipeline/SpirvShaderSampling.cpp
@@ -93,12 +93,21 @@
samplerState.maxLod = 0.0f;
}
}
- else
+ else // Fetch
{
+ ASSERT(samplerMethod == Fetch);
+
// OpImageFetch does not take a sampler descriptor, but for VK_EXT_image_robustness
// requires replacing invalid texels with zero.
// TODO(b/162327166): Only perform bounds checks when VK_EXT_image_robustness is enabled.
samplerState.border = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
+
+ // If there's a single mip level we can skip LOD computation.
+ if(imageViewState.singleMipLevel)
+ {
+ samplerState.minLod = 0.0f;
+ samplerState.maxLod = 0.0f;
+ }
}
return emitSamplerRoutine(instruction, samplerState);