2 * Copyright 2016 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 DebugReportCallbackList::Node* DebugReportCallbackList::AddCallback(
23 const VkDebugReportCallbackCreateInfoEXT& info,
24 VkDebugReportCallbackEXT driver_handle,
25 const VkAllocationCallbacks& allocator) {
26 void* mem = allocator.pfnAllocation(allocator.pUserData, sizeof(Node),
28 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
32 // initialize and prepend node to the list
33 std::lock_guard<decltype(rwmutex_)> lock(rwmutex_);
34 head_.next = new (mem) Node{head_.next, info.flags, info.pfnCallback,
35 info.pUserData, driver_handle};
40 void DebugReportCallbackList::RemoveCallback(
42 const VkAllocationCallbacks& allocator) {
43 // remove node from the list
45 std::lock_guard<decltype(rwmutex_)> lock(rwmutex_);
47 while (prev && prev->next != node)
49 prev->next = node->next;
52 allocator.pfnFree(allocator.pUserData, node);
55 void DebugReportCallbackList::Message(VkDebugReportFlagsEXT flags,
56 VkDebugReportObjectTypeEXT object_type,
60 const char* layer_prefix,
61 const char* message) const {
62 std::shared_lock<decltype(rwmutex_)> lock(rwmutex_);
63 const Node* node = &head_;
64 while ((node = node->next)) {
65 if ((node->flags & flags) != 0) {
66 node->callback(flags, object_type, object, location, message_code,
67 layer_prefix, message, node->user_data);
72 void DebugReportLogger::Message(VkDebugReportFlagsEXT flags,
73 VkDebugReportObjectTypeEXT object_type,
77 const char* layer_prefix,
78 const char* message) const {
79 const VkDebugReportCallbackCreateInfoEXT* info =
80 reinterpret_cast<const VkDebugReportCallbackCreateInfoEXT*>(
83 if (info->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT) {
84 info->pfnCallback(flags, object_type, object, location,
85 message_code, layer_prefix, message,
89 info = reinterpret_cast<const VkDebugReportCallbackCreateInfoEXT*>(
94 callbacks_->Message(flags, object_type, object, location, message_code,
95 layer_prefix, message);
99 void DebugReportLogger::PrintV(VkDebugReportFlagsEXT flags,
100 VkDebugReportObjectTypeEXT object_type,
105 int len = vsnprintf(buf, sizeof(buf), format, ap);
108 if (len >= static_cast<int>(sizeof(buf)))
109 memcpy(buf + sizeof(buf) - 4, "...", 4);
111 Message(flags, object_type, object, 0, 0, LOG_TAG, buf);
114 VkResult CreateDebugReportCallbackEXT(
116 const VkDebugReportCallbackCreateInfoEXT* create_info,
117 const VkAllocationCallbacks* allocator,
118 VkDebugReportCallbackEXT* callback) {
119 const auto& driver = GetData(instance).driver;
120 VkDebugReportCallbackEXT driver_handle = VK_NULL_HANDLE;
121 if (driver.CreateDebugReportCallbackEXT) {
122 VkResult result = driver.CreateDebugReportCallbackEXT(
123 instance, create_info, allocator, &driver_handle);
124 if (result != VK_SUCCESS)
128 auto& callbacks = GetData(instance).debug_report_callbacks;
129 auto node = callbacks.AddCallback(
130 *create_info, driver_handle,
131 (allocator) ? *allocator : GetData(instance).allocator);
133 if (driver_handle != VK_NULL_HANDLE) {
134 driver.DestroyDebugReportCallbackEXT(instance, driver_handle,
138 return VK_ERROR_OUT_OF_HOST_MEMORY;
141 *callback = callbacks.GetHandle(node);
146 void DestroyDebugReportCallbackEXT(VkInstance instance,
147 VkDebugReportCallbackEXT callback,
148 const VkAllocationCallbacks* allocator) {
149 if (callback == VK_NULL_HANDLE)
152 auto& callbacks = GetData(instance).debug_report_callbacks;
153 auto node = callbacks.FromHandle(callback);
154 auto driver_handle = callbacks.GetDriverHandle(node);
156 callbacks.RemoveCallback(
157 node, (allocator) ? *allocator : GetData(instance).allocator);
159 if (driver_handle != VK_NULL_HANDLE) {
160 GetData(instance).driver.DestroyDebugReportCallbackEXT(
161 instance, driver_handle, allocator);
165 void DebugReportMessageEXT(VkInstance instance,
166 VkDebugReportFlagsEXT flags,
167 VkDebugReportObjectTypeEXT object_type,
170 int32_t message_code,
171 const char* layer_prefix,
172 const char* message) {
173 if (GetData(instance).driver.DebugReportMessageEXT) {
174 GetData(instance).driver.DebugReportMessageEXT(
175 instance, flags, object_type, object, location, message_code,
176 layer_prefix, message);
178 GetData(instance).debug_report_callbacks.Message(
179 flags, object_type, object, location, message_code, layer_prefix,
184 } // namespace driver
185 } // namespace vulkan