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