Add maxAnisotropy to GPUSamplerDescriptor

Adds some maxAnisotropy implementation.
Adds an end2end test, drawing a slanted plane with a texture of which each mipmap has a different color, with different maxAnisotropy values.
You can get an idea of what it does at https://jsfiddle.net/t64kpu81/85/
Needs further CTS.

Bug: dawn:568
Change-Id: I89ac56d8cf0fbb655358bf6effa016ddc1f8426f
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/35143
Commit-Queue: Kai Ninomiya <kainino@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
This commit is contained in:
shrekshao
2020-12-24 03:11:17 +00:00
committed by Commit Bot service account
parent c08276644f
commit f8c5e4ab74
13 changed files with 553 additions and 29 deletions

View File

@@ -20,6 +20,12 @@
#include <cmath>
namespace {
uint16_t GetClampedMaxAnisotropy(uint16_t value) {
return value >= 1u ? value : 1u;
}
} // anonymous namespace
namespace dawn_native {
MaybeError ValidateSamplerDescriptor(DeviceBase*, const SamplerDescriptor* descriptor) {
@@ -40,6 +46,16 @@ namespace dawn_native {
"Min lod clamp value cannot greater than max lod clamp value");
}
if (descriptor->maxAnisotropy > 1) {
if (descriptor->minFilter != wgpu::FilterMode::Linear ||
descriptor->magFilter != wgpu::FilterMode::Linear ||
descriptor->mipmapFilter != wgpu::FilterMode::Linear) {
return DAWN_VALIDATION_ERROR(
"min, mag, and mipmap filter should be linear when using anisotropic "
"filtering");
}
}
DAWN_TRY(ValidateFilterMode(descriptor->minFilter));
DAWN_TRY(ValidateFilterMode(descriptor->magFilter));
DAWN_TRY(ValidateFilterMode(descriptor->mipmapFilter));
@@ -62,7 +78,8 @@ namespace dawn_native {
mMipmapFilter(descriptor->mipmapFilter),
mLodMinClamp(descriptor->lodMinClamp),
mLodMaxClamp(descriptor->lodMaxClamp),
mCompareFunction(descriptor->compare) {
mCompareFunction(descriptor->compare),
mMaxAnisotropy(GetClampedMaxAnisotropy(descriptor->maxAnisotropy)) {
}
SamplerBase::SamplerBase(DeviceBase* device, ObjectBase::ErrorTag tag)
@@ -87,7 +104,8 @@ namespace dawn_native {
size_t SamplerBase::ComputeContentHash() {
ObjectContentHasher recorder;
recorder.Record(mAddressModeU, mAddressModeV, mAddressModeW, mMagFilter, mMinFilter,
mMipmapFilter, mLodMinClamp, mLodMaxClamp, mCompareFunction);
mMipmapFilter, mLodMinClamp, mLodMaxClamp, mCompareFunction,
mMaxAnisotropy);
return recorder.GetContentHash();
}
@@ -105,7 +123,7 @@ namespace dawn_native {
a->mAddressModeW == b->mAddressModeW && a->mMagFilter == b->mMagFilter &&
a->mMinFilter == b->mMinFilter && a->mMipmapFilter == b->mMipmapFilter &&
a->mLodMinClamp == b->mLodMinClamp && a->mLodMaxClamp == b->mLodMaxClamp &&
a->mCompareFunction == b->mCompareFunction;
a->mCompareFunction == b->mCompareFunction && a->mMaxAnisotropy == b->mMaxAnisotropy;
}
} // namespace dawn_native

View File

@@ -42,6 +42,10 @@ namespace dawn_native {
bool operator()(const SamplerBase* a, const SamplerBase* b) const;
};
uint16_t GetMaxAnisotropy() const {
return mMaxAnisotropy;
}
private:
SamplerBase(DeviceBase* device, ObjectBase::ErrorTag tag);
@@ -55,6 +59,7 @@ namespace dawn_native {
float mLodMinClamp;
float mLodMaxClamp;
wgpu::CompareFunction mCompareFunction;
uint16_t mMaxAnisotropy;
};
} // namespace dawn_native

View File

@@ -69,13 +69,21 @@ namespace dawn_native { namespace d3d12 {
? D3D12_FILTER_REDUCTION_TYPE_STANDARD
: D3D12_FILTER_REDUCTION_TYPE_COMPARISON;
mSamplerDesc.Filter =
D3D12_ENCODE_BASIC_FILTER(minFilter, magFilter, mipmapFilter, reduction);
// https://docs.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_sampler_desc
mSamplerDesc.MaxAnisotropy = std::min<uint16_t>(GetMaxAnisotropy(), 16u);
if (mSamplerDesc.MaxAnisotropy > 1) {
mSamplerDesc.Filter = D3D12_ENCODE_ANISOTROPIC_FILTER(reduction);
} else {
mSamplerDesc.Filter =
D3D12_ENCODE_BASIC_FILTER(minFilter, magFilter, mipmapFilter, reduction);
}
mSamplerDesc.AddressU = AddressMode(descriptor->addressModeU);
mSamplerDesc.AddressV = AddressMode(descriptor->addressModeV);
mSamplerDesc.AddressW = AddressMode(descriptor->addressModeW);
mSamplerDesc.MipLODBias = 0.f;
mSamplerDesc.MaxAnisotropy = 1;
if (descriptor->compare != wgpu::CompareFunction::Undefined) {
mSamplerDesc.ComparisonFunc = ToD3D12ComparisonFunc(descriptor->compare);
} else {

View File

@@ -75,6 +75,8 @@ namespace dawn_native { namespace metal {
mtlDesc.lodMinClamp = descriptor->lodMinClamp;
mtlDesc.lodMaxClamp = descriptor->lodMaxClamp;
// https://developer.apple.com/documentation/metal/mtlsamplerdescriptor/1516164-maxanisotropy
mtlDesc.maxAnisotropy = std::min<uint16_t>(GetMaxAnisotropy(), 16u);
if (descriptor->compare != wgpu::CompareFunction::Undefined) {
// Sampler compare is unsupported before A9, which we validate in

View File

@@ -82,7 +82,8 @@ namespace dawn_native { namespace opengl {
void Sampler::SetupGLSampler(GLuint sampler,
const SamplerDescriptor* descriptor,
bool forceNearest) {
const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
Device* device = ToBackend(GetDevice());
const OpenGLFunctions& gl = device->gl;
if (forceNearest) {
gl.SamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -105,6 +106,11 @@ namespace dawn_native { namespace opengl {
gl.SamplerParameteri(sampler, GL_TEXTURE_COMPARE_FUNC,
ToOpenGLCompareFunction(descriptor->compare));
}
if (gl.IsAtLeastGL(4, 6) ||
gl.IsGLExtensionSupported("GL_EXT_texture_filter_anisotropic")) {
gl.SamplerParameterf(sampler, GL_TEXTURE_MAX_ANISOTROPY, GetMaxAnisotropy());
}
}
GLuint Sampler::GetFilteringHandle() const {

View File

@@ -316,6 +316,10 @@ namespace dawn_native { namespace vulkan {
mComputeSubgroupSize = FindComputeSubgroupSize();
}
if (mDeviceInfo.features.samplerAnisotropy == VK_TRUE) {
usedKnobs.features.samplerAnisotropy = VK_TRUE;
}
if (IsExtensionEnabled(Extension::TextureCompressionBC)) {
ASSERT(ToBackend(GetAdapter())->GetDeviceInfo().features.textureCompressionBC ==
VK_TRUE);

View File

@@ -71,8 +71,6 @@ namespace dawn_native { namespace vulkan {
createInfo.addressModeV = VulkanSamplerAddressMode(descriptor->addressModeV);
createInfo.addressModeW = VulkanSamplerAddressMode(descriptor->addressModeW);
createInfo.mipLodBias = 0.0f;
createInfo.anisotropyEnable = VK_FALSE;
createInfo.maxAnisotropy = 1.0f;
if (descriptor->compare != wgpu::CompareFunction::Undefined) {
createInfo.compareOp = ToVulkanCompareOp(descriptor->compare);
createInfo.compareEnable = VK_TRUE;
@@ -86,6 +84,18 @@ namespace dawn_native { namespace vulkan {
createInfo.unnormalizedCoordinates = VK_FALSE;
Device* device = ToBackend(GetDevice());
uint16_t maxAnisotropy = GetMaxAnisotropy();
if (device->GetDeviceInfo().features.samplerAnisotropy == VK_TRUE && maxAnisotropy > 1) {
createInfo.anisotropyEnable = VK_TRUE;
// https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkSamplerCreateInfo.html
createInfo.maxAnisotropy =
std::min(static_cast<float>(maxAnisotropy),
device->GetDeviceInfo().properties.limits.maxSamplerAnisotropy);
} else {
createInfo.anisotropyEnable = VK_FALSE;
createInfo.maxAnisotropy = 1;
}
return CheckVkSuccess(
device->fn.CreateSampler(device->GetVkDevice(), &createInfo, nullptr, &*mHandle),
"CreateSampler");