| Jesse Hall | 715b86a | 2016-01-16 16:34:29 -0800 | [diff] [blame] | 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 |  | 
| Chia-I Wu | bc011fc | 2016-05-03 12:19:55 +0800 | [diff] [blame] | 20 | #include <stdarg.h> | 
| Jesse Hall | 715b86a | 2016-01-16 16:34:29 -0800 | [diff] [blame] | 21 | #include <shared_mutex> | 
| Chia-I Wu | bc011fc | 2016-05-03 12:19:55 +0800 | [diff] [blame] | 22 | #include <vulkan/vulkan.h> | 
| Jesse Hall | 715b86a | 2016-01-16 16:34:29 -0800 | [diff] [blame] | 23 |  | 
 | 24 | namespace vulkan { | 
| Chia-I Wu | 6226223 | 2016-03-26 07:06:44 +0800 | [diff] [blame] | 25 | namespace driver { | 
| Jesse Hall | 715b86a | 2016-01-16 16:34:29 -0800 | [diff] [blame] | 26 |  | 
 | 27 | // clang-format off | 
| Chia-I Wu | 6226223 | 2016-03-26 07:06:44 +0800 | [diff] [blame] | 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); | 
| Jesse Hall | 715b86a | 2016-01-16 16:34:29 -0800 | [diff] [blame] | 31 | // clang-format on | 
 | 32 |  | 
 | 33 | class DebugReportCallbackList { | 
| Chia-I Wu | a0d40aa | 2016-05-05 12:43:03 +0800 | [diff] [blame] | 34 |    private: | 
 | 35 |     // forward declaration | 
 | 36 |     struct Node; | 
 | 37 |  | 
| Jesse Hall | 715b86a | 2016-01-16 16:34:29 -0800 | [diff] [blame] | 38 |    public: | 
 | 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 |  | 
| Chia-I Wu | a0d40aa | 2016-05-05 12:43:03 +0800 | [diff] [blame] | 45 |     Node* AddCallback(const VkDebugReportCallbackCreateInfoEXT& info, | 
 | 46 |                       VkDebugReportCallbackEXT driver_handle, | 
 | 47 |                       const VkAllocationCallbacks& allocator); | 
 | 48 |     void RemoveCallback(Node* node, const VkAllocationCallbacks& allocator); | 
 | 49 |  | 
| Jesse Hall | 715b86a | 2016-01-16 16:34:29 -0800 | [diff] [blame] | 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, | 
| Chia-I Wu | b3055f3 | 2016-05-03 12:04:47 +0800 | [diff] [blame] | 56 |                  const char* message) const; | 
| Jesse Hall | 715b86a | 2016-01-16 16:34:29 -0800 | [diff] [blame] | 57 |  | 
| Chia-I Wu | a0d40aa | 2016-05-05 12:43:03 +0800 | [diff] [blame] | 58 |     static Node* FromHandle(VkDebugReportCallbackEXT handle) { | 
 | 59 |         return reinterpret_cast<Node*>(uintptr_t(handle)); | 
 | 60 |     } | 
 | 61 |  | 
 | 62 |     static VkDebugReportCallbackEXT GetHandle(const Node* node) { | 
 | 63 |         return VkDebugReportCallbackEXT(reinterpret_cast<uintptr_t>(node)); | 
 | 64 |     } | 
 | 65 |  | 
 | 66 |     static VkDebugReportCallbackEXT GetDriverHandle(const Node* node) { | 
 | 67 |         return node->driver_handle; | 
 | 68 |     } | 
 | 69 |  | 
| Jesse Hall | 715b86a | 2016-01-16 16:34:29 -0800 | [diff] [blame] | 70 |    private: | 
 | 71 |     struct Node { | 
 | 72 |         Node* next; | 
| Chia-I Wu | a0d40aa | 2016-05-05 12:43:03 +0800 | [diff] [blame] | 73 |  | 
| Jesse Hall | 715b86a | 2016-01-16 16:34:29 -0800 | [diff] [blame] | 74 |         VkDebugReportFlagsEXT flags; | 
 | 75 |         PFN_vkDebugReportCallbackEXT callback; | 
| Chia-I Wu | a0d40aa | 2016-05-05 12:43:03 +0800 | [diff] [blame] | 76 |         void* user_data; | 
 | 77 |  | 
 | 78 |         VkDebugReportCallbackEXT driver_handle; | 
| Jesse Hall | 715b86a | 2016-01-16 16:34:29 -0800 | [diff] [blame] | 79 |     }; | 
 | 80 |  | 
 | 81 |     // TODO(jessehall): replace with std::shared_mutex when available in libc++ | 
| Chia-I Wu | b3055f3 | 2016-05-03 12:04:47 +0800 | [diff] [blame] | 82 |     mutable std::shared_timed_mutex rwmutex_; | 
| Jesse Hall | 715b86a | 2016-01-16 16:34:29 -0800 | [diff] [blame] | 83 |     Node head_; | 
 | 84 | }; | 
 | 85 |  | 
| Chia-I Wu | bc011fc | 2016-05-03 12:19:55 +0800 | [diff] [blame] | 86 | class DebugReportLogger { | 
 | 87 |    public: | 
| Chih-Hung Hsieh | d56988d | 2016-09-01 11:37:47 -0700 | [diff] [blame] | 88 |     explicit DebugReportLogger(const VkInstanceCreateInfo& info) | 
| Chia-I Wu | bc011fc | 2016-05-03 12:19:55 +0800 | [diff] [blame] | 89 |         : instance_pnext_(info.pNext), callbacks_(nullptr) {} | 
| Chih-Hung Hsieh | d56988d | 2016-09-01 11:37:47 -0700 | [diff] [blame] | 90 |     explicit DebugReportLogger(const DebugReportCallbackList& callbacks) | 
| Chia-I Wu | bc011fc | 2016-05-03 12:19:55 +0800 | [diff] [blame] | 91 |         : instance_pnext_(nullptr), callbacks_(&callbacks) {} | 
 | 92 |  | 
 | 93 |     void Message(VkDebugReportFlagsEXT flags, | 
 | 94 |                  VkDebugReportObjectTypeEXT object_type, | 
 | 95 |                  uint64_t object, | 
 | 96 |                  size_t location, | 
 | 97 |                  int32_t message_code, | 
 | 98 |                  const char* layer_prefix, | 
 | 99 |                  const char* message) const; | 
 | 100 |  | 
 | 101 | #define DEBUG_REPORT_LOGGER_PRINTF(fmt, args) \ | 
 | 102 |     __attribute__((format(printf, (fmt) + 1, (args) + 1))) | 
 | 103 |     template <typename ObjectType> | 
 | 104 |     void Info(ObjectType object, const char* format, ...) const | 
 | 105 |         DEBUG_REPORT_LOGGER_PRINTF(2, 3) { | 
 | 106 |         va_list ap; | 
 | 107 |         va_start(ap, format); | 
 | 108 |         PrintV(VK_DEBUG_REPORT_INFORMATION_BIT_EXT, GetObjectType(object), | 
 | 109 |                GetObjectUInt64(object), format, ap); | 
 | 110 |         va_end(ap); | 
 | 111 |     } | 
 | 112 |  | 
 | 113 |     template <typename ObjectType> | 
 | 114 |     void Warn(ObjectType object, const char* format, ...) const | 
 | 115 |         DEBUG_REPORT_LOGGER_PRINTF(2, 3) { | 
 | 116 |         va_list ap; | 
 | 117 |         va_start(ap, format); | 
 | 118 |         PrintV(VK_DEBUG_REPORT_WARNING_BIT_EXT, GetObjectType(object), | 
 | 119 |                GetObjectUInt64(object), format, ap); | 
 | 120 |         va_end(ap); | 
 | 121 |     } | 
 | 122 |  | 
 | 123 |     template <typename ObjectType> | 
 | 124 |     void Err(ObjectType object, const char* format, ...) const | 
 | 125 |         DEBUG_REPORT_LOGGER_PRINTF(2, 3) { | 
 | 126 |         va_list ap; | 
 | 127 |         va_start(ap, format); | 
 | 128 |         PrintV(VK_DEBUG_REPORT_ERROR_BIT_EXT, GetObjectType(object), | 
 | 129 |                GetObjectUInt64(object), format, ap); | 
 | 130 |         va_end(ap); | 
 | 131 |     } | 
 | 132 |  | 
 | 133 |    private: | 
 | 134 |     template <typename ObjectType> | 
 | 135 |     static VkDebugReportObjectTypeEXT GetObjectType(ObjectType) { | 
 | 136 |         if (std::is_same<ObjectType, VkInstance>::value) | 
 | 137 |             return VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT; | 
 | 138 |         else if (std::is_same<ObjectType, VkPhysicalDevice>::value) | 
 | 139 |             return VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT; | 
 | 140 |         else if (std::is_same<ObjectType, VkDevice>::value) | 
 | 141 |             return VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT; | 
 | 142 |         else | 
 | 143 |             return VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT; | 
 | 144 |     } | 
 | 145 |  | 
 | 146 |     template <typename ObjectType> | 
 | 147 |     static uint64_t GetObjectUInt64(ObjectType object) { | 
 | 148 |         return uint64_t(object); | 
 | 149 |     } | 
 | 150 |  | 
 | 151 | #define DEBUG_REPORT_LOGGER_VPRINTF(fmt) \ | 
 | 152 |     __attribute__((format(printf, (fmt) + 1, 0))) | 
 | 153 |     void PrintV(VkDebugReportFlagsEXT flags, | 
 | 154 |                 VkDebugReportObjectTypeEXT object_type, | 
 | 155 |                 uint64_t object, | 
 | 156 |                 const char* format, | 
 | 157 |                 va_list ap) const DEBUG_REPORT_LOGGER_VPRINTF(4); | 
 | 158 |  | 
 | 159 |     const void* const instance_pnext_; | 
 | 160 |     const DebugReportCallbackList* const callbacks_; | 
 | 161 | }; | 
 | 162 |  | 
| Chia-I Wu | 6226223 | 2016-03-26 07:06:44 +0800 | [diff] [blame] | 163 | }  // namespace driver | 
| Jesse Hall | 715b86a | 2016-01-16 16:34:29 -0800 | [diff] [blame] | 164 | }  // namespace vulkan | 
 | 165 |  | 
 | 166 | #endif  // LIBVULKAN_DEBUG_REPORT_H |