diff --git a/Graphics/GraphicsAccessories/interface/GraphicsTypesOutputInserters.hpp b/Graphics/GraphicsAccessories/interface/GraphicsTypesOutputInserters.hpp index dc748ca3a..690e3c752 100644 --- a/Graphics/GraphicsAccessories/interface/GraphicsTypesOutputInserters.hpp +++ b/Graphics/GraphicsAccessories/interface/GraphicsTypesOutputInserters.hpp @@ -70,6 +70,7 @@ DEFINE_TYPE_PRINTER(ShaderDesc, GetShaderDescString) DEFINE_TYPE_PRINTER(ShaderCodeBufferDesc, GetShaderCodeBufferDescString) DEFINE_TYPE_PRINTER(ShaderCodeVariableDesc, GetShaderCodeVariableDescString) DEFINE_TYPE_PRINTER(LayoutElement, GetLayoutElementString) +DEFINE_TYPE_PRINTER(TextureComponentMapping, GetTextureComponentMappingString) #undef DEFINE_TYPE_PRINTER } // namespace Diligent diff --git a/Graphics/GraphicsEngine/interface/TextureView.h b/Graphics/GraphicsEngine/interface/TextureView.h index 1c86bb58f..cee78bdcf 100644 --- a/Graphics/GraphicsEngine/interface/TextureView.h +++ b/Graphics/GraphicsEngine/interface/TextureView.h @@ -146,10 +146,10 @@ struct TextureComponentMapping constexpr bool operator==(const TextureComponentMapping& RHS) const { - return R == RHS.R && - G == RHS.G && - B == RHS.B && - A == RHS.A; + return (R == RHS.R || (R == TEXTURE_COMPONENT_SWIZZLE_IDENTITY && RHS.R == TEXTURE_COMPONENT_SWIZZLE_R) || (R == TEXTURE_COMPONENT_SWIZZLE_R && RHS.R == TEXTURE_COMPONENT_SWIZZLE_IDENTITY)) && + (G == RHS.G || (G == TEXTURE_COMPONENT_SWIZZLE_IDENTITY && RHS.G == TEXTURE_COMPONENT_SWIZZLE_G) || (G == TEXTURE_COMPONENT_SWIZZLE_G && RHS.G == TEXTURE_COMPONENT_SWIZZLE_IDENTITY)) && + (B == RHS.B || (B == TEXTURE_COMPONENT_SWIZZLE_IDENTITY && RHS.B == TEXTURE_COMPONENT_SWIZZLE_B) || (B == TEXTURE_COMPONENT_SWIZZLE_B && RHS.B == TEXTURE_COMPONENT_SWIZZLE_IDENTITY)) && + (A == RHS.A || (A == TEXTURE_COMPONENT_SWIZZLE_IDENTITY && RHS.A == TEXTURE_COMPONENT_SWIZZLE_A) || (A == TEXTURE_COMPONENT_SWIZZLE_A && RHS.A == TEXTURE_COMPONENT_SWIZZLE_IDENTITY)); } constexpr bool operator!=(const TextureComponentMapping& RHS) const { @@ -175,6 +175,46 @@ struct TextureComponentMapping TEXTURE_COMPONENT_SWIZZLE_IDENTITY }; } + + // Combines two component mappings into one. + // The resulting mapping is equivalent to first applying the first (lhs) mapping, + // then applying the second (rhs) mapping. + TextureComponentMapping operator*(const TextureComponentMapping& Rhs) const + { + TextureComponentMapping CombinedMapping; + for (size_t c = 0; c < 4; ++c) + { + TEXTURE_COMPONENT_SWIZZLE RhsCompSwizzle = Rhs[c]; + TEXTURE_COMPONENT_SWIZZLE& DstCompSwizzle = CombinedMapping[c]; + switch (RhsCompSwizzle) + { + case TEXTURE_COMPONENT_SWIZZLE_IDENTITY: DstCompSwizzle = (*this)[c]; break; + case TEXTURE_COMPONENT_SWIZZLE_ZERO: DstCompSwizzle = TEXTURE_COMPONENT_SWIZZLE_ZERO; break; + case TEXTURE_COMPONENT_SWIZZLE_ONE: DstCompSwizzle = TEXTURE_COMPONENT_SWIZZLE_ONE; break; + case TEXTURE_COMPONENT_SWIZZLE_R: DstCompSwizzle = (R == TEXTURE_COMPONENT_SWIZZLE_IDENTITY) ? TEXTURE_COMPONENT_SWIZZLE_R : R; break; + case TEXTURE_COMPONENT_SWIZZLE_G: DstCompSwizzle = (G == TEXTURE_COMPONENT_SWIZZLE_IDENTITY) ? TEXTURE_COMPONENT_SWIZZLE_G : G; break; + case TEXTURE_COMPONENT_SWIZZLE_B: DstCompSwizzle = (B == TEXTURE_COMPONENT_SWIZZLE_IDENTITY) ? TEXTURE_COMPONENT_SWIZZLE_B : B; break; + case TEXTURE_COMPONENT_SWIZZLE_A: DstCompSwizzle = (A == TEXTURE_COMPONENT_SWIZZLE_IDENTITY) ? TEXTURE_COMPONENT_SWIZZLE_A : A; break; + default: DstCompSwizzle = (*this)[c]; break; + } + + if ((DstCompSwizzle == TEXTURE_COMPONENT_SWIZZLE_R && c == 0) || + (DstCompSwizzle == TEXTURE_COMPONENT_SWIZZLE_G && c == 1) || + (DstCompSwizzle == TEXTURE_COMPONENT_SWIZZLE_B && c == 2) || + (DstCompSwizzle == TEXTURE_COMPONENT_SWIZZLE_A && c == 3)) + { + DstCompSwizzle = TEXTURE_COMPONENT_SWIZZLE_IDENTITY; + } + } + static_assert(TEXTURE_COMPONENT_SWIZZLE_COUNT == 7, "Please handle the new component swizzle"); + return CombinedMapping; + } + + TextureComponentMapping& operator*=(const TextureComponentMapping& rhs) + { + *this = *this * rhs; + return *this; + } #endif }; typedef struct TextureComponentMapping TextureComponentMapping; diff --git a/Tests/DiligentCoreTest/src/GraphicsEngine/TextureViewBaseTest.cpp b/Tests/DiligentCoreTest/src/GraphicsEngine/TextureViewBaseTest.cpp new file mode 100644 index 000000000..c5fdcdcd9 --- /dev/null +++ b/Tests/DiligentCoreTest/src/GraphicsEngine/TextureViewBaseTest.cpp @@ -0,0 +1,138 @@ +/* + * Copyright 2023 Diligent Graphics LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "TextureView.h" +#include "GraphicsTypesOutputInserters.hpp" +#include "FastRand.hpp" + +#include "gtest/gtest.h" + +using namespace Diligent; + +namespace +{ + +TEST(TextureComponentMappingTest, OperatorMultiply) +{ + auto Test = [](const std::string& lhs, const std::string& rhs, const std::string& res) { + TextureComponentMapping Mapping1; + EXPECT_TRUE(TextureComponentMappingFromString(lhs, Mapping1)); + TextureComponentMapping Mapping2; + EXPECT_TRUE(TextureComponentMappingFromString(rhs, Mapping2)); + TextureComponentMapping Res; + EXPECT_TRUE(TextureComponentMappingFromString(res, Res)); + EXPECT_EQ(Mapping1 * Mapping2, Res) << Mapping1 << " * " << Mapping2 << " = " << Res; + }; + + Test("rgba", "rrrr", "rrrr"); + Test("rgba", "gggg", "gggg"); + Test("rgba", "bbbb", "bbbb"); + Test("rgba", "aaaa", "aaaa"); + Test("rgba", "0000", "0000"); + Test("rgba", "1111", "1111"); + + Test("rrrr", "rgba", "rrrr"); + Test("gggg", "rgba", "gggg"); + Test("bbbb", "rgba", "bbbb"); + Test("aaaa", "rgba", "aaaa"); + Test("0000", "rgba", "0000"); + Test("1111", "rgba", "1111"); + + Test("rgba", "rgba", "rgba"); + Test("rgba", "abgr", "abgr"); + Test("rrr1", "bbbb", "rrrr"); + + for (Uint32 swizzle1 = 1; swizzle1 < TEXTURE_COMPONENT_SWIZZLE_COUNT; ++swizzle1) + { + const auto Swizzle1 = static_cast(swizzle1); + for (Uint32 swizzle2 = 1; swizzle2 < TEXTURE_COMPONENT_SWIZZLE_COUNT; ++swizzle2) + { + const auto Swizzle2 = static_cast(swizzle2); + TextureComponentMapping Mapping1{Swizzle1, Swizzle1, Swizzle1, Swizzle1}; + TextureComponentMapping Mapping2{Swizzle2, Swizzle2, Swizzle2, Swizzle2}; + + const auto RefSwizzle = Swizzle2 == TEXTURE_COMPONENT_SWIZZLE_ONE || Swizzle2 == TEXTURE_COMPONENT_SWIZZLE_ZERO ? + Swizzle2 : + Swizzle1; + + TextureComponentMapping RefMapping{ + RefSwizzle == TEXTURE_COMPONENT_SWIZZLE_R ? TEXTURE_COMPONENT_SWIZZLE_IDENTITY : RefSwizzle, + RefSwizzle == TEXTURE_COMPONENT_SWIZZLE_G ? TEXTURE_COMPONENT_SWIZZLE_IDENTITY : RefSwizzle, + RefSwizzle == TEXTURE_COMPONENT_SWIZZLE_B ? TEXTURE_COMPONENT_SWIZZLE_IDENTITY : RefSwizzle, + RefSwizzle == TEXTURE_COMPONENT_SWIZZLE_A ? TEXTURE_COMPONENT_SWIZZLE_IDENTITY : RefSwizzle, + }; + + EXPECT_EQ(Mapping1 * Mapping2, RefMapping) << Mapping1 << " * " << Mapping2 << " = " << RefMapping; + } + } + + Test("ab01", "barg", "01ab"); + Test("ab01", "ba1g", "011b"); + Test("gba1", "barg", "a1gb"); + + FastRandInt rnd{0, 0, static_cast(TEXTURE_COMPONENT_SWIZZLE_COUNT - 1)}; + for (size_t i = 0; i < 2048; ++i) + { + TextureComponentMapping Mapping1{ + static_cast(rnd()), + static_cast(rnd()), + static_cast(rnd()), + static_cast(rnd()), + }; + TextureComponentMapping Mapping2{ + static_cast(rnd()), + static_cast(rnd()), + static_cast(rnd()), + static_cast(rnd()), + }; + TextureComponentMapping Res = Mapping1 * Mapping2; + + for (Uint32 c = 0; c < 4; ++c) + { + if (Mapping1[c] == TEXTURE_COMPONENT_SWIZZLE_IDENTITY) + Mapping1[c] = static_cast(c + TEXTURE_COMPONENT_SWIZZLE_R); + if (Mapping2[c] == TEXTURE_COMPONENT_SWIZZLE_IDENTITY) + Mapping2[c] = static_cast(c + TEXTURE_COMPONENT_SWIZZLE_R); + } + + auto CombineSwizzle = [&Mapping1](TEXTURE_COMPONENT_SWIZZLE Swizzle) { + VERIFY_EXPR(Swizzle != TEXTURE_COMPONENT_SWIZZLE_IDENTITY); + return (Swizzle == TEXTURE_COMPONENT_SWIZZLE_ONE || Swizzle == TEXTURE_COMPONENT_SWIZZLE_ZERO) ? + Swizzle : + Mapping1[Swizzle - TEXTURE_COMPONENT_SWIZZLE_R]; + }; + TextureComponentMapping Ref{ + CombineSwizzle(Mapping2.R), + CombineSwizzle(Mapping2.G), + CombineSwizzle(Mapping2.B), + CombineSwizzle(Mapping2.A), + }; + + EXPECT_EQ(Res, Ref) << Mapping1 << " * " << Mapping2; + } +} + +} // namespace