core: Define VK_USE_PLATFORM_XCB_KHR before including vkd3d_utils.h.
[vkmodelviewer.git] / Core / Hash.h
blob32aed01b925fcdb39a13fc8634ef4bd50dff0f40
1 //
2 // Copyright (c) Microsoft. All rights reserved.
3 // This code is licensed under the MIT License (MIT).
4 // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
5 // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
6 // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
7 // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
8 //
9 // Developed by Minigraph
11 // Author: James Stanard
13 #pragma once
15 #include "Math/Common.h"
16 #include <smmintrin.h>
18 #ifdef __SSE4_2__
19 #define ENABLE_SSE_CRC32 1
20 #else
21 #define ENABLE_SSE_CRC32 0
22 #endif
24 namespace Utility
26 inline size_t HashRange(const uint32_t* const Begin, const uint32_t* const End, size_t Hash)
28 #if ENABLE_SSE_CRC32
29 const uint64_t* Iter64 = (const uint64_t*)Math::AlignUp(Begin, 8);
30 const uint64_t* const End64 = (const uint64_t* const)Math::AlignDown(End, 8);
32 // If not 64-bit aligned, start with a single u32
33 if ((uint32_t*)Iter64 > Begin)
34 Hash = _mm_crc32_u32((uint32_t)Hash, *Begin);
36 // Iterate over consecutive u64 values
37 while (Iter64 < End64)
38 Hash = _mm_crc32_u64((uint64_t)Hash, *Iter64++);
40 // If there is a 32-bit remainder, accumulate that
41 if ((uint32_t*)Iter64 < End)
42 Hash = _mm_crc32_u32((uint32_t)Hash, *(uint32_t*)Iter64);
43 #else
44 // An inexpensive hash for CPUs lacking SSE4.2
45 for (const uint32_t* Iter = Begin; Iter < End; ++Iter)
46 Hash = 16777619U * Hash ^ *Iter;
47 #endif
49 return Hash;
52 template <typename T> inline size_t HashState( const T* StateDesc, size_t Count = 1, size_t Hash = 2166136261U )
54 static_assert((sizeof(T) & 3) == 0 && alignof(T) >= 4, "State object is not word-aligned");
55 return HashRange((uint32_t*)StateDesc, (uint32_t*)(StateDesc + Count), Hash);
58 } // namespace Utility