• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2002 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // angleutils.h: Common ANGLE utilities.
8 
9 #ifndef COMMON_ANGLEUTILS_H_
10 #define COMMON_ANGLEUTILS_H_
11 
12 #include "common/platform.h"
13 
14 #if defined(ANGLE_USE_ABSEIL)
15 #    include "absl/container/flat_hash_map.h"
16 #    include "absl/container/flat_hash_set.h"
17 #endif  // defined(ANGLE_USE_ABSEIL)
18 
19 #if defined(ANGLE_WITH_LSAN)
20 #    include <sanitizer/lsan_interface.h>
21 #endif  // defined(ANGLE_WITH_LSAN)
22 
23 #include <climits>
24 #include <cstdarg>
25 #include <cstddef>
26 #include <fstream>
27 #include <mutex>
28 #include <set>
29 #include <sstream>
30 #include <string>
31 #include <unordered_map>
32 #include <unordered_set>
33 #include <vector>
34 
35 // A helper class to disallow copy and assignment operators
36 namespace angle
37 {
38 
39 #if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
40 using Microsoft::WRL::ComPtr;
41 #endif  // defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
42 
43 #if defined(ANGLE_USE_ABSEIL)
44 template <typename Key, typename T, class Hash = absl::container_internal::hash_default_hash<Key>>
45 using HashMap = absl::flat_hash_map<Key, T, Hash>;
46 template <typename Key, class Hash = absl::container_internal::hash_default_hash<Key>>
47 using HashSet = absl::flat_hash_set<Key, Hash>;
48 #else
49 template <typename Key, typename T, class Hash = std::hash<Key>>
50 using HashMap = std::unordered_map<Key, T, Hash>;
51 template <typename Key, class Hash = std::hash<Key>>
52 using HashSet = std::unordered_set<Key, Hash>;
53 #endif  // defined(ANGLE_USE_ABSEIL)
54 
55 class NonCopyable
56 {
57   protected:
58     constexpr NonCopyable() = default;
59     ~NonCopyable()          = default;
60 
61   private:
62     NonCopyable(const NonCopyable &) = delete;
63     void operator=(const NonCopyable &) = delete;
64 };
65 
66 extern const uintptr_t DirtyPointer;
67 
68 struct SaveFileHelper
69 {
70   public:
71     // We always use ios::binary to avoid inconsistent line endings when captured on Linux vs Win.
72     SaveFileHelper(const std::string &filePathIn);
73     ~SaveFileHelper();
74 
75     template <typename T>
76     SaveFileHelper &operator<<(const T &value)
77     {
78         mOfs << value;
79         checkError();
80         return *this;
81     }
82 
83     void write(const uint8_t *data, size_t size);
84 
85   private:
86     void checkError();
87 
88     std::ofstream mOfs;
89     std::string mFilePath;
90 };
91 
92 // AMD_performance_monitor helpers.
93 constexpr char kPerfMonitorExtensionName[] = "GL_AMD_performance_monitor";
94 
95 struct PerfMonitorCounter
96 {
97     PerfMonitorCounter();
98     ~PerfMonitorCounter();
99 
100     std::string name;
101     uint32_t value;
102 };
103 using PerfMonitorCounters = std::vector<PerfMonitorCounter>;
104 
105 struct PerfMonitorCounterGroup
106 {
107     PerfMonitorCounterGroup();
108     ~PerfMonitorCounterGroup();
109 
110     std::string name;
111     PerfMonitorCounters counters;
112 };
113 using PerfMonitorCounterGroups = std::vector<PerfMonitorCounterGroup>;
114 
115 uint32_t GetPerfMonitorCounterIndex(const PerfMonitorCounters &counters, const std::string &name);
116 const PerfMonitorCounter &GetPerfMonitorCounter(const PerfMonitorCounters &counters,
117                                                 const std::string &name);
118 PerfMonitorCounter &GetPerfMonitorCounter(PerfMonitorCounters &counters, const std::string &name);
119 uint32_t GetPerfMonitorCounterGroupIndex(const PerfMonitorCounterGroups &groups,
120                                          const std::string &name);
121 const PerfMonitorCounterGroup &GetPerfMonitorCounterGroup(const PerfMonitorCounterGroups &groups,
122                                                           const std::string &name);
123 PerfMonitorCounterGroup &GetPerfMonitorCounterGroup(PerfMonitorCounterGroups &groups,
124                                                     const std::string &name);
125 
126 struct PerfMonitorTriplet
127 {
128     uint32_t group;
129     uint32_t counter;
130     uint32_t value;
131 };
132 
133 #define ANGLE_VK_PERF_COUNTERS_X(FN)               \
134     FN(primaryBuffers)                             \
135     FN(renderPasses)                               \
136     FN(submittedCommands)                          \
137     FN(writeDescriptorSets)                        \
138     FN(flushedOutsideRenderPassCommandBuffers)     \
139     FN(swapchainResolveInSubpass)                  \
140     FN(swapchainResolveOutsideSubpass)             \
141     FN(resolveImageCommands)                       \
142     FN(colorLoadOpClears)                          \
143     FN(colorLoadOpLoads)                           \
144     FN(colorLoadOpNones)                           \
145     FN(colorStoreOpStores)                         \
146     FN(colorStoreOpNones)                          \
147     FN(colorClearAttachments)                      \
148     FN(depthLoadOpClears)                          \
149     FN(depthLoadOpLoads)                           \
150     FN(depthLoadOpNones)                           \
151     FN(depthStoreOpStores)                         \
152     FN(depthStoreOpNones)                          \
153     FN(depthClearAttachments)                      \
154     FN(stencilLoadOpClears)                        \
155     FN(stencilLoadOpLoads)                         \
156     FN(stencilLoadOpNones)                         \
157     FN(stencilStoreOpStores)                       \
158     FN(stencilStoreOpNones)                        \
159     FN(stencilClearAttachments)                    \
160     FN(colorAttachmentUnresolves)                  \
161     FN(depthAttachmentUnresolves)                  \
162     FN(stencilAttachmentUnresolves)                \
163     FN(colorAttachmentResolves)                    \
164     FN(depthAttachmentResolves)                    \
165     FN(stencilAttachmentResolves)                  \
166     FN(readOnlyDepthStencilRenderPasses)           \
167     FN(descriptorSetAllocations)                   \
168     FN(descriptorSetCacheTotalSize)                \
169     FN(descriptorSetCacheKeySizeBytes)             \
170     FN(uniformsAndXfbDescriptorSetCacheHits)       \
171     FN(uniformsAndXfbDescriptorSetCacheMisses)     \
172     FN(uniformsAndXfbDescriptorSetCacheTotalSize)  \
173     FN(textureDescriptorSetCacheHits)              \
174     FN(textureDescriptorSetCacheMisses)            \
175     FN(textureDescriptorSetCacheTotalSize)         \
176     FN(shaderResourcesDescriptorSetCacheHits)      \
177     FN(shaderResourcesDescriptorSetCacheMisses)    \
178     FN(shaderResourcesDescriptorSetCacheTotalSize) \
179     FN(buffersGhosted)                             \
180     FN(vertexArraySyncStateCalls)                  \
181     FN(allocateNewBufferBlockCalls)                \
182     FN(dynamicBufferAllocations)
183 
184 #define ANGLE_DECLARE_PERF_COUNTER(COUNTER) uint32_t COUNTER;
185 
186 struct VulkanPerfCounters
187 {
188     ANGLE_VK_PERF_COUNTERS_X(ANGLE_DECLARE_PERF_COUNTER)
189 };
190 
191 #undef ANGLE_DECLARE_PERF_COUNTER
192 
193 }  // namespace angle
194 
195 template <typename T, size_t N>
ArraySize(T (&)[N])196 constexpr inline size_t ArraySize(T (&)[N])
197 {
198     return N;
199 }
200 
201 template <typename T>
202 class WrappedArray final : angle::NonCopyable
203 {
204   public:
205     template <size_t N>
WrappedArray(const T (& data)[N])206     constexpr WrappedArray(const T (&data)[N]) : mArray(&data[0]), mSize(N)
207     {}
208 
WrappedArray()209     constexpr WrappedArray() : mArray(nullptr), mSize(0) {}
WrappedArray(const T * data,size_t size)210     constexpr WrappedArray(const T *data, size_t size) : mArray(data), mSize(size) {}
211 
WrappedArray(WrappedArray && other)212     WrappedArray(WrappedArray &&other) : WrappedArray()
213     {
214         std::swap(mArray, other.mArray);
215         std::swap(mSize, other.mSize);
216     }
217 
~WrappedArray()218     ~WrappedArray() {}
219 
get()220     constexpr const T *get() const { return mArray; }
size()221     constexpr size_t size() const { return mSize; }
222 
223   private:
224     const T *mArray;
225     size_t mSize;
226 };
227 
228 template <typename T, unsigned int N>
SafeRelease(T (& resourceBlock)[N])229 void SafeRelease(T (&resourceBlock)[N])
230 {
231     for (unsigned int i = 0; i < N; i++)
232     {
233         SafeRelease(resourceBlock[i]);
234     }
235 }
236 
237 template <typename T>
SafeRelease(T & resource)238 void SafeRelease(T &resource)
239 {
240     if (resource)
241     {
242         resource->Release();
243         resource = nullptr;
244     }
245 }
246 
247 template <typename T>
SafeDelete(T * & resource)248 void SafeDelete(T *&resource)
249 {
250     delete resource;
251     resource = nullptr;
252 }
253 
254 template <typename T>
SafeDeleteContainer(T & resource)255 void SafeDeleteContainer(T &resource)
256 {
257     for (auto &element : resource)
258     {
259         SafeDelete(element);
260     }
261     resource.clear();
262 }
263 
264 template <typename T>
SafeDeleteArray(T * & resource)265 void SafeDeleteArray(T *&resource)
266 {
267     delete[] resource;
268     resource = nullptr;
269 }
270 
271 // Provide a less-than function for comparing structs
272 // Note: struct memory must be initialized to zero, because of packing gaps
273 template <typename T>
StructLessThan(const T & a,const T & b)274 inline bool StructLessThan(const T &a, const T &b)
275 {
276     return (memcmp(&a, &b, sizeof(T)) < 0);
277 }
278 
279 // Provide a less-than function for comparing structs
280 // Note: struct memory must be initialized to zero, because of packing gaps
281 template <typename T>
StructEquals(const T & a,const T & b)282 inline bool StructEquals(const T &a, const T &b)
283 {
284     return (memcmp(&a, &b, sizeof(T)) == 0);
285 }
286 
287 template <typename T>
StructZero(T * obj)288 inline void StructZero(T *obj)
289 {
290     memset(obj, 0, sizeof(T));
291 }
292 
293 template <typename T>
IsMaskFlagSet(T mask,T flag)294 inline bool IsMaskFlagSet(T mask, T flag)
295 {
296     // Handles multibit flags as well
297     return (mask & flag) == flag;
298 }
299 
MakeStaticString(const std::string & str)300 inline const char *MakeStaticString(const std::string &str)
301 {
302     // On the heap so that no destructor runs on application exit.
303     static std::set<std::string> *strings = new std::set<std::string>;
304     std::set<std::string>::iterator it    = strings->find(str);
305     if (it != strings->end())
306     {
307         return it->c_str();
308     }
309 
310     return strings->insert(str).first->c_str();
311 }
312 
313 std::string ArrayString(unsigned int i);
314 
315 // Indices are stored in vectors with the outermost index in the back. In the output of the function
316 // the indices are reversed.
317 std::string ArrayIndexString(const std::vector<unsigned int> &indices);
318 
Str(int i)319 inline std::string Str(int i)
320 {
321     std::stringstream strstr;
322     strstr << i;
323     return strstr.str();
324 }
325 
326 template <typename T>
ToString(const T & value)327 std::string ToString(const T &value)
328 {
329     std::ostringstream o;
330     o << value;
331     return o.str();
332 }
333 
IsLittleEndian()334 inline bool IsLittleEndian()
335 {
336     constexpr uint32_t kEndiannessTest = 1;
337     const bool isLittleEndian          = *reinterpret_cast<const uint8_t *>(&kEndiannessTest) == 1;
338     return isLittleEndian;
339 }
340 
341 // Helper class to use a mutex with the control of boolean.
342 class ConditionalMutex final : angle::NonCopyable
343 {
344   public:
ConditionalMutex()345     ConditionalMutex() : mUseMutex(true) {}
init(bool useMutex)346     void init(bool useMutex) { mUseMutex = useMutex; }
lock()347     void lock()
348     {
349         if (mUseMutex)
350         {
351             mMutex.lock();
352         }
353     }
unlock()354     void unlock()
355     {
356         if (mUseMutex)
357         {
358             mMutex.unlock();
359         }
360     }
361 
362   private:
363     std::mutex mMutex;
364     bool mUseMutex;
365 };
366 
367 // snprintf is not defined with MSVC prior to to msvc14
368 #if defined(_MSC_VER) && _MSC_VER < 1900
369 #    define snprintf _snprintf
370 #endif
371 
372 #define GL_A1RGB5_ANGLEX 0x6AC5
373 #define GL_BGRX8_ANGLEX 0x6ABA
374 #define GL_BGR565_ANGLEX 0x6ABB
375 #define GL_BGRA4_ANGLEX 0x6ABC
376 #define GL_BGR5_A1_ANGLEX 0x6ABD
377 #define GL_INT_64_ANGLEX 0x6ABE
378 #define GL_UINT_64_ANGLEX 0x6ABF
379 #define GL_BGRA8_SRGB_ANGLEX 0x6AC0
380 #define GL_BGR10_A2_ANGLEX 0x6AF9
381 
382 // These are fake formats used to fit typeless D3D textures that can be bound to EGL pbuffers into
383 // the format system (for extension EGL_ANGLE_d3d_texture_client_buffer):
384 #define GL_RGBA8_TYPELESS_ANGLEX 0x6AC1
385 #define GL_RGBA8_TYPELESS_SRGB_ANGLEX 0x6AC2
386 #define GL_BGRA8_TYPELESS_ANGLEX 0x6AC3
387 #define GL_BGRA8_TYPELESS_SRGB_ANGLEX 0x6AC4
388 
389 #define GL_R8_SSCALED_ANGLEX 0x6AC6
390 #define GL_RG8_SSCALED_ANGLEX 0x6AC7
391 #define GL_RGB8_SSCALED_ANGLEX 0x6AC8
392 #define GL_RGBA8_SSCALED_ANGLEX 0x6AC9
393 #define GL_R8_USCALED_ANGLEX 0x6ACA
394 #define GL_RG8_USCALED_ANGLEX 0x6ACB
395 #define GL_RGB8_USCALED_ANGLEX 0x6ACC
396 #define GL_RGBA8_USCALED_ANGLEX 0x6ACD
397 
398 #define GL_R16_SSCALED_ANGLEX 0x6ACE
399 #define GL_RG16_SSCALED_ANGLEX 0x6ACF
400 #define GL_RGB16_SSCALED_ANGLEX 0x6AD0
401 #define GL_RGBA16_SSCALED_ANGLEX 0x6AD1
402 #define GL_R16_USCALED_ANGLEX 0x6AD2
403 #define GL_RG16_USCALED_ANGLEX 0x6AD3
404 #define GL_RGB16_USCALED_ANGLEX 0x6AD4
405 #define GL_RGBA16_USCALED_ANGLEX 0x6AD5
406 
407 #define GL_R32_SSCALED_ANGLEX 0x6AD6
408 #define GL_RG32_SSCALED_ANGLEX 0x6AD7
409 #define GL_RGB32_SSCALED_ANGLEX 0x6AD8
410 #define GL_RGBA32_SSCALED_ANGLEX 0x6AD9
411 #define GL_R32_USCALED_ANGLEX 0x6ADA
412 #define GL_RG32_USCALED_ANGLEX 0x6ADB
413 #define GL_RGB32_USCALED_ANGLEX 0x6ADC
414 #define GL_RGBA32_USCALED_ANGLEX 0x6ADD
415 
416 #define GL_R32_SNORM_ANGLEX 0x6ADE
417 #define GL_RG32_SNORM_ANGLEX 0x6ADF
418 #define GL_RGB32_SNORM_ANGLEX 0x6AE0
419 #define GL_RGBA32_SNORM_ANGLEX 0x6AE1
420 #define GL_R32_UNORM_ANGLEX 0x6AE2
421 #define GL_RG32_UNORM_ANGLEX 0x6AE3
422 #define GL_RGB32_UNORM_ANGLEX 0x6AE4
423 #define GL_RGBA32_UNORM_ANGLEX 0x6AE5
424 
425 #define GL_R32_FIXED_ANGLEX 0x6AE6
426 #define GL_RG32_FIXED_ANGLEX 0x6AE7
427 #define GL_RGB32_FIXED_ANGLEX 0x6AE8
428 #define GL_RGBA32_FIXED_ANGLEX 0x6AE9
429 
430 #define GL_RGB10_A2_SINT_ANGLEX 0x6AEA
431 #define GL_RGB10_A2_SNORM_ANGLEX 0x6AEB
432 #define GL_RGB10_A2_SSCALED_ANGLEX 0x6AEC
433 #define GL_RGB10_A2_USCALED_ANGLEX 0x6AED
434 
435 // EXT_texture_type_2_10_10_10_REV
436 #define GL_RGB10_UNORM_ANGLEX 0x6AEE
437 
438 // These are fake formats for OES_vertex_type_10_10_10_2
439 #define GL_A2_RGB10_UNORM_ANGLEX 0x6AEF
440 #define GL_A2_RGB10_SNORM_ANGLEX 0x6AF0
441 #define GL_A2_RGB10_USCALED_ANGLEX 0x6AF1
442 #define GL_A2_RGB10_SSCALED_ANGLEX 0x6AF2
443 #define GL_X2_RGB10_UINT_ANGLEX 0x6AF3
444 #define GL_X2_RGB10_SINT_ANGLEX 0x6AF4
445 #define GL_X2_RGB10_USCALED_ANGLEX 0x6AF5
446 #define GL_X2_RGB10_SSCALED_ANGLEX 0x6AF6
447 #define GL_X2_RGB10_UNORM_ANGLEX 0x6AF7
448 #define GL_X2_RGB10_SNORM_ANGLEX 0x6AF8
449 
450 #define ANGLE_CHECK_GL_ALLOC(context, result) \
451     ANGLE_CHECK(context, result, "Failed to allocate host memory", GL_OUT_OF_MEMORY)
452 
453 #define ANGLE_CHECK_GL_MATH(context, result) \
454     ANGLE_CHECK(context, result, "Integer overflow.", GL_INVALID_OPERATION)
455 
456 #define ANGLE_GL_UNREACHABLE(context) \
457     UNREACHABLE();                    \
458     ANGLE_CHECK(context, false, "Unreachable Code.", GL_INVALID_OPERATION)
459 
460 #if defined(ANGLE_WITH_LSAN)
461 #    define ANGLE_SCOPED_DISABLE_LSAN() __lsan::ScopedDisabler lsanDisabler
462 #else
463 #    define ANGLE_SCOPED_DISABLE_LSAN()
464 #endif
465 
466 // The ANGLE_NO_SANITIZE_MEMORY macro suppresses MemorySanitizer checks for
467 // use-of-uninitialized-data. It can be used to decorate functions with known
468 // false positives.
469 #ifdef __clang__
470 #    define ANGLE_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory))
471 #else
472 #    define ANGLE_NO_SANITIZE_MEMORY
473 #endif
474 
475 // Similar to the above, but for thread sanitization.
476 #ifdef __clang__
477 #    define ANGLE_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread))
478 #else
479 #    define ANGLE_NO_SANITIZE_THREAD
480 #endif
481 
482 // The below inlining code lifted from V8.
483 #if defined(__clang__) || (defined(__GNUC__) && defined(__has_attribute))
484 #    define ANGLE_HAS_ATTRIBUTE_ALWAYS_INLINE (__has_attribute(always_inline))
485 #    define ANGLE_HAS___FORCEINLINE 0
486 #elif defined(_MSC_VER)
487 #    define ANGLE_HAS_ATTRIBUTE_ALWAYS_INLINE 0
488 #    define ANGLE_HAS___FORCEINLINE 1
489 #else
490 #    define ANGLE_HAS_ATTRIBUTE_ALWAYS_INLINE 0
491 #    define ANGLE_HAS___FORCEINLINE 0
492 #endif
493 
494 #if defined(NDEBUG) && ANGLE_HAS_ATTRIBUTE_ALWAYS_INLINE
495 #    define ANGLE_INLINE inline __attribute__((always_inline))
496 #elif defined(NDEBUG) && ANGLE_HAS___FORCEINLINE
497 #    define ANGLE_INLINE __forceinline
498 #else
499 #    define ANGLE_INLINE inline
500 #endif
501 
502 #if defined(__clang__) || (defined(__GNUC__) && defined(__has_attribute))
503 #    if __has_attribute(noinline)
504 #        define ANGLE_NOINLINE __attribute__((noinline))
505 #    else
506 #        define ANGLE_NOINLINE
507 #    endif
508 #elif defined(_MSC_VER)
509 #    define ANGLE_NOINLINE __declspec(noinline)
510 #else
511 #    define ANGLE_NOINLINE
512 #endif
513 
514 #if defined(__clang__) || (defined(__GNUC__) && defined(__has_attribute))
515 #    if __has_attribute(format)
516 #        define ANGLE_FORMAT_PRINTF(fmt, args) __attribute__((format(__printf__, fmt, args)))
517 #    else
518 #        define ANGLE_FORMAT_PRINTF(fmt, args)
519 #    endif
520 #else
521 #    define ANGLE_FORMAT_PRINTF(fmt, args)
522 #endif
523 
524 ANGLE_FORMAT_PRINTF(1, 0)
525 size_t FormatStringIntoVector(const char *fmt, va_list vararg, std::vector<char> &buffer);
526 
527 // Format messes up the # inside the macro.
528 // clang-format off
529 #ifndef ANGLE_STRINGIFY
530 #    define ANGLE_STRINGIFY(x) #x
531 #endif
532 // clang-format on
533 
534 #ifndef ANGLE_MACRO_STRINGIFY
535 #    define ANGLE_MACRO_STRINGIFY(x) ANGLE_STRINGIFY(x)
536 #endif
537 
538 // Detect support for C++17 [[nodiscard]]
539 #if !defined(__has_cpp_attribute)
540 #    define __has_cpp_attribute(name) 0
541 #endif  // !defined(__has_cpp_attribute)
542 
543 #if __has_cpp_attribute(nodiscard)
544 #    define ANGLE_NO_DISCARD [[nodiscard]]
545 #else
546 #    define ANGLE_NO_DISCARD
547 #endif  // __has_cpp_attribute(nodiscard)
548 
549 #if __has_cpp_attribute(maybe_unused)
550 #    define ANGLE_MAYBE_UNUSED [[maybe_unused]]
551 #else
552 #    define ANGLE_MAYBE_UNUSED
553 #endif  // __has_cpp_attribute(maybe_unused)
554 
555 #if __has_cpp_attribute(require_constant_initialization)
556 #    define ANGLE_REQUIRE_CONSTANT_INIT [[require_constant_initialization]]
557 #else
558 #    define ANGLE_REQUIRE_CONSTANT_INIT
559 #endif  // __has_cpp_attribute(require_constant_initialization)
560 
561 #if __has_cpp_attribute(clang::fallthrough)
562 #    define ANGLE_FALLTHROUGH [[clang::fallthrough]]
563 #else
564 #    define ANGLE_FALLTHROUGH
565 #endif
566 
567 // Compiler configs.
IsASan()568 inline bool IsASan()
569 {
570 #if defined(ANGLE_WITH_ASAN)
571     return true;
572 #else
573     return false;
574 #endif  // defined(ANGLE_WITH_ASAN)
575 }
576 
IsMSan()577 inline bool IsMSan()
578 {
579 #if defined(ANGLE_WITH_MSAN)
580     return true;
581 #else
582     return false;
583 #endif  // defined(ANGLE_WITH_MSAN)
584 }
585 
IsTSan()586 inline bool IsTSan()
587 {
588 #if defined(ANGLE_WITH_TSAN)
589     return true;
590 #else
591     return false;
592 #endif  // defined(ANGLE_WITH_TSAN)
593 }
594 
IsUBSan()595 inline bool IsUBSan()
596 {
597 #if defined(ANGLE_WITH_UBSAN)
598     return true;
599 #else
600     return false;
601 #endif  // defined(ANGLE_WITH_UBSAN)
602 }
603 #endif  // COMMON_ANGLEUTILS_H_
604