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