• 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 #include "driver.h"
18 
19 #include <string.h>
20 
21 namespace vulkan {
22 namespace driver {
23 
AddCallback(const VkDebugReportCallbackCreateInfoEXT & info,VkDebugReportCallbackEXT driver_handle,const VkAllocationCallbacks & allocator)24 DebugReportCallbackList::Node* DebugReportCallbackList::AddCallback(
25     const VkDebugReportCallbackCreateInfoEXT& info,
26     VkDebugReportCallbackEXT driver_handle,
27     const VkAllocationCallbacks& allocator) {
28     void* mem = allocator.pfnAllocation(allocator.pUserData, sizeof(Node),
29                                         alignof(Node),
30                                         VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
31     if (!mem)
32         return nullptr;
33 
34     // initialize and prepend node to the list
35     std::lock_guard<decltype(rwmutex_)> lock(rwmutex_);
36     head_.next = new (mem) Node{head_.next, info.flags, info.pfnCallback,
37                                 info.pUserData, driver_handle};
38 
39     return head_.next;
40 }
41 
RemoveCallback(Node * node,const VkAllocationCallbacks & allocator)42 void DebugReportCallbackList::RemoveCallback(
43     Node* node,
44     const VkAllocationCallbacks& allocator) {
45     // remove node from the list
46     {
47         std::lock_guard<decltype(rwmutex_)> lock(rwmutex_);
48         Node* prev = &head_;
49         while (prev && prev->next != node)
50             prev = prev->next;
51         if (prev)
52             prev->next = node->next;
53     }
54 
55     allocator.pfnFree(allocator.pUserData, node);
56 }
57 
Message(VkDebugReportFlagsEXT flags,VkDebugReportObjectTypeEXT object_type,uint64_t object,size_t location,int32_t message_code,const char * layer_prefix,const char * message) const58 void DebugReportCallbackList::Message(VkDebugReportFlagsEXT flags,
59                                       VkDebugReportObjectTypeEXT object_type,
60                                       uint64_t object,
61                                       size_t location,
62                                       int32_t message_code,
63                                       const char* layer_prefix,
64                                       const char* message) const {
65     std::lock_guard<std::mutex> lock(rwmutex_);
66     const Node* node = &head_;
67     while ((node = node->next)) {
68         if ((node->flags & flags) != 0) {
69             node->callback(flags, object_type, object, location, message_code,
70                            layer_prefix, message, node->user_data);
71         }
72     }
73 }
74 
Message(VkDebugReportFlagsEXT flags,VkDebugReportObjectTypeEXT object_type,uint64_t object,size_t location,int32_t message_code,const char * layer_prefix,const char * message) const75 void DebugReportLogger::Message(VkDebugReportFlagsEXT flags,
76                                 VkDebugReportObjectTypeEXT object_type,
77                                 uint64_t object,
78                                 size_t location,
79                                 int32_t message_code,
80                                 const char* layer_prefix,
81                                 const char* message) const {
82     const VkDebugReportCallbackCreateInfoEXT* info =
83         reinterpret_cast<const VkDebugReportCallbackCreateInfoEXT*>(
84             instance_pnext_);
85     while (info) {
86         if (info->sType ==
87                 VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT &&
88             (info->flags & flags) != 0) {
89             info->pfnCallback(flags, object_type, object, location,
90                               message_code, layer_prefix, message,
91                               info->pUserData);
92         }
93 
94         info = reinterpret_cast<const VkDebugReportCallbackCreateInfoEXT*>(
95             info->pNext);
96     }
97 
98     if (callbacks_) {
99         callbacks_->Message(flags, object_type, object, location, message_code,
100                             layer_prefix, message);
101     }
102 }
103 
PrintV(VkDebugReportFlagsEXT flags,VkDebugReportObjectTypeEXT object_type,uint64_t object,const char * format,va_list ap) const104 void DebugReportLogger::PrintV(VkDebugReportFlagsEXT flags,
105                                VkDebugReportObjectTypeEXT object_type,
106                                uint64_t object,
107                                const char* format,
108                                va_list ap) const {
109     char buf[1024];
110     int len = vsnprintf(buf, sizeof(buf), format, ap);
111 
112     // message truncated
113     if (len >= static_cast<int>(sizeof(buf)))
114         memcpy(buf + sizeof(buf) - 4, "...", 4);
115 
116     Message(flags, object_type, object, 0, 0, LOG_TAG, buf);
117 }
118 
CreateDebugReportCallbackEXT(VkInstance instance,const VkDebugReportCallbackCreateInfoEXT * create_info,const VkAllocationCallbacks * allocator,VkDebugReportCallbackEXT * callback)119 VkResult CreateDebugReportCallbackEXT(
120     VkInstance instance,
121     const VkDebugReportCallbackCreateInfoEXT* create_info,
122     const VkAllocationCallbacks* allocator,
123     VkDebugReportCallbackEXT* callback) {
124     const auto& driver = GetData(instance).driver;
125     VkDebugReportCallbackEXT driver_handle = VK_NULL_HANDLE;
126     if (driver.CreateDebugReportCallbackEXT) {
127         VkResult result = driver.CreateDebugReportCallbackEXT(
128             instance, create_info, allocator, &driver_handle);
129         if (result != VK_SUCCESS)
130             return result;
131     }
132 
133     auto& callbacks = GetData(instance).debug_report_callbacks;
134     auto node = callbacks.AddCallback(
135         *create_info, driver_handle,
136         (allocator) ? *allocator : GetData(instance).allocator);
137     if (!node) {
138         if (driver_handle != VK_NULL_HANDLE) {
139             driver.DestroyDebugReportCallbackEXT(instance, driver_handle,
140                                                  allocator);
141         }
142 
143         return VK_ERROR_OUT_OF_HOST_MEMORY;
144     }
145 
146     *callback = callbacks.GetHandle(node);
147 
148     return VK_SUCCESS;
149 }
150 
DestroyDebugReportCallbackEXT(VkInstance instance,VkDebugReportCallbackEXT callback,const VkAllocationCallbacks * allocator)151 void DestroyDebugReportCallbackEXT(VkInstance instance,
152                                    VkDebugReportCallbackEXT callback,
153                                    const VkAllocationCallbacks* allocator) {
154     if (callback == VK_NULL_HANDLE)
155         return;
156 
157     auto& callbacks = GetData(instance).debug_report_callbacks;
158     auto node = callbacks.FromHandle(callback);
159     auto driver_handle = callbacks.GetDriverHandle(node);
160 
161     callbacks.RemoveCallback(
162         node, (allocator) ? *allocator : GetData(instance).allocator);
163 
164     if (driver_handle != VK_NULL_HANDLE) {
165         GetData(instance).driver.DestroyDebugReportCallbackEXT(
166             instance, driver_handle, allocator);
167     }
168 }
169 
DebugReportMessageEXT(VkInstance instance,VkDebugReportFlagsEXT flags,VkDebugReportObjectTypeEXT object_type,uint64_t object,size_t location,int32_t message_code,const char * layer_prefix,const char * message)170 void DebugReportMessageEXT(VkInstance instance,
171                            VkDebugReportFlagsEXT flags,
172                            VkDebugReportObjectTypeEXT object_type,
173                            uint64_t object,
174                            size_t location,
175                            int32_t message_code,
176                            const char* layer_prefix,
177                            const char* message) {
178     if (GetData(instance).driver.DebugReportMessageEXT) {
179         GetData(instance).driver.DebugReportMessageEXT(
180             instance, flags, object_type, object, location, message_code,
181             layer_prefix, message);
182     } else {
183         GetData(instance).debug_report_callbacks.Message(
184             flags, object_type, object, location, message_code, layer_prefix,
185             message);
186     }
187 }
188 
189 }  // namespace driver
190 }  // namespace vulkan
191