• 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 <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