1 /* 2 * Copyright 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef LIBVULKAN_DEBUG_REPORT_H 18 #define LIBVULKAN_DEBUG_REPORT_H 1 19 20 #include <stdarg.h> 21 #include <shared_mutex> 22 #include <vulkan/vulkan.h> 23 24 namespace vulkan { 25 namespace driver { 26 27 // clang-format off 28 VKAPI_ATTR VkResult CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback); 29 VKAPI_ATTR void DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks* pAllocator); 30 VKAPI_ATTR void DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage); 31 // clang-format on 32 33 class DebugReportCallbackList { 34 private: 35 // forward declaration 36 struct Node; 37 38 public: DebugReportCallbackList()39 DebugReportCallbackList() 40 : head_{nullptr, 0, nullptr, nullptr, VK_NULL_HANDLE} {} 41 DebugReportCallbackList(const DebugReportCallbackList&) = delete; 42 DebugReportCallbackList& operator=(const DebugReportCallbackList&) = delete; 43 ~DebugReportCallbackList() = default; 44 45 Node* AddCallback(const VkDebugReportCallbackCreateInfoEXT& info, 46 VkDebugReportCallbackEXT driver_handle, 47 const VkAllocationCallbacks& allocator); 48 void RemoveCallback(Node* node, const VkAllocationCallbacks& allocator); 49 50 void Message(VkDebugReportFlagsEXT flags, 51 VkDebugReportObjectTypeEXT object_type, 52 uint64_t object, 53 size_t location, 54 int32_t message_code, 55 const char* layer_prefix, 56 const char* message) const; 57 FromHandle(VkDebugReportCallbackEXT handle)58 static Node* FromHandle(VkDebugReportCallbackEXT handle) { 59 return reinterpret_cast<Node*>(uintptr_t(handle)); 60 } 61 GetHandle(const Node * node)62 static VkDebugReportCallbackEXT GetHandle(const Node* node) { 63 return VkDebugReportCallbackEXT(reinterpret_cast<uintptr_t>(node)); 64 } 65 GetDriverHandle(const Node * node)66 static VkDebugReportCallbackEXT GetDriverHandle(const Node* node) { 67 return node->driver_handle; 68 } 69 70 private: 71 struct Node { 72 Node* next; 73 74 VkDebugReportFlagsEXT flags; 75 PFN_vkDebugReportCallbackEXT callback; 76 void* user_data; 77 78 VkDebugReportCallbackEXT driver_handle; 79 }; 80 81 mutable std::shared_mutex rwmutex_; 82 Node head_; 83 }; 84 85 class DebugReportLogger { 86 public: DebugReportLogger(const VkInstanceCreateInfo & info)87 explicit DebugReportLogger(const VkInstanceCreateInfo& info) 88 : instance_pnext_(info.pNext), callbacks_(nullptr) {} DebugReportLogger(const DebugReportCallbackList & callbacks)89 explicit DebugReportLogger(const DebugReportCallbackList& callbacks) 90 : instance_pnext_(nullptr), callbacks_(&callbacks) {} 91 92 void Message(VkDebugReportFlagsEXT flags, 93 VkDebugReportObjectTypeEXT object_type, 94 uint64_t object, 95 size_t location, 96 int32_t message_code, 97 const char* layer_prefix, 98 const char* message) const; 99 100 #define DEBUG_REPORT_LOGGER_PRINTF(fmt, args) \ 101 __attribute__((format(printf, (fmt) + 1, (args) + 1))) 102 template <typename ObjectType> Info(ObjectType object,const char * format,...)103 void Info(ObjectType object, const char* format, ...) const 104 DEBUG_REPORT_LOGGER_PRINTF(2, 3) { 105 va_list ap; 106 va_start(ap, format); 107 PrintV(VK_DEBUG_REPORT_INFORMATION_BIT_EXT, GetObjectType(object), 108 GetObjectUInt64(object), format, ap); 109 va_end(ap); 110 } 111 112 template <typename ObjectType> Warn(ObjectType object,const char * format,...)113 void Warn(ObjectType object, const char* format, ...) const 114 DEBUG_REPORT_LOGGER_PRINTF(2, 3) { 115 va_list ap; 116 va_start(ap, format); 117 PrintV(VK_DEBUG_REPORT_WARNING_BIT_EXT, GetObjectType(object), 118 GetObjectUInt64(object), format, ap); 119 va_end(ap); 120 } 121 122 template <typename ObjectType> Err(ObjectType object,const char * format,...)123 void Err(ObjectType object, const char* format, ...) const 124 DEBUG_REPORT_LOGGER_PRINTF(2, 3) { 125 va_list ap; 126 va_start(ap, format); 127 PrintV(VK_DEBUG_REPORT_ERROR_BIT_EXT, GetObjectType(object), 128 GetObjectUInt64(object), format, ap); 129 va_end(ap); 130 } 131 132 private: 133 template <typename ObjectType> GetObjectType(ObjectType)134 static VkDebugReportObjectTypeEXT GetObjectType(ObjectType) { 135 if (std::is_same<ObjectType, VkInstance>::value) 136 return VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT; 137 else if (std::is_same<ObjectType, VkPhysicalDevice>::value) 138 return VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT; 139 else if (std::is_same<ObjectType, VkDevice>::value) 140 return VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT; 141 else 142 return VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT; 143 } 144 145 template <typename ObjectType> GetObjectUInt64(ObjectType object)146 static uint64_t GetObjectUInt64(ObjectType object) { 147 return uint64_t(object); 148 } 149 150 #define DEBUG_REPORT_LOGGER_VPRINTF(fmt) \ 151 __attribute__((format(printf, (fmt) + 1, 0))) 152 void PrintV(VkDebugReportFlagsEXT flags, 153 VkDebugReportObjectTypeEXT object_type, 154 uint64_t object, 155 const char* format, 156 va_list ap) const DEBUG_REPORT_LOGGER_VPRINTF(4); 157 158 const void* const instance_pnext_; 159 const DebugReportCallbackList* const callbacks_; 160 }; 161 162 } // namespace driver 163 } // namespace vulkan 164 165 #endif // LIBVULKAN_DEBUG_REPORT_H 166