blob: fbb54586743b6e35bb746f1f6d0cb74e0496c781 [file] [log] [blame]
Jesse Hall715b86a2016-01-16 16:34:29 -08001/*
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
Chia-I Wu4a6a9162016-03-26 07:17:34 +080017#include "driver.h"
Jesse Hall715b86a2016-01-16 16:34:29 -080018
19namespace vulkan {
Chia-I Wu62262232016-03-26 07:06:44 +080020namespace driver {
Jesse Hall715b86a2016-01-16 16:34:29 -080021
Chia-I Wua0d40aa2016-05-05 12:43:03 +080022DebugReportCallbackList::Node* DebugReportCallbackList::AddCallback(
23 const VkDebugReportCallbackCreateInfoEXT& info,
24 VkDebugReportCallbackEXT driver_handle,
25 const VkAllocationCallbacks& allocator) {
26 void* mem = allocator.pfnAllocation(allocator.pUserData, sizeof(Node),
27 alignof(Node),
28 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
29 if (!mem)
30 return nullptr;
Courtney Goeltzenleuchter6fecdd52016-02-03 15:14:46 -070031
Chia-I Wua0d40aa2016-05-05 12:43:03 +080032 // initialize and prepend node to the list
Jesse Hall715b86a2016-01-16 16:34:29 -080033 std::lock_guard<decltype(rwmutex_)> lock(rwmutex_);
Chia-I Wua0d40aa2016-05-05 12:43:03 +080034 head_.next = new (mem) Node{head_.next, info.flags, info.pfnCallback,
35 info.pUserData, driver_handle};
36
37 return head_.next;
Jesse Hall715b86a2016-01-16 16:34:29 -080038}
39
Chia-I Wua0d40aa2016-05-05 12:43:03 +080040void DebugReportCallbackList::RemoveCallback(
41 Node* node,
42 const VkAllocationCallbacks& allocator) {
43 // remove node from the list
44 {
45 std::lock_guard<decltype(rwmutex_)> lock(rwmutex_);
46 Node* prev = &head_;
47 while (prev && prev->next != node)
48 prev = prev->next;
49 prev->next = node->next;
Courtney Goeltzenleuchter6fecdd52016-02-03 15:14:46 -070050 }
Jesse Hall715b86a2016-01-16 16:34:29 -080051
Chia-I Wua0d40aa2016-05-05 12:43:03 +080052 allocator.pfnFree(allocator.pUserData, node);
Jesse Hall715b86a2016-01-16 16:34:29 -080053}
54
55void DebugReportCallbackList::Message(VkDebugReportFlagsEXT flags,
56 VkDebugReportObjectTypeEXT object_type,
57 uint64_t object,
58 size_t location,
59 int32_t message_code,
60 const char* layer_prefix,
Chia-I Wub3055f32016-05-03 12:04:47 +080061 const char* message) const {
Jesse Hall715b86a2016-01-16 16:34:29 -080062 std::shared_lock<decltype(rwmutex_)> lock(rwmutex_);
Chia-I Wub3055f32016-05-03 12:04:47 +080063 const Node* node = &head_;
Jesse Hall715b86a2016-01-16 16:34:29 -080064 while ((node = node->next)) {
65 if ((node->flags & flags) != 0) {
66 node->callback(flags, object_type, object, location, message_code,
Chia-I Wua0d40aa2016-05-05 12:43:03 +080067 layer_prefix, message, node->user_data);
Jesse Hall715b86a2016-01-16 16:34:29 -080068 }
69 }
70}
71
Chia-I Wubc011fc2016-05-03 12:19:55 +080072void DebugReportLogger::Message(VkDebugReportFlagsEXT flags,
73 VkDebugReportObjectTypeEXT object_type,
74 uint64_t object,
75 size_t location,
76 int32_t message_code,
77 const char* layer_prefix,
78 const char* message) const {
79 const VkDebugReportCallbackCreateInfoEXT* info =
80 reinterpret_cast<const VkDebugReportCallbackCreateInfoEXT*>(
81 instance_pnext_);
82 while (info) {
Chia-I Wuede02ac2016-05-13 10:45:59 +080083 if (info->sType == VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT &&
84 (info->flags & flags) != 0) {
Chia-I Wubc011fc2016-05-03 12:19:55 +080085 info->pfnCallback(flags, object_type, object, location,
86 message_code, layer_prefix, message,
87 info->pUserData);
88 }
89
90 info = reinterpret_cast<const VkDebugReportCallbackCreateInfoEXT*>(
91 info->pNext);
92 }
93
94 if (callbacks_) {
95 callbacks_->Message(flags, object_type, object, location, message_code,
96 layer_prefix, message);
97 }
98}
99
100void DebugReportLogger::PrintV(VkDebugReportFlagsEXT flags,
101 VkDebugReportObjectTypeEXT object_type,
102 uint64_t object,
103 const char* format,
104 va_list ap) const {
105 char buf[1024];
106 int len = vsnprintf(buf, sizeof(buf), format, ap);
107
108 // message truncated
109 if (len >= static_cast<int>(sizeof(buf)))
110 memcpy(buf + sizeof(buf) - 4, "...", 4);
111
112 Message(flags, object_type, object, 0, 0, LOG_TAG, buf);
113}
114
Chia-I Wu62262232016-03-26 07:06:44 +0800115VkResult CreateDebugReportCallbackEXT(
Jesse Hall715b86a2016-01-16 16:34:29 -0800116 VkInstance instance,
117 const VkDebugReportCallbackCreateInfoEXT* create_info,
118 const VkAllocationCallbacks* allocator,
119 VkDebugReportCallbackEXT* callback) {
Chia-I Wua0d40aa2016-05-05 12:43:03 +0800120 const auto& driver = GetData(instance).driver;
121 VkDebugReportCallbackEXT driver_handle = VK_NULL_HANDLE;
122 if (driver.CreateDebugReportCallbackEXT) {
123 VkResult result = driver.CreateDebugReportCallbackEXT(
124 instance, create_info, allocator, &driver_handle);
125 if (result != VK_SUCCESS)
126 return result;
127 }
128
129 auto& callbacks = GetData(instance).debug_report_callbacks;
130 auto node = callbacks.AddCallback(
131 *create_info, driver_handle,
132 (allocator) ? *allocator : GetData(instance).allocator);
133 if (!node) {
134 if (driver_handle != VK_NULL_HANDLE) {
135 driver.DestroyDebugReportCallbackEXT(instance, driver_handle,
136 allocator);
137 }
138
139 return VK_ERROR_OUT_OF_HOST_MEMORY;
140 }
141
142 *callback = callbacks.GetHandle(node);
143
144 return VK_SUCCESS;
Jesse Hall715b86a2016-01-16 16:34:29 -0800145}
146
Chia-I Wu62262232016-03-26 07:06:44 +0800147void DestroyDebugReportCallbackEXT(VkInstance instance,
148 VkDebugReportCallbackEXT callback,
149 const VkAllocationCallbacks* allocator) {
Chia-I Wua0d40aa2016-05-05 12:43:03 +0800150 if (callback == VK_NULL_HANDLE)
151 return;
152
153 auto& callbacks = GetData(instance).debug_report_callbacks;
154 auto node = callbacks.FromHandle(callback);
155 auto driver_handle = callbacks.GetDriverHandle(node);
156
157 callbacks.RemoveCallback(
158 node, (allocator) ? *allocator : GetData(instance).allocator);
159
160 if (driver_handle != VK_NULL_HANDLE) {
161 GetData(instance).driver.DestroyDebugReportCallbackEXT(
162 instance, driver_handle, allocator);
163 }
Jesse Hall715b86a2016-01-16 16:34:29 -0800164}
165
Chia-I Wu62262232016-03-26 07:06:44 +0800166void DebugReportMessageEXT(VkInstance instance,
167 VkDebugReportFlagsEXT flags,
168 VkDebugReportObjectTypeEXT object_type,
169 uint64_t object,
170 size_t location,
171 int32_t message_code,
172 const char* layer_prefix,
173 const char* message) {
Chia-I Wu4a6a9162016-03-26 07:17:34 +0800174 if (GetData(instance).driver.DebugReportMessageEXT) {
175 GetData(instance).driver.DebugReportMessageEXT(
176 instance, flags, object_type, object, location, message_code,
177 layer_prefix, message);
Chia-I Wu2e673662016-05-03 12:06:21 +0800178 } else {
179 GetData(instance).debug_report_callbacks.Message(
180 flags, object_type, object, location, message_code, layer_prefix,
181 message);
Courtney Goeltzenleuchter6fecdd52016-02-03 15:14:46 -0700182 }
Jesse Hall715b86a2016-01-16 16:34:29 -0800183}
184
Chia-I Wu62262232016-03-26 07:06:44 +0800185} // namespace driver
Jesse Hall715b86a2016-01-16 16:34:29 -0800186} // namespace vulkan