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