From: Eunki Hong Date: Sun, 6 Apr 2025 05:05:43 +0000 (+0900) Subject: Make HashUtil implements as cpp, So reduce duplicated implmenets X-Git-Tag: dali_2.4.14~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F07%2F322207%2F14;p=platform%2Fcore%2Fuifw%2Fdali-core.git Make HashUtil implements as cpp, So reduce duplicated implmenets Let we make basement of hash calculate optimization + Include below patchset, due to line coverage https://review.tizen.org/gerrit/c/platform/core/uifw/dali-core/+/322289 Change-Id: I8b4679b737f5adfa0c09932af17f02d61bdea8a4 Signed-off-by: Eunki Hong --- diff --git a/dali/internal/common/hash-utils.cpp b/dali/internal/common/hash-utils.cpp new file mode 100644 index 000000000..3fdce90d5 --- /dev/null +++ b/dali/internal/common/hash-utils.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2025 Samsung Electronics Co., Ltd. + * + * 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. + * + */ + +// CLASS HEADERS +#include + +// EXTERNAL INCLUDES +#include // uint8_t + +namespace Dali::Internal::HashUtils +{ +HashType HashRawByteBufferMultipleComponent(const uint8_t* __restrict__ buffer, std::size_t bufferSize, HashType& hash) +{ + // TODO : use ARM_NEON here in future + static constexpr HashType SCALE_LEVEL_1 = Dali::Power<33, 1>::value; + static constexpr HashType SCALE_LEVEL_2 = Dali::Power<33, 2>::value; + static constexpr HashType SCALE_LEVEL_3 = Dali::Power<33, 3>::value; + static constexpr HashType SCALE_LEVEL_4 = Dali::Power<33, 4>::value; + static constexpr HashType SCALE_LEVEL_5 = Dali::Power<33, 5>::value; + static constexpr HashType SCALE_LEVEL_6 = Dali::Power<33, 6>::value; + static constexpr HashType SCALE_LEVEL_7 = Dali::Power<33, 7>::value; + static constexpr HashType SCALE_LEVEL_8 = Dali::Power<33, 8>::value; + + while(bufferSize & (~0x7)) // bufferSize >= 8 + { + // clang-format off + hash = hash * SCALE_LEVEL_8 + + *(buffer + 0) * SCALE_LEVEL_7 + + *(buffer + 1) * SCALE_LEVEL_6 + + *(buffer + 2) * SCALE_LEVEL_5 + + *(buffer + 3) * SCALE_LEVEL_4 + + *(buffer + 4) * SCALE_LEVEL_3 + + *(buffer + 5) * SCALE_LEVEL_2 + + *(buffer + 6) * SCALE_LEVEL_1 + + *(buffer + 7); + // clang-format on + buffer += 8; + bufferSize -= 8; + } + + if(bufferSize & 0x4) // bufferSize >= 4. Note that 0 <= bufferSize < 8 in here. + { + // clang-format off + hash = hash * SCALE_LEVEL_4 + + *(buffer + 0) * SCALE_LEVEL_3 + + *(buffer + 1) * SCALE_LEVEL_2 + + *(buffer + 2) * SCALE_LEVEL_1 + + *(buffer + 3); + // clang-format on + buffer += 4; + bufferSize &= 0x3; + } + + // Now bufferSize is 0, 1, 2, 3. We can optimize here by switch-case + switch(bufferSize) + { + case 3: + { + hash = hash * 33 + *(buffer++); + DALI_FALLTHROUGH; + } + case 2: + { + hash = hash * 33 + *(buffer++); + DALI_FALLTHROUGH; + } + case 1: + { + hash = hash * 33 + *(buffer++); + DALI_FALLTHROUGH; + } + case 0: + default: + { + break; + } + } + + return hash; +} + +} // namespace Dali::Internal::HashUtils diff --git a/dali/internal/common/hash-utils.h b/dali/internal/common/hash-utils.h index 81639ec4c..5fe123390 100644 --- a/dali/internal/common/hash-utils.h +++ b/dali/internal/common/hash-utils.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_HASH_UTILS_H /* - * Copyright (c) 2024 Samsung Electronics Co., Ltd. + * Copyright (c) 2025 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,13 +29,15 @@ namespace Dali::Internal::HashUtils { -constexpr std::size_t INITIAL_HASH_VALUE = 5381; +using HashType = std::size_t; + +constexpr HashType INITIAL_HASH_VALUE = 5381; /* * djb2 (http://www.cse.yorku.ca/~oz/hash.html) */ -[[maybe_unused]] inline std::size_t HashString(const char* string, std::size_t& hash) +[[maybe_unused]] inline HashType HashString(const char* string, HashType& hash) { while(int c = *string++) { @@ -44,7 +46,7 @@ constexpr std::size_t INITIAL_HASH_VALUE = 5381; return hash; } -[[maybe_unused]] inline std::size_t HashString(const char* string, std::size_t& hash, char terminator) +[[maybe_unused]] inline HashType HashString(const char* string, HashType& hash, char terminator) { char c; while((c = *string++) && c != terminator) @@ -54,16 +56,7 @@ constexpr std::size_t INITIAL_HASH_VALUE = 5381; return hash; } -[[maybe_unused]] inline std::size_t HashStringView(const std::string_view& string, std::size_t& hash) -{ - for(auto c : string) - { - hash = hash * 33 + c; - } - return hash; -} - -[[maybe_unused]] inline std::size_t HashStringView(const std::string_view& string, std::size_t& hash, char terminator) +[[maybe_unused]] inline HashType HashStringView(const std::string_view& string, HashType& hash, char terminator) { for(auto c : string) { @@ -71,50 +64,53 @@ constexpr std::size_t INITIAL_HASH_VALUE = 5381; { break; } - hash = hash * 33 + static_cast(c); + hash = hash * 33 + static_cast(c); } return hash; } -[[maybe_unused]] inline std::size_t HashBuffer(const std::vector& buffer, std::size_t& hash) +// Hash functions with specified length, which we could optimize for +[[maybe_unused]] HashType HashRawByteBufferMultipleComponent(const uint8_t* __restrict__ buffer, std::size_t bufferSize, HashType& hash); + +[[maybe_unused]] inline HashType HashRawByteBuffer(const uint8_t* __restrict__ buffer, std::size_t bufferSize, HashType& hash) { - for(const auto& c : buffer) + if(bufferSize > 8) { - hash = hash * 33 + c; + return HashRawByteBufferMultipleComponent(buffer, bufferSize, hash); } - return hash; -} -[[maybe_unused]] inline std::size_t HashBuffer(const Dali::Vector& buffer, std::size_t& hash) -{ - for(const auto& c : buffer) + while(bufferSize--) { - hash = hash * 33 + c; + hash = hash * 33 + *(buffer++); } return hash; } +[[maybe_unused]] inline HashType HashStringView(const std::string_view& string, HashType& hash) +{ + return HashRawByteBuffer(reinterpret_cast(string.data()), string.size(), hash); +} + +[[maybe_unused]] inline HashType HashBuffer(const std::vector& buffer, HashType& hash) +{ + return HashRawByteBuffer(buffer.data(), buffer.size(), hash); +} + +[[maybe_unused]] inline HashType HashBuffer(const Dali::Vector& buffer, HashType& hash) +{ + return HashRawByteBuffer(buffer.Begin(), buffer.Count(), hash); +} + template -[[maybe_unused]] inline std::size_t HashRawBuffer(const T* buffer, std::size_t bufferSize, std::size_t& hash) +[[maybe_unused]] inline HashType HashRawBuffer(const T* __restrict__ buffer, std::size_t bufferSize, HashType& hash) { - if constexpr(sizeof(T) == 1u) - { - while(bufferSize--) - { - hash = hash * 33 + *(buffer++); - } - return hash; - } - else - { - return HashRawBuffer(reinterpret_cast(buffer), sizeof(T) * bufferSize, hash); - } + return HashRawByteBuffer(reinterpret_cast(buffer), sizeof(T) * bufferSize, hash); } template -[[maybe_unused]] inline std::size_t HashRawValue(const T& value, std::size_t& hash) +[[maybe_unused]] inline HashType HashRawValue(const T& value, HashType& hash) { - return HashRawBuffer(reinterpret_cast(&value), sizeof(T), hash); + return HashRawBuffer(reinterpret_cast(&value), sizeof(T), hash); } } // namespace Dali::Internal::HashUtils diff --git a/dali/internal/file.list b/dali/internal/file.list index e8956ec52..63f3a5e95 100644 --- a/dali/internal/file.list +++ b/dali/internal/file.list @@ -6,6 +6,7 @@ SET( internal_src_files ${internal_src_dir}/common/blending-options.cpp ${internal_src_dir}/common/core-impl.cpp ${internal_src_dir}/common/dummy-memory-pool.cpp + ${internal_src_dir}/common/hash-utils.cpp ${internal_src_dir}/common/math.cpp ${internal_src_dir}/common/matrix-utils.cpp ${internal_src_dir}/common/message-buffer.cpp diff --git a/dali/internal/render/shaders/program.cpp b/dali/internal/render/shaders/program.cpp index b97caac4f..d13a74ba7 100644 --- a/dali/internal/render/shaders/program.cpp +++ b/dali/internal/render/shaders/program.cpp @@ -144,7 +144,7 @@ void Program::BuildRequirements( // // If the name represents an element in an array of structs, it will contain an // index operator, but should be hashed in full. - auto hashValue = CalculateHash(item.name); + auto hashValue = CalculateHash(std::string_view(item.name.data(), item.name.size())); mReflection.emplace_back(ReflectionUniformInfo{hashValue, false, item}); // update buffer index @@ -166,7 +166,7 @@ void Program::BuildRequirements( auto samplers = graphicsReflection.GetSamplers(); // Only holds first element of arrays without []. for(const auto& sampler : samplers) { - mReflection.emplace_back(ReflectionUniformInfo{CalculateHash(sampler.name), false, sampler}); + mReflection.emplace_back(ReflectionUniformInfo{CalculateHash(std::string_view(sampler.name.data(), sampler.name.size())), false, sampler}); } // check for potential collisions