Commit 49f01a53 by Geoff Lang Committed by Commit Bot

Vulkan: Add features to modify sampling parameters

Add features to optionally increase the LoD offset of all sampling operations or disable linear filtering. These can be used to compare performance without recompiling ANGLE. These features could be potentially implemented in the frontend it is more difficult because the features are not available at texture initialization time. Bug: b/167404532 Change-Id: Ifcf56fbcf130c24c54834737733bbffa5ade3959 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2411475 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent ed899835
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#include "platform/Feature.h" #include "platform/Feature.h"
#include <array>
namespace angle namespace angle
{ {
...@@ -378,6 +380,34 @@ struct FeaturesVk : FeatureSetBase ...@@ -378,6 +380,34 @@ struct FeaturesVk : FeatureSetBase
"Before passing an oldSwapchain to VkSwapchainCreateInfoKHR, wait for queue to be idle. " "Before passing an oldSwapchain to VkSwapchainCreateInfoKHR, wait for queue to be idle. "
"Works around a bug on platforms which destroy oldSwapchain in vkCreateSwapchainKHR.", "Works around a bug on platforms which destroy oldSwapchain in vkCreateSwapchainKHR.",
&members, "http://anglebug.com/5061"}; &members, "http://anglebug.com/5061"};
// Allow forcing an LOD offset on all sampling operations for performance comparisons. ANGLE is
// non-conformant if this feature is enabled.
std::array<angle::Feature, 4> forceTextureLODOffset = {
angle::Feature{"force_texture_lod_offset_1", angle::FeatureCategory::VulkanWorkarounds,
"Increase the minimum texture level-of-detail by 1 when sampling.",
&members},
angle::Feature{"force_texture_lod_offset_2", angle::FeatureCategory::VulkanWorkarounds,
"Increase the minimum texture level-of-detail by 2 when sampling.",
&members},
angle::Feature{"force_texture_lod_offset_3", angle::FeatureCategory::VulkanWorkarounds,
"Increase the minimum texture level-of-detail by 3 when sampling.",
&members},
angle::Feature{"force_texture_lod_offset_4", angle::FeatureCategory::VulkanWorkarounds,
"Increase the minimum texture level-of-detail by 4 when sampling.",
&members},
};
// Translate non-nearest filtering modes to nearest for all samplers for performance
// comparisons. ANGLE is non-conformant if this feature is enabled.
Feature forceNearestFiltering = {"force_nearest_filtering", FeatureCategory::VulkanWorkarounds,
"Force nearest filtering when sampling.", &members};
// Translate non-nearest mip filtering modes to nearest mip for all samplers for performance
// comparisons. ANGLE is non-conformant if this feature is enabled.
Feature forceNearestMipFiltering = {"force_nearest_mip_filtering",
FeatureCategory::VulkanWorkarounds,
"Force nearest mip filtering when sampling.", &members};
}; };
inline FeaturesVk::FeaturesVk() = default; inline FeaturesVk::FeaturesVk() = default;
......
...@@ -67,6 +67,34 @@ bool IsMipmapFiltered(GLenum minFilterMode) ...@@ -67,6 +67,34 @@ bool IsMipmapFiltered(GLenum minFilterMode)
} }
} }
GLenum ConvertToNearestFilterMode(GLenum filterMode)
{
switch (filterMode)
{
case GL_LINEAR:
return GL_NEAREST;
case GL_LINEAR_MIPMAP_NEAREST:
return GL_NEAREST_MIPMAP_NEAREST;
case GL_LINEAR_MIPMAP_LINEAR:
return GL_NEAREST_MIPMAP_LINEAR;
default:
return filterMode;
}
}
GLenum ConvertToNearestMipFilterMode(GLenum filterMode)
{
switch (filterMode)
{
case GL_LINEAR_MIPMAP_LINEAR:
return GL_LINEAR_MIPMAP_NEAREST;
case GL_NEAREST_MIPMAP_LINEAR:
return GL_NEAREST_MIPMAP_NEAREST;
default:
return filterMode;
}
}
SwizzleState::SwizzleState() SwizzleState::SwizzleState()
: swizzleRed(GL_RED), swizzleGreen(GL_GREEN), swizzleBlue(GL_BLUE), swizzleAlpha(GL_ALPHA) : swizzleRed(GL_RED), swizzleGreen(GL_GREEN), swizzleBlue(GL_BLUE), swizzleAlpha(GL_ALPHA)
{} {}
......
...@@ -52,6 +52,12 @@ constexpr GLuint kInitialMaxLevel = 1000; ...@@ -52,6 +52,12 @@ constexpr GLuint kInitialMaxLevel = 1000;
bool IsMipmapFiltered(GLenum minFilterMode); bool IsMipmapFiltered(GLenum minFilterMode);
// Convert a given filter mode to nearest filtering.
GLenum ConvertToNearestFilterMode(GLenum filterMode);
// Convert a given filter mode to nearest mip filtering.
GLenum ConvertToNearestMipFilterMode(GLenum filterMode);
struct ImageDesc final struct ImageDesc final
{ {
ImageDesc(); ImageDesc();
......
...@@ -1884,6 +1884,14 @@ void RendererVk::initFeatures(DisplayVk *displayVk, const ExtensionNameList &dev ...@@ -1884,6 +1884,14 @@ void RendererVk::initFeatures(DisplayVk *displayVk, const ExtensionNameList &dev
// Android mistakenly destroys the old swapchain when creating a new one. // Android mistakenly destroys the old swapchain when creating a new one.
ANGLE_FEATURE_CONDITION(&mFeatures, waitIdleBeforeSwapchainRecreation, IsAndroid() && isARM); ANGLE_FEATURE_CONDITION(&mFeatures, waitIdleBeforeSwapchainRecreation, IsAndroid() && isARM);
for (size_t lodOffsetFeatureIdx = 0;
lodOffsetFeatureIdx < mFeatures.forceTextureLODOffset.size(); lodOffsetFeatureIdx++)
{
ANGLE_FEATURE_CONDITION(&mFeatures, forceTextureLODOffset[lodOffsetFeatureIdx], false);
}
ANGLE_FEATURE_CONDITION(&mFeatures, forceNearestFiltering, false);
ANGLE_FEATURE_CONDITION(&mFeatures, forceNearestMipFiltering, false);
angle::PlatformMethods *platform = ANGLEPlatformCurrent(); angle::PlatformMethods *platform = ANGLEPlatformCurrent();
platform->overrideFeaturesVk(platform, &mFeatures); platform->overrideFeaturesVk(platform, &mFeatures);
......
...@@ -39,7 +39,7 @@ angle::Result SamplerVk::syncState(const gl::Context *context, const bool dirty) ...@@ -39,7 +39,7 @@ angle::Result SamplerVk::syncState(const gl::Context *context, const bool dirty)
mSampler.reset(); mSampler.reset();
} }
vk::SamplerDesc desc(mState, false, 0); vk::SamplerDesc desc(contextVk->getFeatures(), mState, false, 0);
ANGLE_TRY(renderer->getSamplerCache().getSampler(contextVk, desc, &mSampler)); ANGLE_TRY(renderer->getSamplerCache().getSampler(contextVk, desc, &mSampler));
return angle::Result::Continue; return angle::Result::Continue;
......
...@@ -1519,7 +1519,7 @@ angle::Result TextureVk::generateMipmapsWithCompute(ContextVk *contextVk) ...@@ -1519,7 +1519,7 @@ angle::Result TextureVk::generateMipmapsWithCompute(ContextVk *contextVk)
samplerState.setWrapR(GL_CLAMP_TO_EDGE); samplerState.setWrapR(GL_CLAMP_TO_EDGE);
vk::BindingPointer<vk::SamplerHelper> sampler; vk::BindingPointer<vk::SamplerHelper> sampler;
vk::SamplerDesc samplerDesc(samplerState, false, 0); vk::SamplerDesc samplerDesc(contextVk->getFeatures(), samplerState, false, 0);
ANGLE_TRY(renderer->getSamplerCache().getSampler(contextVk, samplerDesc, &sampler)); ANGLE_TRY(renderer->getSamplerCache().getSampler(contextVk, samplerDesc, &sampler));
// If the image has more levels than supported, generate as many mips as possible at a time. // If the image has more levels than supported, generate as many mips as possible at a time.
...@@ -2204,8 +2204,8 @@ angle::Result TextureVk::syncState(const gl::Context *context, ...@@ -2204,8 +2204,8 @@ angle::Result TextureVk::syncState(const gl::Context *context,
onStateChange(angle::SubjectMessage::SubjectChanged); onStateChange(angle::SubjectMessage::SubjectChanged);
} }
vk::SamplerDesc samplerDesc(mState.getSamplerState(), mState.isStencilMode(), vk::SamplerDesc samplerDesc(contextVk->getFeatures(), mState.getSamplerState(),
mImage->getExternalFormat()); mState.isStencilMode(), mImage->getExternalFormat());
ANGLE_TRY(renderer->getSamplerCache().getSampler(contextVk, samplerDesc, &mSampler)); ANGLE_TRY(renderer->getSamplerCache().getSampler(contextVk, samplerDesc, &mSampler));
return angle::Result::Continue; return angle::Result::Continue;
......
...@@ -2248,11 +2248,12 @@ SamplerDesc::SamplerDesc(const SamplerDesc &other) = default; ...@@ -2248,11 +2248,12 @@ SamplerDesc::SamplerDesc(const SamplerDesc &other) = default;
SamplerDesc &SamplerDesc::operator=(const SamplerDesc &rhs) = default; SamplerDesc &SamplerDesc::operator=(const SamplerDesc &rhs) = default;
SamplerDesc::SamplerDesc(const gl::SamplerState &samplerState, SamplerDesc::SamplerDesc(const angle::FeaturesVk &featuresVk,
const gl::SamplerState &samplerState,
bool stencilMode, bool stencilMode,
uint64_t externalFormat) uint64_t externalFormat)
{ {
update(samplerState, stencilMode, externalFormat); update(featuresVk, samplerState, stencilMode, externalFormat);
} }
void SamplerDesc::reset() void SamplerDesc::reset()
...@@ -2275,11 +2276,23 @@ void SamplerDesc::reset() ...@@ -2275,11 +2276,23 @@ void SamplerDesc::reset()
mReserved[2] = 0; mReserved[2] = 0;
} }
void SamplerDesc::update(const gl::SamplerState &samplerState, void SamplerDesc::update(const angle::FeaturesVk &featuresVk,
const gl::SamplerState &samplerState,
bool stencilMode, bool stencilMode,
uint64_t externalFormat) uint64_t externalFormat)
{ {
mMipLodBias = 0.0f; mMipLodBias = 0.0f;
for (size_t lodOffsetFeatureIdx = 0;
lodOffsetFeatureIdx < featuresVk.forceTextureLODOffset.size(); lodOffsetFeatureIdx++)
{
if (featuresVk.forceTextureLODOffset[lodOffsetFeatureIdx].enabled)
{
// Make sure only one forceTextureLODOffset feature is set.
ASSERT(mMipLodBias == 0.0f);
mMipLodBias = static_cast<float>(lodOffsetFeatureIdx + 1);
}
}
mMaxAnisotropy = samplerState.getMaxAnisotropy(); mMaxAnisotropy = samplerState.getMaxAnisotropy();
mMinLod = samplerState.getMinLod(); mMinLod = samplerState.getMinLod();
mMaxLod = samplerState.getMaxLod(); mMaxLod = samplerState.getMaxLod();
...@@ -2298,8 +2311,20 @@ void SamplerDesc::update(const gl::SamplerState &samplerState, ...@@ -2298,8 +2311,20 @@ void SamplerDesc::update(const gl::SamplerState &samplerState,
compareOp = VK_COMPARE_OP_ALWAYS; compareOp = VK_COMPARE_OP_ALWAYS;
} }
SetBitField(mMagFilter, gl_vk::GetFilter(samplerState.getMagFilter())); GLenum magFilter = samplerState.getMagFilter();
SetBitField(mMinFilter, gl_vk::GetFilter(samplerState.getMinFilter())); GLenum minFilter = samplerState.getMinFilter();
if (featuresVk.forceNearestFiltering.enabled)
{
magFilter = gl::ConvertToNearestFilterMode(magFilter);
minFilter = gl::ConvertToNearestFilterMode(minFilter);
}
if (featuresVk.forceNearestMipFiltering.enabled)
{
minFilter = gl::ConvertToNearestMipFilterMode(minFilter);
}
SetBitField(mMagFilter, gl_vk::GetFilter(magFilter));
SetBitField(mMinFilter, gl_vk::GetFilter(minFilter));
SetBitField(mMipmapMode, gl_vk::GetSamplerMipmapMode(samplerState.getMinFilter())); SetBitField(mMipmapMode, gl_vk::GetSamplerMipmapMode(samplerState.getMinFilter()));
SetBitField(mAddressModeU, gl_vk::GetSamplerAddressMode(samplerState.getWrapS())); SetBitField(mAddressModeU, gl_vk::GetSamplerAddressMode(samplerState.getWrapS()));
SetBitField(mAddressModeV, gl_vk::GetSamplerAddressMode(samplerState.getWrapT())); SetBitField(mAddressModeV, gl_vk::GetSamplerAddressMode(samplerState.getWrapT()));
...@@ -2307,7 +2332,7 @@ void SamplerDesc::update(const gl::SamplerState &samplerState, ...@@ -2307,7 +2332,7 @@ void SamplerDesc::update(const gl::SamplerState &samplerState,
SetBitField(mCompareEnabled, compareEnable); SetBitField(mCompareEnabled, compareEnable);
SetBitField(mCompareOp, compareOp); SetBitField(mCompareOp, compareOp);
if (!gl::IsMipmapFiltered(samplerState.getMinFilter())) if (!gl::IsMipmapFiltered(minFilter))
{ {
// Per the Vulkan spec, GL_NEAREST and GL_LINEAR do not map directly to Vulkan, so // Per the Vulkan spec, GL_NEAREST and GL_LINEAR do not map directly to Vulkan, so
// they must be emulated (See "Mapping of OpenGL to Vulkan filter modes") // they must be emulated (See "Mapping of OpenGL to Vulkan filter modes")
...@@ -2336,7 +2361,7 @@ angle::Result SamplerDesc::init(ContextVk *contextVk, vk::Sampler *sampler) cons ...@@ -2336,7 +2361,7 @@ angle::Result SamplerDesc::init(ContextVk *contextVk, vk::Sampler *sampler) cons
createInfo.addressModeU = static_cast<VkSamplerAddressMode>(mAddressModeU); createInfo.addressModeU = static_cast<VkSamplerAddressMode>(mAddressModeU);
createInfo.addressModeV = static_cast<VkSamplerAddressMode>(mAddressModeV); createInfo.addressModeV = static_cast<VkSamplerAddressMode>(mAddressModeV);
createInfo.addressModeW = static_cast<VkSamplerAddressMode>(mAddressModeW); createInfo.addressModeW = static_cast<VkSamplerAddressMode>(mAddressModeW);
createInfo.mipLodBias = 0.0f; createInfo.mipLodBias = mMipLodBias;
createInfo.anisotropyEnable = anisotropyEnable; createInfo.anisotropyEnable = anisotropyEnable;
createInfo.maxAnisotropy = mMaxAnisotropy; createInfo.maxAnisotropy = mMaxAnisotropy;
createInfo.compareEnable = mCompareEnabled ? VK_TRUE : VK_FALSE; createInfo.compareEnable = mCompareEnabled ? VK_TRUE : VK_FALSE;
......
...@@ -756,13 +756,19 @@ class SamplerDesc final ...@@ -756,13 +756,19 @@ class SamplerDesc final
{ {
public: public:
SamplerDesc(); SamplerDesc();
SamplerDesc(const gl::SamplerState &samplerState, bool stencilMode, uint64_t externalFormat); SamplerDesc(const angle::FeaturesVk &featuresVk,
const gl::SamplerState &samplerState,
bool stencilMode,
uint64_t externalFormat);
~SamplerDesc(); ~SamplerDesc();
SamplerDesc(const SamplerDesc &other); SamplerDesc(const SamplerDesc &other);
SamplerDesc &operator=(const SamplerDesc &rhs); SamplerDesc &operator=(const SamplerDesc &rhs);
void update(const gl::SamplerState &samplerState, bool stencilMode, uint64_t externalFormat); void update(const angle::FeaturesVk &featuresVk,
const gl::SamplerState &samplerState,
bool stencilMode,
uint64_t externalFormat);
void reset(); void reset();
angle::Result init(ContextVk *contextVk, vk::Sampler *sampler) const; angle::Result init(ContextVk *contextVk, vk::Sampler *sampler) const;
......
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