diff --git a/cocos/asset/assets/texture-base.ts b/cocos/asset/assets/texture-base.ts index 77f7aa36753..b571ff9651d 100644 --- a/cocos/asset/assets/texture-base.ts +++ b/cocos/asset/assets/texture-base.ts @@ -243,6 +243,7 @@ export class TextureBase extends Asset { * @param anisotropy @en The anisotropy to be set. @zh 待设置的各向异性数值。 */ public setAnisotropy (anisotropy: number): void { + anisotropy = Math.min(anisotropy, 16); this._anisotropy = anisotropy; this._samplerInfo$.maxAnisotropy = anisotropy; diff --git a/cocos/gfx/base/states/sampler.ts b/cocos/gfx/base/states/sampler.ts index 1469c22e9c6..e7ef587ba8b 100644 --- a/cocos/gfx/base/states/sampler.ts +++ b/cocos/gfx/base/states/sampler.ts @@ -48,21 +48,21 @@ export class Sampler extends GFXObject { hash |= ((info.addressU as number) << 6); hash |= ((info.addressV as number) << 8); hash |= ((info.addressW as number) << 10); - hash |= (info.maxAnisotropy << 12); - hash |= ((info.cmpFunc as number) << 16); + hash |= (Math.min(info.maxAnisotropy, 16) << 12); + hash |= ((info.cmpFunc as number) << 17); return hash; } static unpackFromHash (hash: number): SamplerInfo { const info = new SamplerInfo(); - info.minFilter = (hash & ((1 << 2) - 1)) >> 0; - info.magFilter = (hash & ((1 << 2) - 1)) >> 2; - info.mipFilter = (hash & ((1 << 2) - 1)) >> 4; - info.addressU = (hash & ((1 << 2) - 1)) >> 6; - info.addressV = (hash & ((1 << 2) - 1)) >> 8; - info.addressW = (hash & ((1 << 2) - 1)) >> 10; - info.maxAnisotropy = (hash & ((1 << 4) - 1)) >> 12; - info.cmpFunc = (hash & ((1 << 3) - 1)) >> 16; + info.minFilter = hash & 3; + info.magFilter = (hash >> 2) & 3; + info.mipFilter = (hash >> 4) & 3; + info.addressU = (hash >> 6) & 3; + info.addressV = (hash >> 8) & 3; + info.addressW = (hash >> 10) & 3; + info.maxAnisotropy = (hash >> 12) & 31; + info.cmpFunc = (hash >> 17) & 7; return info; } } diff --git a/native/CMakeLists.txt b/native/CMakeLists.txt index c61b80bb4b9..a7fb148f195 100644 --- a/native/CMakeLists.txt +++ b/native/CMakeLists.txt @@ -1212,6 +1212,7 @@ cocos_source_files( cocos/renderer/gfx-base/GFXQueryPool.h cocos/renderer/gfx-base/GFXRenderPass.cpp cocos/renderer/gfx-base/GFXRenderPass.h + cocos/renderer/gfx-base/GFXSamplerUtils.h cocos/renderer/gfx-base/GFXShader.cpp cocos/renderer/gfx-base/GFXShader.h cocos/renderer/gfx-base/GFXSwapchain.cpp diff --git a/native/cocos/renderer/gfx-base/GFXDef.cpp b/native/cocos/renderer/gfx-base/GFXDef.cpp index 8a89def0486..02703daec9c 100644 --- a/native/cocos/renderer/gfx-base/GFXDef.cpp +++ b/native/cocos/renderer/gfx-base/GFXDef.cpp @@ -28,6 +28,7 @@ #include "GFXDef.h" #include "GFXRenderPass.h" +#include "GFXSamplerUtils.h" #include "GFXTexture.h" namespace cc { @@ -203,18 +204,7 @@ bool operator==(const BufferInfo &lhs, const BufferInfo &rhs) { template <> ccstd::hash_t Hasher::operator()(const SamplerInfo &info) const { - // return quickHashTrivialStruct(&info); - - // the hash may be used to reconstruct the original struct - auto hash = static_cast(info.minFilter); - hash |= static_cast(info.magFilter) << 2; - hash |= static_cast(info.mipFilter) << 4; - hash |= static_cast(info.addressU) << 6; - hash |= static_cast(info.addressV) << 8; - hash |= static_cast(info.addressW) << 10; - hash |= static_cast(info.maxAnisotropy) << 12; - hash |= static_cast(info.cmpFunc) << 16; - return static_cast(hash); + return static_cast(compressSamplerInfo(info)); } bool operator==(const SamplerInfo &lhs, const SamplerInfo &rhs) { diff --git a/native/cocos/renderer/gfx-base/GFXSamplerUtils.h b/native/cocos/renderer/gfx-base/GFXSamplerUtils.h new file mode 100644 index 00000000000..4d17faff9eb --- /dev/null +++ b/native/cocos/renderer/gfx-base/GFXSamplerUtils.h @@ -0,0 +1,66 @@ +/**************************************************************************** + Copyright (c) 2019-2024 Xiamen Yaji Software Co., Ltd. + + http://www.cocos.com + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +****************************************************************************/ + +#pragma once +#include "cocos/renderer/gfx-base/GFXDef-common.h" + +namespace cc { +namespace gfx { + +constexpr uint32_t compressSamplerInfo(const SamplerInfo &info) noexcept { + CC_ASSERT(static_cast(info.minFilter) < (1 << 2)); + CC_ASSERT(static_cast(info.magFilter) < (1 << 2)); + CC_ASSERT(static_cast(info.mipFilter) < (1 << 2)); + CC_ASSERT(static_cast(info.addressU) < (1 << 2)); + CC_ASSERT(static_cast(info.addressV) < (1 << 2)); + CC_ASSERT(static_cast(info.addressW) < (1 << 2)); + CC_ASSERT(info.maxAnisotropy <= 16); + CC_ASSERT(static_cast(info.cmpFunc) < (1 << 3)); + + auto packed = static_cast(info.minFilter); + packed |= static_cast(info.magFilter) << 2; + packed |= static_cast(info.mipFilter) << 4; + packed |= static_cast(info.addressU) << 6; + packed |= static_cast(info.addressV) << 8; + packed |= static_cast(info.addressW) << 10; + packed |= static_cast(info.maxAnisotropy) << 12; + packed |= static_cast(info.cmpFunc) << 17; + return packed; +} + +constexpr SamplerInfo uncompressSamplerInfo(const uint32_t packed) noexcept { + SamplerInfo info{}; + info.minFilter = static_cast(packed & ((1 << 2) - 1)); + info.magFilter = static_cast((packed >> 2) & ((1 << 2) - 1)); + info.mipFilter = static_cast((packed >> 4) & ((1 << 2) - 1)); + info.addressU = static_cast
((packed >> 6) & ((1 << 2) - 1)); + info.addressV = static_cast
((packed >> 8) & ((1 << 2) - 1)); + info.addressW = static_cast
((packed >> 10) & ((1 << 2) - 1)); + info.maxAnisotropy = (packed >> 12) & ((1 << 5) - 1); + info.cmpFunc = static_cast((packed >> 17) & ((1 << 3) - 1)); + return info; +} + +} // namespace gfx +} // namespace cc diff --git a/native/cocos/renderer/gfx-base/states/GFXSampler.cpp b/native/cocos/renderer/gfx-base/states/GFXSampler.cpp index 1b3d09a4387..2ce721d45ee 100644 --- a/native/cocos/renderer/gfx-base/states/GFXSampler.cpp +++ b/native/cocos/renderer/gfx-base/states/GFXSampler.cpp @@ -23,6 +23,7 @@ ****************************************************************************/ #include "GFXSampler.h" +#include "../GFXSamplerUtils.h" namespace cc { namespace gfx { @@ -38,17 +39,59 @@ ccstd::hash_t Sampler::computeHash(const SamplerInfo &info) { } SamplerInfo Sampler::unpackFromHash(ccstd::hash_t hash) { - SamplerInfo info; - info.minFilter = static_cast((hash & ((1 << 2) - 1)) >> 0); - info.magFilter = static_cast((hash & ((1 << 2) - 1)) >> 2); - info.mipFilter = static_cast((hash & ((1 << 2) - 1)) >> 4); - info.addressU = static_cast
((hash & ((1 << 2) - 1)) >> 6); - info.addressV = static_cast
((hash & ((1 << 2) - 1)) >> 8); - info.addressW = static_cast
((hash & ((1 << 2) - 1)) >> 10); - info.maxAnisotropy = (hash & ((1 << 4) - 1)) >> 12; - info.cmpFunc = static_cast((hash & ((1 << 3) - 1)) >> 16); - return info; + return uncompressSamplerInfo(hash); } +namespace { + +constexpr bool testSamplerInfo(const SamplerInfo &info) { + const uint32_t packed = compressSamplerInfo(info); + const SamplerInfo unpacked = uncompressSamplerInfo(packed); + + return info.minFilter == unpacked.minFilter && + info.magFilter == unpacked.magFilter && + info.mipFilter == unpacked.mipFilter && + info.addressU == unpacked.addressU && + info.addressV == unpacked.addressV && + info.addressW == unpacked.addressW && + info.maxAnisotropy == unpacked.maxAnisotropy && + info.cmpFunc == unpacked.cmpFunc; +} + +static_assert(testSamplerInfo(SamplerInfo{ + Filter::NONE, + Filter::NONE, + Filter::NONE, + Address::WRAP, + Address::WRAP, + Address::WRAP, + 0U, + ComparisonFunc::NEVER, +})); + +static_assert(testSamplerInfo(SamplerInfo{ + Filter::ANISOTROPIC, + Filter::ANISOTROPIC, + Filter::ANISOTROPIC, + Address::BORDER, + Address::BORDER, + Address::BORDER, + 16U, + ComparisonFunc::ALWAYS, +})); + +static_assert(testSamplerInfo(SamplerInfo{ + Filter::POINT, + Filter::LINEAR, + Filter::ANISOTROPIC, + Address::MIRROR, + Address::CLAMP, + Address::BORDER, + 15U, + ComparisonFunc::GREATER_EQUAL, +})); + +} // namespace + } // namespace gfx } // namespace cc