• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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