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