• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 The Dawn Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "common/Math.h"
16 
17 #include "common/Assert.h"
18 
19 #include <algorithm>
20 #include <cmath>
21 
22 #if defined(DAWN_COMPILER_MSVC)
23 #    include <intrin.h>
24 #endif
25 
ScanForward(uint32_t bits)26 uint32_t ScanForward(uint32_t bits) {
27     ASSERT(bits != 0);
28 #if defined(DAWN_COMPILER_MSVC)
29     unsigned long firstBitIndex = 0ul;
30     unsigned char ret = _BitScanForward(&firstBitIndex, bits);
31     ASSERT(ret != 0);
32     return firstBitIndex;
33 #else
34     return static_cast<uint32_t>(__builtin_ctz(bits));
35 #endif
36 }
37 
Log2(uint32_t value)38 uint32_t Log2(uint32_t value) {
39     ASSERT(value != 0);
40 #if defined(DAWN_COMPILER_MSVC)
41     unsigned long firstBitIndex = 0ul;
42     unsigned char ret = _BitScanReverse(&firstBitIndex, value);
43     ASSERT(ret != 0);
44     return firstBitIndex;
45 #else
46     return 31 - static_cast<uint32_t>(__builtin_clz(value));
47 #endif
48 }
49 
IsPowerOfTwo(size_t n)50 bool IsPowerOfTwo(size_t n) {
51     ASSERT(n != 0);
52     return (n & (n - 1)) == 0;
53 }
54 
IsPtrAligned(const void * ptr,size_t alignment)55 bool IsPtrAligned(const void* ptr, size_t alignment) {
56     ASSERT(IsPowerOfTwo(alignment));
57     ASSERT(alignment != 0);
58     return (reinterpret_cast<size_t>(ptr) & (alignment - 1)) == 0;
59 }
60 
AlignVoidPtr(void * ptr,size_t alignment)61 void* AlignVoidPtr(void* ptr, size_t alignment) {
62     ASSERT(IsPowerOfTwo(alignment));
63     ASSERT(alignment != 0);
64     return reinterpret_cast<void*>((reinterpret_cast<size_t>(ptr) + (alignment - 1)) &
65                                    ~(alignment - 1));
66 }
67 
IsAligned(uint32_t value,size_t alignment)68 bool IsAligned(uint32_t value, size_t alignment) {
69     ASSERT(alignment <= UINT32_MAX);
70     ASSERT(IsPowerOfTwo(alignment));
71     ASSERT(alignment != 0);
72     uint32_t alignment32 = static_cast<uint32_t>(alignment);
73     return (value & (alignment32 - 1)) == 0;
74 }
75 
Align(uint32_t value,size_t alignment)76 uint32_t Align(uint32_t value, size_t alignment) {
77     ASSERT(alignment <= UINT32_MAX);
78     ASSERT(IsPowerOfTwo(alignment));
79     ASSERT(alignment != 0);
80     uint32_t alignment32 = static_cast<uint32_t>(alignment);
81     return (value + (alignment32 - 1)) & ~(alignment32 - 1);
82 }
83 
Float32ToFloat16(float fp32)84 uint16_t Float32ToFloat16(float fp32) {
85     uint32_t fp32i = BitCast<uint32_t>(fp32);
86     uint32_t sign16 = (fp32i & 0x80000000) >> 16;
87     uint32_t mantissaAndExponent = fp32i & 0x7FFFFFFF;
88 
89     if (mantissaAndExponent > 0x7F800000) {  // NaN
90         return 0x7FFF;
91     } else if (mantissaAndExponent > 0x47FFEFFF) {  // Infinity
92         return static_cast<uint16_t>(sign16 | 0x7C00);
93     } else if (mantissaAndExponent < 0x38800000) {  // Denormal
94         uint32_t mantissa = (mantissaAndExponent & 0x007FFFFF) | 0x00800000;
95         int32_t exponent = 113 - (mantissaAndExponent >> 23);
96 
97         if (exponent < 24) {
98             mantissaAndExponent = mantissa >> exponent;
99         } else {
100             mantissaAndExponent = 0;
101         }
102 
103         return static_cast<uint16_t>(
104             sign16 | (mantissaAndExponent + 0x00000FFF + ((mantissaAndExponent >> 13) & 1)) >> 13);
105     } else {
106         return static_cast<uint16_t>(sign16 | (mantissaAndExponent + 0xC8000000 + 0x00000FFF +
107                                                ((mantissaAndExponent >> 13) & 1)) >>
108                                                   13);
109     }
110 }
111 
IsFloat16NaN(uint16_t fp16)112 bool IsFloat16NaN(uint16_t fp16) {
113     return (fp16 & 0x7FFF) > 0x7C00;
114 }
115 
116 // Based on the Khronos Data Format Specification 1.2 Section 13.3 sRGB transfer functions
SRGBToLinear(float srgb)117 float SRGBToLinear(float srgb) {
118     // sRGB is always used in unsigned normalized formats so clamp to [0.0, 1.0]
119     if (srgb <= 0.0f) {
120         return 0.0f;
121     } else if (srgb > 1.0f) {
122         return 1.0f;
123     }
124 
125     if (srgb < 0.04045f) {
126         return srgb / 12.92f;
127     } else {
128         return std::pow((srgb + 0.055f) / 1.055f, 2.4f);
129     }
130 }
131