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