| // Copyright 2017 The Dawn & Tint Authors |
| // |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions are met: |
| // |
| // 1. Redistributions of source code must retain the above copyright notice, this |
| // list of conditions and the following disclaimer. |
| // |
| // 2. Redistributions in binary form must reproduce the above copyright notice, |
| // this list of conditions and the following disclaimer in the documentation |
| // and/or other materials provided with the distribution. |
| // |
| // 3. Neither the name of the copyright holder nor the names of its |
| // contributors may be used to endorse or promote products derived from |
| // this software without specific prior written permission. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
| // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| #include "dawn/native/Sampler.h" |
| |
| #include <cmath> |
| |
| #include "dawn/native/ChainUtils.h" |
| #include "dawn/native/Device.h" |
| #include "dawn/native/ObjectContentHasher.h" |
| #include "dawn/native/ValidationUtils_autogen.h" |
| |
| namespace dawn::native { |
| |
| namespace vulkan { |
| struct YCbCrVulkanDescriptor; |
| } |
| |
| MaybeError ValidateSamplerDescriptor(DeviceBase* device, const SamplerDescriptor* descriptor) { |
| DAWN_INVALID_IF(std::isnan(descriptor->lodMinClamp) || std::isnan(descriptor->lodMaxClamp), |
| "LOD clamp bounds [%f, %f] contain a NaN.", descriptor->lodMinClamp, |
| descriptor->lodMaxClamp); |
| |
| DAWN_INVALID_IF(descriptor->lodMinClamp < 0 || descriptor->lodMaxClamp < 0, |
| "LOD clamp bounds [%f, %f] contain contain a negative number.", |
| descriptor->lodMinClamp, descriptor->lodMaxClamp); |
| |
| DAWN_INVALID_IF(descriptor->lodMinClamp > descriptor->lodMaxClamp, |
| "LOD min clamp (%f) is larger than the max clamp (%f).", |
| descriptor->lodMinClamp, descriptor->lodMaxClamp); |
| |
| if (descriptor->maxAnisotropy > 1) { |
| DAWN_INVALID_IF(descriptor->minFilter != wgpu::FilterMode::Linear || |
| descriptor->magFilter != wgpu::FilterMode::Linear || |
| descriptor->mipmapFilter != wgpu::MipmapFilterMode::Linear, |
| "One of minFilter (%s), magFilter (%s) or mipmapFilter (%s) is not %s " |
| "while using anisotropic filter (maxAnisotropy is %f)", |
| descriptor->magFilter, descriptor->minFilter, descriptor->mipmapFilter, |
| wgpu::FilterMode::Linear, descriptor->maxAnisotropy); |
| } else if (descriptor->maxAnisotropy == 0u) { |
| return DAWN_VALIDATION_ERROR("Max anisotropy (%f) is less than 1.", |
| descriptor->maxAnisotropy); |
| } |
| |
| DAWN_TRY(ValidateFilterMode(descriptor->minFilter)); |
| DAWN_TRY(ValidateFilterMode(descriptor->magFilter)); |
| DAWN_TRY(ValidateMipmapFilterMode(descriptor->mipmapFilter)); |
| DAWN_TRY(ValidateAddressMode(descriptor->addressModeU)); |
| DAWN_TRY(ValidateAddressMode(descriptor->addressModeV)); |
| DAWN_TRY(ValidateAddressMode(descriptor->addressModeW)); |
| DAWN_TRY(ValidateCompareFunction(descriptor->compare)); |
| |
| UnpackedPtr<SamplerDescriptor> unpacked = Unpack(descriptor); |
| |
| if (unpacked.Get<vulkan::YCbCrVulkanDescriptor>()) { |
| DAWN_INVALID_IF(!device->HasFeature(Feature::YCbCrVulkanSamplers), "%s is not enabled.", |
| wgpu::FeatureName::YCbCrVulkanSamplers); |
| } |
| |
| return {}; |
| } |
| |
| // SamplerBase |
| |
| SamplerBase::SamplerBase(DeviceBase* device, |
| const SamplerDescriptor* descriptor, |
| ApiObjectBase::UntrackedByDeviceTag tag) |
| : ApiObjectBase(device, descriptor->label), |
| mAddressModeU(descriptor->addressModeU), |
| mAddressModeV(descriptor->addressModeV), |
| mAddressModeW(descriptor->addressModeW), |
| mMagFilter(descriptor->magFilter), |
| mMinFilter(descriptor->minFilter), |
| mMipmapFilter(descriptor->mipmapFilter), |
| mLodMinClamp(descriptor->lodMinClamp), |
| mLodMaxClamp(descriptor->lodMaxClamp), |
| mCompareFunction(descriptor->compare), |
| mMaxAnisotropy(descriptor->maxAnisotropy) { |
| if (Unpack(descriptor).Get<vulkan::YCbCrVulkanDescriptor>()) { |
| mIsYCbCr = true; |
| } |
| } |
| |
| SamplerBase::SamplerBase(DeviceBase* device, const SamplerDescriptor* descriptor) |
| : SamplerBase(device, descriptor, kUntrackedByDevice) { |
| GetObjectTrackingList()->Track(this); |
| } |
| |
| SamplerBase::SamplerBase(DeviceBase* device, ObjectBase::ErrorTag tag, const char* label) |
| : ApiObjectBase(device, tag, label) {} |
| |
| SamplerBase::~SamplerBase() = default; |
| |
| void SamplerBase::DestroyImpl() { |
| Uncache(); |
| } |
| |
| // static |
| Ref<SamplerBase> SamplerBase::MakeError(DeviceBase* device, const char* label) { |
| return AcquireRef(new SamplerBase(device, ObjectBase::kError, label)); |
| } |
| |
| ObjectType SamplerBase::GetType() const { |
| return ObjectType::Sampler; |
| } |
| |
| bool SamplerBase::IsComparison() const { |
| return mCompareFunction != wgpu::CompareFunction::Undefined; |
| } |
| |
| bool SamplerBase::IsFiltering() const { |
| return mMinFilter == wgpu::FilterMode::Linear || mMagFilter == wgpu::FilterMode::Linear || |
| mMipmapFilter == wgpu::MipmapFilterMode::Linear; |
| } |
| |
| bool SamplerBase::IsYCbCr() const { |
| return mIsYCbCr; |
| } |
| |
| size_t SamplerBase::ComputeContentHash() { |
| ObjectContentHasher recorder; |
| recorder.Record(mAddressModeU, mAddressModeV, mAddressModeW, mMagFilter, mMinFilter, |
| mMipmapFilter, mLodMinClamp, mLodMaxClamp, mCompareFunction, mMaxAnisotropy); |
| return recorder.GetContentHash(); |
| } |
| |
| bool SamplerBase::EqualityFunc::operator()(const SamplerBase* a, const SamplerBase* b) const { |
| if (a == b) { |
| return true; |
| } |
| |
| DAWN_ASSERT(!std::isnan(a->mLodMinClamp)); |
| DAWN_ASSERT(!std::isnan(b->mLodMinClamp)); |
| DAWN_ASSERT(!std::isnan(a->mLodMaxClamp)); |
| DAWN_ASSERT(!std::isnan(b->mLodMaxClamp)); |
| |
| return a->mAddressModeU == b->mAddressModeU && a->mAddressModeV == b->mAddressModeV && |
| 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->mMaxAnisotropy == b->mMaxAnisotropy; |
| } |
| |
| } // namespace dawn::native |