From a99421e9ede7fac9c1ea832038e2b6dfe4231845 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Mika=20Isoj=C3=A4rvi?= Date: Thu, 30 Apr 2015 15:15:36 -0700 Subject: [PATCH] Optimize sRGB8 lookups by using lut. Change-Id: I8e77ed3d6572130658b67f8b1dcccad68583d2e6 --- Android.mk | 1 + framework/common/tcuSRGB8Lut.inl | 257 ++++++++++++++++++++++++++++ framework/common/tcuTexture.cpp | 17 +- framework/common/tcuTextureUtil.cpp | 29 ++++ framework/common/tcuTextureUtil.hpp | 2 + modules/internal/CMakeLists.txt | 2 + modules/internal/ditSRGB8ConversionTest.cpp | 104 +++++++++++ modules/internal/ditSRGB8ConversionTest.hpp | 36 ++++ modules/internal/ditTestPackage.cpp | 20 +++ 9 files changed, 466 insertions(+), 2 deletions(-) create mode 100644 framework/common/tcuSRGB8Lut.inl create mode 100644 modules/internal/ditSRGB8ConversionTest.cpp create mode 100644 modules/internal/ditSRGB8ConversionTest.hpp diff --git a/Android.mk b/Android.mk index 68fe0bd..be05333 100644 --- a/Android.mk +++ b/Android.mk @@ -659,6 +659,7 @@ LOCAL_SRC_FILES := \ modules/glshared/glsUniformBlockCase.cpp \ modules/glshared/glsVertexArrayTests.cpp \ modules/internal/ditBuildInfoTests.cpp \ + modules/internal/ditSRGB8ConversionTest.cpp \ modules/internal/ditDelibsTests.cpp \ modules/internal/ditFrameworkTests.cpp \ modules/internal/ditImageCompareTests.cpp \ diff --git a/framework/common/tcuSRGB8Lut.inl b/framework/common/tcuSRGB8Lut.inl new file mode 100644 index 0000000..f38a499 --- /dev/null +++ b/framework/common/tcuSRGB8Lut.inl @@ -0,0 +1,257 @@ + // Generated on x86_64 linux + 0x0u, + 0x399f22b4u, + 0x3a1f22b4u, + 0x3a6eb40eu, + 0x3a9f22b4u, + 0x3ac6eb61u, + 0x3aeeb40eu, + 0x3b0b3e5du, + 0x3b1f22b4u, + 0x3b33070bu, + 0x3b46eb61u, + 0x3b5b518du, + 0x3b70f18du, + 0x3b83e1c6u, + 0x3b8fe616u, + 0x3b9c87fdu, + 0x3ba9c9b6u, + 0x3bb7ad6fu, + 0x3bc63549u, + 0x3bd56361u, + 0x3be539c1u, + 0x3bf5ba70u, + 0x3c0373b5u, + 0x3c0c6152u, + 0x3c15a703u, + 0x3c1f45beu, + 0x3c293e6bu, + 0x3c3391f7u, + 0x3c3e4149u, + 0x3c494d43u, + 0x3c54b6c7u, + 0x3c607eb1u, + 0x3c6ca5dfu, + 0x3c792d22u, + 0x3c830aa8u, + 0x3c89af9eu, + 0x3c9085dbu, + 0x3c978dc5u, + 0x3c9ec7c2u, + 0x3ca63434u, + 0x3cadd37du, + 0x3cb5a601u, + 0x3cbdac20u, + 0x3cc5e639u, + 0x3cce54abu, + 0x3cd6f7d5u, + 0x3cdfd010u, + 0x3ce8ddb9u, + 0x3cf2212cu, + 0x3cfb9ac1u, + 0x3d02a569u, + 0x3d0798dcu, + 0x3d0ca7e6u, + 0x3d11d2afu, + 0x3d171963u, + 0x3d1c7c2eu, + 0x3d21fb3cu, + 0x3d2796b2u, + 0x3d2d4ebbu, + 0x3d332380u, + 0x3d39152bu, + 0x3d3f23e3u, + 0x3d454fd0u, + 0x3d4b991cu, + 0x3d51ffeeu, + 0x3d58846au, + 0x3d5f26b7u, + 0x3d65e6feu, + 0x3d6cc564u, + 0x3d73c210u, + 0x3d7add29u, + 0x3d810b67u, + 0x3d84b795u, + 0x3d887330u, + 0x3d8c3e4au, + 0x3d9018f6u, + 0x3d940345u, + 0x3d97fd4au, + 0x3d9c0716u, + 0x3da020bbu, + 0x3da44a4bu, + 0x3da883d6u, + 0x3daccd70u, + 0x3db12728u, + 0x3db59112u, + 0x3dba0b3au, + 0x3dbe95b5u, + 0x3dc33092u, + 0x3dc7dbe2u, + 0x3dcc97b6u, + 0x3dd1641fu, + 0x3dd6412cu, + 0x3ddb2eefu, + 0x3de02d77u, + 0x3de53cd5u, + 0x3dea5d19u, + 0x3def8e52u, + 0x3df4d091u, + 0x3dfa23e8u, + 0x3dff8861u, + 0x3e027f07u, + 0x3e054280u, + 0x3e080ea3u, + 0x3e0ae378u, + 0x3e0dc105u, + 0x3e10a754u, + 0x3e13966bu, + 0x3e168e52u, + 0x3e198f10u, + 0x3e1c98adu, + 0x3e1fab30u, + 0x3e22c6a3u, + 0x3e25eb09u, + 0x3e29186cu, + 0x3e2c4ed0u, + 0x3e2f8e42u, + 0x3e32d6c4u, + 0x3e362861u, + 0x3e39831eu, + 0x3e3ce702u, + 0x3e405416u, + 0x3e43ca5eu, + 0x3e4749e4u, + 0x3e4ad2aeu, + 0x3e4e64c2u, + 0x3e520027u, + 0x3e55a4e6u, + 0x3e595303u, + 0x3e5d0a8au, + 0x3e60cb7cu, + 0x3e6495e0u, + 0x3e6869bfu, + 0x3e6c4720u, + 0x3e702e0cu, + 0x3e741e84u, + 0x3e781890u, + 0x3e7c1c38u, + 0x3e8014c2u, + 0x3e82203bu, + 0x3e84308du, + 0x3e8645bau, + 0x3e885fc5u, + 0x3e8a7eb2u, + 0x3e8ca283u, + 0x3e8ecb3cu, + 0x3e90f8e1u, + 0x3e932b74u, + 0x3e9562f8u, + 0x3e979f71u, + 0x3e99e0e2u, + 0x3e9c274eu, + 0x3e9e72b8u, + 0x3ea0c322u, + 0x3ea31892u, + 0x3ea57308u, + 0x3ea7d28au, + 0x3eaa3718u, + 0x3eaca0b7u, + 0x3eaf0f69u, + 0x3eb18332u, + 0x3eb3fc18u, + 0x3eb67a18u, + 0x3eb8fd37u, + 0x3ebb8579u, + 0x3ebe12e0u, + 0x3ec0a571u, + 0x3ec33d2du, + 0x3ec5da17u, + 0x3ec87c33u, + 0x3ecb2383u, + 0x3ecdd00bu, + 0x3ed081ccu, + 0x3ed338ccu, + 0x3ed5f50au, + 0x3ed8b68du, + 0x3edb7d54u, + 0x3ede4965u, + 0x3ee11ac1u, + 0x3ee3f16bu, + 0x3ee6cd67u, + 0x3ee9aeb6u, + 0x3eec955du, + 0x3eef815du, + 0x3ef272bau, + 0x3ef56976u, + 0x3ef86594u, + 0x3efb6717u, + 0x3efe6e02u, + 0x3f00bd2du, + 0x3f02460eu, + 0x3f03d1a7u, + 0x3f055ff9u, + 0x3f06f106u, + 0x3f0884cfu, + 0x3f0a1b56u, + 0x3f0bb49bu, + 0x3f0d50a0u, + 0x3f0eef67u, + 0x3f1090f1u, + 0x3f12353eu, + 0x3f13dc51u, + 0x3f15862bu, + 0x3f1732cdu, + 0x3f18e239u, + 0x3f1a946fu, + 0x3f1c4972u, + 0x3f1e0141u, + 0x3f1fbbe0u, + 0x3f21794eu, + 0x3f23398eu, + 0x3f24fca0u, + 0x3f26c286u, + 0x3f288b42u, + 0x3f2a56d3u, + 0x3f2c253du, + 0x3f2df680u, + 0x3f2fca9fu, + 0x3f31a197u, + 0x3f337b6cu, + 0x3f355820u, + 0x3f3737b2u, + 0x3f391a26u, + 0x3f3aff7cu, + 0x3f3ce7b4u, + 0x3f3ed2d2u, + 0x3f40c0d4u, + 0x3f42b1beu, + 0x3f44a590u, + 0x3f469c4bu, + 0x3f4895f0u, + 0x3f4a9282u, + 0x3f4c9201u, + 0x3f4e946eu, + 0x3f5099cau, + 0x3f52a218u, + 0x3f54ad57u, + 0x3f56bb8au, + 0x3f58ccb0u, + 0x3f5ae0cdu, + 0x3f5cf7e0u, + 0x3f5f11ecu, + 0x3f612eeeu, + 0x3f634eefu, + 0x3f6571eau, + 0x3f6797e3u, + 0x3f69c0d6u, + 0x3f6beccdu, + 0x3f6e1bc0u, + 0x3f704db8u, + 0x3f7282afu, + 0x3f74baaeu, + 0x3f76f5aeu, + 0x3f7933b8u, + 0x3f7b74c6u, + 0x3f7db8e0u, + 0x3f800000u diff --git a/framework/common/tcuTexture.cpp b/framework/common/tcuTexture.cpp index 43c7616..a41d9c6 100644 --- a/framework/common/tcuTexture.cpp +++ b/framework/common/tcuTexture.cpp @@ -1187,8 +1187,21 @@ static bool isFixedPointDepthTextureFormat (const tcu::TextureFormat& format) // Texel lookup with color conversion. static inline Vec4 lookup (const ConstPixelBufferAccess& access, int i, int j, int k) { - Vec4 p = access.getPixel(i, j, k); - return isSRGB(access.getFormat()) ? sRGBToLinear(p) : p; + const TextureFormat& format = access.getFormat(); + + if (isSRGB(format)) + { + if (format.type == TextureFormat::UNORM_INT8 && format.order == TextureFormat::sRGB) + return sRGB8ToLinear(access.getPixelUint(i, j, k)); + else if (format.type == TextureFormat::UNORM_INT8 && format.order == TextureFormat::sRGBA) + return sRGBA8ToLinear(access.getPixelUint(i, j, k)); + else + return sRGBToLinear(access.getPixel(i, j, k)); + } + else + { + return access.getPixel(i, j, k); + } } // Border texel lookup with color conversion. diff --git a/framework/common/tcuTextureUtil.cpp b/framework/common/tcuTextureUtil.cpp index f11778e..5ac30de 100644 --- a/framework/common/tcuTextureUtil.cpp +++ b/framework/common/tcuTextureUtil.cpp @@ -40,6 +40,19 @@ static inline float sRGBChannelToLinear (float cs) return deFloatPow((cs + 0.055f) / 1.055f, 2.4f); } +static const deUint32 s_srgb8Lut[256] = +{ +#include "tcuSRGB8Lut.inl" +}; + +static inline float sRGB8ChannelToLinear (deUint32 cs) +{ + DE_ASSERT(cs < 256); + + // \note This triggers UB, but in practice it doesn't cause any problems + return ((const float*)s_srgb8Lut)[cs]; +} + static inline float linearChannelToSRGB (float cl) { if (cl <= 0.0f) @@ -61,6 +74,22 @@ Vec4 sRGBToLinear (const Vec4& cs) cs[3]); } +Vec4 sRGB8ToLinear (const UVec4& cs) +{ + return Vec4(sRGB8ChannelToLinear(cs[0]), + sRGB8ChannelToLinear(cs[1]), + sRGB8ChannelToLinear(cs[2]), + 1.0f); +} + +Vec4 sRGBA8ToLinear (const UVec4& cs) +{ + return Vec4(sRGB8ChannelToLinear(cs[0]), + sRGB8ChannelToLinear(cs[1]), + sRGB8ChannelToLinear(cs[2]), + (float)cs[3] / 255.0f); +} + //! Convert from linear to sRGB colorspace Vec4 linearToSRGB (const Vec4& cl) { diff --git a/framework/common/tcuTextureUtil.hpp b/framework/common/tcuTextureUtil.hpp index b31f2d0..056a930 100644 --- a/framework/common/tcuTextureUtil.hpp +++ b/framework/common/tcuTextureUtil.hpp @@ -45,6 +45,8 @@ bool hasDepthComponent (TextureFormat::ChannelOrder order); // sRGB - linear conversion. Vec4 sRGBToLinear (const Vec4& cs); +Vec4 sRGB8ToLinear (const UVec4& cs); +Vec4 sRGBA8ToLinear (const UVec4& cs); Vec4 linearToSRGB (const Vec4& cl); bool isSRGB (TextureFormat format); diff --git a/modules/internal/CMakeLists.txt b/modules/internal/CMakeLists.txt index d14a271..a8f7983 100644 --- a/modules/internal/CMakeLists.txt +++ b/modules/internal/CMakeLists.txt @@ -19,6 +19,8 @@ set(DE_INTERNAL_TESTS_SRCS ditTestPackage.hpp ditSeedBuilderTests.hpp ditSeedBuilderTests.cpp + ditSRGB8ConversionTest.hpp + ditSRGB8ConversionTest.cpp ) set(DE_INTERNAL_TESTS_LIBS diff --git a/modules/internal/ditSRGB8ConversionTest.cpp b/modules/internal/ditSRGB8ConversionTest.cpp new file mode 100644 index 0000000..5092e73 --- /dev/null +++ b/modules/internal/ditSRGB8ConversionTest.cpp @@ -0,0 +1,104 @@ +/*------------------------------------------------------------------------- + * drawElements Internal Test Module + * --------------------------------- + * + * Copyright 2015 The Android Open Source Project + * + * 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. + * + *//*! + * \file + * \brief 8-bit sRGB conversion test. + *//*--------------------------------------------------------------------*/ + +#include "ditSRGB8ConversionTest.hpp" + +#include "tcuFloat.hpp" +#include "tcuTestLog.hpp" +#include "tcuTextureUtil.hpp" +#include "tcuVectorUtil.hpp" + +namespace dit +{ +namespace +{ + +deUint32 calculateDiscreteFloatDistance (float a, float b) +{ + const deUint32 au = tcu::Float32(a).bits(); + const deUint32 bu = tcu::Float32(b).bits(); + + const bool asign = (au & (0x1u << 31u)) != 0u; + const bool bsign = (bu & (0x1u << 31u)) != 0u; + + const deUint32 avalue = (au & ((0x1u << 31u) - 1u)); + const deUint32 bvalue = (bu & ((0x1u << 31u) - 1u)); + + if (asign != bsign) + return avalue + bvalue + 1u; + else if (avalue < bvalue) + return bvalue - avalue; + else + return avalue - bvalue; +} + +const tcu::UVec4 calculateDiscreteFloatDistance (const tcu::Vec4& ref, const tcu::Vec4& res) +{ + return tcu::UVec4(calculateDiscreteFloatDistance(ref[0], res[0]), calculateDiscreteFloatDistance(ref[1], res[1]), calculateDiscreteFloatDistance(ref[2], res[2]), calculateDiscreteFloatDistance(ref[3], res[3])); +} + +class SRGB8ConversionTest : public tcu::TestCase +{ +public: + SRGB8ConversionTest (tcu::TestContext& context) + : tcu::TestCase (context, "srgb8", "SRGB8 conversion test") + { + } + + IterateResult iterate (void) + { + bool isOk = true; + tcu::TestLog& log = m_testCtx.getLog(); + + for (int i = 0; i < 256; i++) + { + const tcu::UVec4 src (i); + const tcu::Vec4 res (tcu::sRGBA8ToLinear(src)); + const tcu::Vec4 ref (tcu::sRGBToLinear(src.cast() / tcu::Vec4(255.0f))); + const tcu::Vec4 diff (res - ref); + const tcu::UVec4 discreteFloatDiff (calculateDiscreteFloatDistance(ref, res)); + + if (tcu::anyNotEqual(res, ref)) + log << tcu::TestLog::Message << i << ", Res: " << res << ", Ref: " << ref << ", Diff: " << diff << ", Discrete float diff: " << discreteFloatDiff << tcu::TestLog::EndMessage; + + if (tcu::boolAny(tcu::greaterThan(discreteFloatDiff, tcu::UVec4(1u)))) + isOk = false; + } + + if (isOk) + m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); + else + m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got ulp diffs greater than one."); + + return STOP; + } +}; + +} // anonymous + +tcu::TestCase* createSRGB8ConversionTest (tcu::TestContext& context) +{ + return new SRGB8ConversionTest(context); +} + +} // dit diff --git a/modules/internal/ditSRGB8ConversionTest.hpp b/modules/internal/ditSRGB8ConversionTest.hpp new file mode 100644 index 0000000..536babb --- /dev/null +++ b/modules/internal/ditSRGB8ConversionTest.hpp @@ -0,0 +1,36 @@ +#ifndef _DITSRGB8CONVERSIONTEST_HPP +#define _DITSRGB8CONVERSIONTEST_HPP +/*------------------------------------------------------------------------- + * drawElements Internal Test Module + * --------------------------------- + * + * Copyright 2015 The Android Open Source Project + * + * 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. + * + *//*! + * \file + * \brief 8-bit sRGB conversion test. + *//*--------------------------------------------------------------------*/ + +#include "tcuDefs.hpp" +#include "tcuTestCase.hpp" + +namespace dit +{ + +tcu::TestCase* createSRGB8ConversionTest (tcu::TestContext& context); + +} // dit + +#endif // _DITSRGB8CONVERSIONTEST_HPP diff --git a/modules/internal/ditTestPackage.cpp b/modules/internal/ditTestPackage.cpp index a290c70..607a7d1 100644 --- a/modules/internal/ditTestPackage.cpp +++ b/modules/internal/ditTestPackage.cpp @@ -29,9 +29,26 @@ #include "ditImageCompareTests.hpp" #include "ditTestLogTests.hpp" #include "ditSeedBuilderTests.hpp" +#include "ditSRGB8ConversionTest.hpp" namespace dit { +namespace +{ + +class TextureTests : public tcu::TestCaseGroup +{ +public: + TextureTests (tcu::TestContext& testCtx) + : tcu::TestCaseGroup(testCtx, "texture", "Tests for tcu::Texture and utils.") + { + } + + void init (void) + { + addChild(createSRGB8ConversionTest(m_testCtx)); + } +}; class DeqpTests : public tcu::TestCaseGroup { @@ -46,10 +63,13 @@ public: addChild(new TestLogTests (m_testCtx)); addChild(new ImageIOTests (m_testCtx)); addChild(new ImageCompareTests (m_testCtx)); + addChild(new TextureTests (m_testCtx)); addChild(createSeedBuilderTests (m_testCtx)); } }; +} // anonymous + class TestCaseExecutor : public tcu::TestCaseExecutor { public: -- 2.7.4