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 macro that casts to a bitfield type then verifies no bits were dropped.
379 #define SetBitField(lhs, rhs) \
380 do \
381 { \
382 auto ANGLE_LOCAL_VAR = rhs; \
383 lhs = static_cast<typename std::decay<decltype(lhs)>::type>(ANGLE_LOCAL_VAR); \
384 ASSERT(static_cast<decltype(ANGLE_LOCAL_VAR)>(lhs) == ANGLE_LOCAL_VAR); \
385 } while (0)
386
387 // snprintf is not defined with MSVC prior to to msvc14
388 #if defined(_MSC_VER) && _MSC_VER < 1900
389 # define snprintf _snprintf
390 #endif
391
392 #define GL_A1RGB5_ANGLEX 0x6AC5
393 #define GL_BGRX8_ANGLEX 0x6ABA
394 #define GL_BGR565_ANGLEX 0x6ABB
395 #define GL_BGRA4_ANGLEX 0x6ABC
396 #define GL_BGR5_A1_ANGLEX 0x6ABD
397 #define GL_INT_64_ANGLEX 0x6ABE
398 #define GL_UINT_64_ANGLEX 0x6ABF
399 #define GL_BGRA8_SRGB_ANGLEX 0x6AC0
400 #define GL_BGR10_A2_ANGLEX 0x6AF9
401 #define GL_BGRX8_SRGB_ANGLEX 0x6AFC
402 // fake format for GL_ANGLE_rgbx_internal_format
403 #define GL_RGBX8_SRGB_ANGLEX 0x6AFA
404
405 // These are fake formats used to fit typeless D3D textures that can be bound to EGL pbuffers into
406 // the format system (for extension EGL_ANGLE_d3d_texture_client_buffer):
407 #define GL_RGBA8_TYPELESS_ANGLEX 0x6AC1
408 #define GL_RGBA8_TYPELESS_SRGB_ANGLEX 0x6AC2
409 #define GL_BGRA8_TYPELESS_ANGLEX 0x6AC3
410 #define GL_BGRA8_TYPELESS_SRGB_ANGLEX 0x6AC4
411
412 #define GL_R8_SSCALED_ANGLEX 0x6AC6
413 #define GL_RG8_SSCALED_ANGLEX 0x6AC7
414 #define GL_RGB8_SSCALED_ANGLEX 0x6AC8
415 #define GL_RGBA8_SSCALED_ANGLEX 0x6AC9
416 #define GL_R8_USCALED_ANGLEX 0x6ACA
417 #define GL_RG8_USCALED_ANGLEX 0x6ACB
418 #define GL_RGB8_USCALED_ANGLEX 0x6ACC
419 #define GL_RGBA8_USCALED_ANGLEX 0x6ACD
420
421 #define GL_R16_SSCALED_ANGLEX 0x6ACE
422 #define GL_RG16_SSCALED_ANGLEX 0x6ACF
423 #define GL_RGB16_SSCALED_ANGLEX 0x6AD0
424 #define GL_RGBA16_SSCALED_ANGLEX 0x6AD1
425 #define GL_R16_USCALED_ANGLEX 0x6AD2
426 #define GL_RG16_USCALED_ANGLEX 0x6AD3
427 #define GL_RGB16_USCALED_ANGLEX 0x6AD4
428 #define GL_RGBA16_USCALED_ANGLEX 0x6AD5
429
430 #define GL_R32_SSCALED_ANGLEX 0x6AD6
431 #define GL_RG32_SSCALED_ANGLEX 0x6AD7
432 #define GL_RGB32_SSCALED_ANGLEX 0x6AD8
433 #define GL_RGBA32_SSCALED_ANGLEX 0x6AD9
434 #define GL_R32_USCALED_ANGLEX 0x6ADA
435 #define GL_RG32_USCALED_ANGLEX 0x6ADB
436 #define GL_RGB32_USCALED_ANGLEX 0x6ADC
437 #define GL_RGBA32_USCALED_ANGLEX 0x6ADD
438
439 #define GL_R32_SNORM_ANGLEX 0x6ADE
440 #define GL_RG32_SNORM_ANGLEX 0x6ADF
441 #define GL_RGB32_SNORM_ANGLEX 0x6AE0
442 #define GL_RGBA32_SNORM_ANGLEX 0x6AE1
443 #define GL_R32_UNORM_ANGLEX 0x6AE2
444 #define GL_RG32_UNORM_ANGLEX 0x6AE3
445 #define GL_RGB32_UNORM_ANGLEX 0x6AE4
446 #define GL_RGBA32_UNORM_ANGLEX 0x6AE5
447
448 #define GL_R32_FIXED_ANGLEX 0x6AE6
449 #define GL_RG32_FIXED_ANGLEX 0x6AE7
450 #define GL_RGB32_FIXED_ANGLEX 0x6AE8
451 #define GL_RGBA32_FIXED_ANGLEX 0x6AE9
452
453 #define GL_RGB10_A2_SINT_ANGLEX 0x6AEA
454 #define GL_RGB10_A2_SNORM_ANGLEX 0x6AEB
455 #define GL_RGB10_A2_SSCALED_ANGLEX 0x6AEC
456 #define GL_RGB10_A2_USCALED_ANGLEX 0x6AED
457
458 // EXT_texture_type_2_10_10_10_REV
459 #define GL_RGB10_UNORM_ANGLEX 0x6AEE
460
461 // These are fake formats for OES_vertex_type_10_10_10_2
462 #define GL_A2_RGB10_UNORM_ANGLEX 0x6AEF
463 #define GL_A2_RGB10_SNORM_ANGLEX 0x6AF0
464 #define GL_A2_RGB10_USCALED_ANGLEX 0x6AF1
465 #define GL_A2_RGB10_SSCALED_ANGLEX 0x6AF2
466 #define GL_X2_RGB10_UINT_ANGLEX 0x6AF3
467 #define GL_X2_RGB10_SINT_ANGLEX 0x6AF4
468 #define GL_X2_RGB10_USCALED_ANGLEX 0x6AF5
469 #define GL_X2_RGB10_SSCALED_ANGLEX 0x6AF6
470 #define GL_X2_RGB10_UNORM_ANGLEX 0x6AF7
471 #define GL_X2_RGB10_SNORM_ANGLEX 0x6AF8
472
473 #define ANGLE_CHECK_GL_ALLOC(context, result) \
474 ANGLE_CHECK(context, result, "Failed to allocate host memory", GL_OUT_OF_MEMORY)
475
476 #define ANGLE_CHECK_GL_MATH(context, result) \
477 ANGLE_CHECK(context, result, "Integer overflow.", GL_INVALID_OPERATION)
478
479 #define ANGLE_GL_UNREACHABLE(context) \
480 UNREACHABLE(); \
481 ANGLE_CHECK(context, false, "Unreachable Code.", GL_INVALID_OPERATION)
482
483 #if defined(ANGLE_WITH_LSAN)
484 # define ANGLE_SCOPED_DISABLE_LSAN() __lsan::ScopedDisabler lsanDisabler
485 #else
486 # define ANGLE_SCOPED_DISABLE_LSAN()
487 #endif
488
489 #if defined(ANGLE_WITH_MSAN)
490 class MsanScopedDisableInterceptorChecks final : angle::NonCopyable
491 {
492 public:
MsanScopedDisableInterceptorChecks()493 MsanScopedDisableInterceptorChecks() { __msan_scoped_disable_interceptor_checks(); }
~MsanScopedDisableInterceptorChecks()494 ~MsanScopedDisableInterceptorChecks() { __msan_scoped_enable_interceptor_checks(); }
495 };
496 # define ANGLE_SCOPED_DISABLE_MSAN() \
497 MsanScopedDisableInterceptorChecks msanScopedDisableInterceptorChecks
498 #else
499 # define ANGLE_SCOPED_DISABLE_MSAN()
500 #endif
501
502 // The ANGLE_NO_SANITIZE_MEMORY macro suppresses MemorySanitizer checks for
503 // use-of-uninitialized-data. It can be used to decorate functions with known
504 // false positives.
505 #ifdef __clang__
506 # define ANGLE_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory))
507 #else
508 # define ANGLE_NO_SANITIZE_MEMORY
509 #endif
510
511 // Similar to the above, but for thread sanitization.
512 #ifdef __clang__
513 # define ANGLE_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread))
514 #else
515 # define ANGLE_NO_SANITIZE_THREAD
516 #endif
517
518 // Similar to the above, but for cfi-icall.
519 #ifdef __clang__
520 # define ANGLE_NO_SANITIZE_CFI_ICALL __attribute__((no_sanitize("cfi-icall")))
521 #else
522 # define ANGLE_NO_SANITIZE_CFI_ICALL
523 #endif
524
525 // The below inlining code lifted from V8.
526 #if defined(__clang__) || (defined(__GNUC__) && defined(__has_attribute))
527 # define ANGLE_HAS_ATTRIBUTE_ALWAYS_INLINE (__has_attribute(always_inline))
528 # define ANGLE_HAS___FORCEINLINE 0
529 #elif defined(_MSC_VER)
530 # define ANGLE_HAS_ATTRIBUTE_ALWAYS_INLINE 0
531 # define ANGLE_HAS___FORCEINLINE 1
532 #else
533 # define ANGLE_HAS_ATTRIBUTE_ALWAYS_INLINE 0
534 # define ANGLE_HAS___FORCEINLINE 0
535 #endif
536
537 #if defined(NDEBUG) && ANGLE_HAS_ATTRIBUTE_ALWAYS_INLINE
538 # define ANGLE_INLINE inline __attribute__((always_inline))
539 #elif defined(NDEBUG) && ANGLE_HAS___FORCEINLINE
540 # define ANGLE_INLINE __forceinline
541 #else
542 # define ANGLE_INLINE inline
543 #endif
544
545 #if defined(__clang__) || (defined(__GNUC__) && defined(__has_attribute))
546 # if __has_attribute(noinline)
547 # define ANGLE_NOINLINE __attribute__((noinline))
548 # else
549 # define ANGLE_NOINLINE
550 # endif
551 #elif defined(_MSC_VER)
552 # define ANGLE_NOINLINE __declspec(noinline)
553 #else
554 # define ANGLE_NOINLINE
555 #endif
556
557 #if defined(__clang__) || (defined(__GNUC__) && defined(__has_attribute))
558 # if __has_attribute(format)
559 # define ANGLE_FORMAT_PRINTF(fmt, args) __attribute__((format(__printf__, fmt, args)))
560 # else
561 # define ANGLE_FORMAT_PRINTF(fmt, args)
562 # endif
563 #else
564 # define ANGLE_FORMAT_PRINTF(fmt, args)
565 #endif
566
567 #if defined(__clang__) || (defined(__GNUC__) && defined(__has_attribute))
568 # define ANGLE_HAS_ATTRIBUTE_CONSTRUCTOR (__has_attribute(constructor))
569 # define ANGLE_HAS_ATTRIBUTE_DESTRUCTOR (__has_attribute(destructor))
570 #else
571 # define ANGLE_HAS_ATTRIBUTE_CONSTRUCTOR 0
572 # define ANGLE_HAS_ATTRIBUTE_DESTRUCTOR 0
573 #endif
574
575 #if ANGLE_HAS_ATTRIBUTE_CONSTRUCTOR
576 # define ANGLE_CONSTRUCTOR __attribute__((constructor))
577 #endif
578
579 #if ANGLE_HAS_ATTRIBUTE_DESTRUCTOR
580 # define ANGLE_DESTRUCTOR __attribute__((destructor))
581 #endif
582
583 ANGLE_FORMAT_PRINTF(1, 0)
584 size_t FormatStringIntoVector(const char *fmt, va_list vararg, std::vector<char> &buffer);
585
586 // Format messes up the # inside the macro.
587 // clang-format off
588 #ifndef ANGLE_STRINGIFY
589 # define ANGLE_STRINGIFY(x) #x
590 #endif
591 // clang-format on
592
593 #ifndef ANGLE_MACRO_STRINGIFY
594 # define ANGLE_MACRO_STRINGIFY(x) ANGLE_STRINGIFY(x)
595 #endif
596
597 // The ANGLE_MAYBE_UNUSED_PRIVATE_FIELD can be used to hint 'unused private field'
598 // instead of 'maybe_unused' attribute for the compatibility with GCC because
599 // GCC doesn't have '-Wno-unused-private-field' whereas Clang has.
600 #if defined(__clang__) || defined(_MSC_VER)
601 # define ANGLE_MAYBE_UNUSED_PRIVATE_FIELD [[maybe_unused]]
602 #else
603 # define ANGLE_MAYBE_UNUSED_PRIVATE_FIELD
604 #endif
605
606 #if __has_cpp_attribute(clang::require_constant_initialization)
607 # define ANGLE_REQUIRE_CONSTANT_INIT [[clang::require_constant_initialization]]
608 #else
609 # define ANGLE_REQUIRE_CONSTANT_INIT
610 #endif // __has_cpp_attribute(require_constant_initialization)
611
612 // Compiler configs.
IsASan()613 inline bool IsASan()
614 {
615 #if defined(ANGLE_WITH_ASAN)
616 return true;
617 #else
618 return false;
619 #endif // defined(ANGLE_WITH_ASAN)
620 }
621
IsMSan()622 inline bool IsMSan()
623 {
624 #if defined(ANGLE_WITH_MSAN)
625 return true;
626 #else
627 return false;
628 #endif // defined(ANGLE_WITH_MSAN)
629 }
630
IsTSan()631 inline bool IsTSan()
632 {
633 #if defined(ANGLE_WITH_TSAN)
634 return true;
635 #else
636 return false;
637 #endif // defined(ANGLE_WITH_TSAN)
638 }
639
IsUBSan()640 inline bool IsUBSan()
641 {
642 #if defined(ANGLE_WITH_UBSAN)
643 return true;
644 #else
645 return false;
646 #endif // defined(ANGLE_WITH_UBSAN)
647 }
648 #endif // COMMON_ANGLEUTILS_H_
649