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 <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::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 #ifdef __clang__ 101 #define DEBUG_REPORT_LOGGER_PRINTF(fmt, args) \ 102 __attribute__((format(printf, (fmt) + 1, (args) + 1))) 103 #else 104 #define DEBUG_REPORT_LOGGER_PRINTF(fmt, args) 105 #endif 106 template <typename ObjectType> Info(ObjectType object,const char * format,...)107 inline void Info(ObjectType object, const char* format, ...) const 108 DEBUG_REPORT_LOGGER_PRINTF(2, 3) { 109 va_list ap; 110 va_start(ap, format); 111 PrintV(VK_DEBUG_REPORT_INFORMATION_BIT_EXT, GetObjectType(object), 112 GetObjectUInt64(object), format, ap); 113 va_end(ap); 114 } 115 116 template <typename ObjectType> Warn(ObjectType object,const char * format,...)117 inline void Warn(ObjectType object, const char* format, ...) const 118 DEBUG_REPORT_LOGGER_PRINTF(2, 3) { 119 va_list ap; 120 va_start(ap, format); 121 PrintV(VK_DEBUG_REPORT_WARNING_BIT_EXT, GetObjectType(object), 122 GetObjectUInt64(object), format, ap); 123 va_end(ap); 124 } 125 126 template <typename ObjectType> Err(ObjectType object,const char * format,...)127 inline void Err(ObjectType object, const char* format, ...) const 128 DEBUG_REPORT_LOGGER_PRINTF(2, 3) { 129 va_list ap; 130 va_start(ap, format); 131 PrintV(VK_DEBUG_REPORT_ERROR_BIT_EXT, GetObjectType(object), 132 GetObjectUInt64(object), format, ap); 133 va_end(ap); 134 } 135 136 private: 137 template <typename ObjectType> GetObjectType(ObjectType)138 static VkDebugReportObjectTypeEXT GetObjectType(ObjectType) { 139 if (std::is_same<ObjectType, VkInstance>::value) 140 return VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT; 141 else if (std::is_same<ObjectType, VkPhysicalDevice>::value) 142 return VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT; 143 else if (std::is_same<ObjectType, VkDevice>::value) 144 return VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT; 145 else 146 return VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT; 147 } 148 149 template <typename ObjectType> GetObjectUInt64(ObjectType object)150 static uint64_t GetObjectUInt64(ObjectType object) { 151 return uint64_t(object); 152 } 153 154 #define DEBUG_REPORT_LOGGER_VPRINTF(fmt) \ 155 __attribute__((format(printf, (fmt) + 1, 0))) 156 void PrintV(VkDebugReportFlagsEXT flags, 157 VkDebugReportObjectTypeEXT object_type, 158 uint64_t object, 159 const char* format, 160 va_list ap) const DEBUG_REPORT_LOGGER_VPRINTF(4); 161 162 const void* const instance_pnext_; 163 const DebugReportCallbackList* const callbacks_; 164 }; 165 166 } // namespace driver 167 } // namespace vulkan 168 169 #endif // LIBVULKAN_DEBUG_REPORT_H 170