Only perform LOD computation when it is necessary

If an image has a single mip level, and filtering isn't LOD dependent, as is the case when using FILTER_MIN_POINT_MAG_LINEAR or FILTER_MIN_LINEAR_MAG_POINT, LOD computation is not necessary in order to perform image sampling and can be bypassed entirely. Bug: b/179889245 Change-Id: Ic69fe0c45211ccbb66c88c502c2dba1c50630aa7 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/52688 Presubmit-Ready: Alexis Hétu <sugoi@google.com> Kokoro-Result: kokoro <noreply+kokoro@google.com> Tested-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com> Commit-Queue: Alexis Hétu <sugoi@google.com>
parent 4eb079f7
......@@ -54,7 +54,15 @@ Vector4f SamplerCore::sampleTexture(Pointer<Byte> &texture, Float4 uvwa[4], Floa
w = As<Float4>(face);
}
if(function == Implicit || function == Bias || function == Grad || function == Query)
bool singleMipLevel = (state.minLod == state.maxLod) && (function != Query) && (function != Fetch);
// We can't skip the LOD computation for LOD query, where we have to return the proper value
if(singleMipLevel)
{
// Skip costly LOD computation if there's only 1 possible outcome
lod = state.minLod;
}
else if(function == Implicit || function == Bias || function == Grad || function == Query)
{
if(state.is1D())
{
......@@ -108,8 +116,11 @@ Vector4f SamplerCore::sampleTexture(Pointer<Byte> &texture, Float4 uvwa[4], Floa
c.y = Float4(lod); // Unclamped LOD.
}
lod = Max(lod, state.minLod);
lod = Min(lod, state.maxLod);
if (!singleMipLevel)
{
lod = Max(lod, state.minLod);
lod = Min(lod, state.maxLod);
}
if(function == Query)
{
......
......@@ -78,6 +78,20 @@ SpirvShader::ImageSampler *SpirvShader::getImageSampler(const vk::Device *device
samplerState.maxAnisotropy = vkSamplerState->maxAnisotropy;
samplerState.minLod = vkSamplerState->minLod;
samplerState.maxLod = vkSamplerState->maxLod;
// If there's a single mip level and filtering doesn't depend on the LOD level,
// the sampler will need to compute the LOD to produce the proper result.
// Otherwise, it can be ignored.
// We can skip the LOD computation for all modes, except LOD query,
// where we have to return the proper value even if nothing else requires it.
if(imageViewState.singleMipLevel &&
(samplerState.textureFilter != FILTER_MIN_POINT_MAG_LINEAR) &&
(samplerState.textureFilter != FILTER_MIN_LINEAR_MAG_POINT) &&
(samplerMethod != Query))
{
samplerState.minLod = 0.0f;
samplerState.maxLod = 0.0f;
}
}
else
{
......
......@@ -87,14 +87,14 @@ Identifier::Identifier(const VkImageViewCreateInfo *pCreateInfo)
const Image *sampledImage = image->getSampledImage(viewFormat);
vk::Format samplingFormat = (image == sampledImage) ? viewFormat : sampledImage->getFormat().getAspectFormat(subresource.aspectMask);
pack({ pCreateInfo->viewType, samplingFormat, ResolveComponentMapping(pCreateInfo->components, viewFormat) });
pack({ pCreateInfo->viewType, samplingFormat, ResolveComponentMapping(pCreateInfo->components, viewFormat), subresource.levelCount <= 1u });
}
Identifier::Identifier(VkFormat bufferFormat)
{
static_assert(vk::VK_IMAGE_VIEW_TYPE_END_RANGE == 6, "VkImageViewType does not allow using 7 to indicate buffer view");
constexpr VkComponentMapping identityMapping = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
pack({ VK_IMAGE_VIEW_TYPE_1D, bufferFormat, ResolveComponentMapping(identityMapping, bufferFormat) });
pack({ VK_IMAGE_VIEW_TYPE_1D, bufferFormat, ResolveComponentMapping(identityMapping, bufferFormat), true });
}
void Identifier::pack(const State &state)
......@@ -105,6 +105,7 @@ void Identifier::pack(const State &state)
g = static_cast<uint32_t>(state.mapping.g);
b = static_cast<uint32_t>(state.mapping.b);
a = static_cast<uint32_t>(state.mapping.a);
singleMipLevel = state.singleMipLevel;
}
Identifier::State Identifier::getState() const
......@@ -114,7 +115,8 @@ Identifier::State Identifier::getState() const
{ static_cast<VkComponentSwizzle>(r),
static_cast<VkComponentSwizzle>(g),
static_cast<VkComponentSwizzle>(b),
static_cast<VkComponentSwizzle>(a) } };
static_cast<VkComponentSwizzle>(a) },
static_cast<bool>(singleMipLevel) };
}
ImageView::ImageView(const VkImageViewCreateInfo *pCreateInfo, void *mem, const vk::SamplerYcbcrConversion *ycbcrConversion)
......
......@@ -53,6 +53,7 @@ union Identifier
VkImageViewType imageViewType;
VkFormat format;
VkComponentMapping mapping;
bool singleMipLevel;
};
State getState() const;
......@@ -68,6 +69,7 @@ private:
uint32_t g : 3;
uint32_t b : 3;
uint32_t a : 3;
uint32_t singleMipLevel : 1;
};
uint32_t id = 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment