You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
189 lines
6.8 KiB
189 lines
6.8 KiB
/*
|
|
* Copyright 2016 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "driver.h"
|
|
|
|
namespace vulkan {
|
|
namespace driver {
|
|
|
|
DebugReportCallbackList::Node* DebugReportCallbackList::AddCallback(
|
|
const VkDebugReportCallbackCreateInfoEXT& info,
|
|
VkDebugReportCallbackEXT driver_handle,
|
|
const VkAllocationCallbacks& allocator) {
|
|
void* mem = allocator.pfnAllocation(allocator.pUserData, sizeof(Node),
|
|
alignof(Node),
|
|
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
|
if (!mem)
|
|
return nullptr;
|
|
|
|
// initialize and prepend node to the list
|
|
std::lock_guard<decltype(rwmutex_)> lock(rwmutex_);
|
|
head_.next = new (mem) Node{head_.next, info.flags, info.pfnCallback,
|
|
info.pUserData, driver_handle};
|
|
|
|
return head_.next;
|
|
}
|
|
|
|
void DebugReportCallbackList::RemoveCallback(
|
|
Node* node,
|
|
const VkAllocationCallbacks& allocator) {
|
|
// remove node from the list
|
|
{
|
|
std::lock_guard<decltype(rwmutex_)> lock(rwmutex_);
|
|
Node* prev = &head_;
|
|
while (prev && prev->next != node)
|
|
prev = prev->next;
|
|
if (prev)
|
|
prev->next = node->next;
|
|
}
|
|
|
|
allocator.pfnFree(allocator.pUserData, node);
|
|
}
|
|
|
|
void DebugReportCallbackList::Message(VkDebugReportFlagsEXT flags,
|
|
VkDebugReportObjectTypeEXT object_type,
|
|
uint64_t object,
|
|
size_t location,
|
|
int32_t message_code,
|
|
const char* layer_prefix,
|
|
const char* message) const {
|
|
std::shared_lock<decltype(rwmutex_)> lock(rwmutex_);
|
|
const Node* node = &head_;
|
|
while ((node = node->next)) {
|
|
if ((node->flags & flags) != 0) {
|
|
node->callback(flags, object_type, object, location, message_code,
|
|
layer_prefix, message, node->user_data);
|
|
}
|
|
}
|
|
}
|
|
|
|
void DebugReportLogger::Message(VkDebugReportFlagsEXT flags,
|
|
VkDebugReportObjectTypeEXT object_type,
|
|
uint64_t object,
|
|
size_t location,
|
|
int32_t message_code,
|
|
const char* layer_prefix,
|
|
const char* message) const {
|
|
const VkDebugReportCallbackCreateInfoEXT* info =
|
|
reinterpret_cast<const VkDebugReportCallbackCreateInfoEXT*>(
|
|
instance_pnext_);
|
|
while (info) {
|
|
if (info->sType ==
|
|
VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT &&
|
|
(info->flags & flags) != 0) {
|
|
info->pfnCallback(flags, object_type, object, location,
|
|
message_code, layer_prefix, message,
|
|
info->pUserData);
|
|
}
|
|
|
|
info = reinterpret_cast<const VkDebugReportCallbackCreateInfoEXT*>(
|
|
info->pNext);
|
|
}
|
|
|
|
if (callbacks_) {
|
|
callbacks_->Message(flags, object_type, object, location, message_code,
|
|
layer_prefix, message);
|
|
}
|
|
}
|
|
|
|
void DebugReportLogger::PrintV(VkDebugReportFlagsEXT flags,
|
|
VkDebugReportObjectTypeEXT object_type,
|
|
uint64_t object,
|
|
const char* format,
|
|
va_list ap) const {
|
|
char buf[1024];
|
|
int len = vsnprintf(buf, sizeof(buf), format, ap);
|
|
|
|
// message truncated
|
|
if (len >= static_cast<int>(sizeof(buf)))
|
|
memcpy(buf + sizeof(buf) - 4, "...", 4);
|
|
|
|
Message(flags, object_type, object, 0, 0, LOG_TAG, buf);
|
|
}
|
|
|
|
VkResult CreateDebugReportCallbackEXT(
|
|
VkInstance instance,
|
|
const VkDebugReportCallbackCreateInfoEXT* create_info,
|
|
const VkAllocationCallbacks* allocator,
|
|
VkDebugReportCallbackEXT* callback) {
|
|
const auto& driver = GetData(instance).driver;
|
|
VkDebugReportCallbackEXT driver_handle = VK_NULL_HANDLE;
|
|
if (driver.CreateDebugReportCallbackEXT) {
|
|
VkResult result = driver.CreateDebugReportCallbackEXT(
|
|
instance, create_info, allocator, &driver_handle);
|
|
if (result != VK_SUCCESS)
|
|
return result;
|
|
}
|
|
|
|
auto& callbacks = GetData(instance).debug_report_callbacks;
|
|
auto node = callbacks.AddCallback(
|
|
*create_info, driver_handle,
|
|
(allocator) ? *allocator : GetData(instance).allocator);
|
|
if (!node) {
|
|
if (driver_handle != VK_NULL_HANDLE) {
|
|
driver.DestroyDebugReportCallbackEXT(instance, driver_handle,
|
|
allocator);
|
|
}
|
|
|
|
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
}
|
|
|
|
*callback = callbacks.GetHandle(node);
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
void DestroyDebugReportCallbackEXT(VkInstance instance,
|
|
VkDebugReportCallbackEXT callback,
|
|
const VkAllocationCallbacks* allocator) {
|
|
if (callback == VK_NULL_HANDLE)
|
|
return;
|
|
|
|
auto& callbacks = GetData(instance).debug_report_callbacks;
|
|
auto node = callbacks.FromHandle(callback);
|
|
auto driver_handle = callbacks.GetDriverHandle(node);
|
|
|
|
callbacks.RemoveCallback(
|
|
node, (allocator) ? *allocator : GetData(instance).allocator);
|
|
|
|
if (driver_handle != VK_NULL_HANDLE) {
|
|
GetData(instance).driver.DestroyDebugReportCallbackEXT(
|
|
instance, driver_handle, allocator);
|
|
}
|
|
}
|
|
|
|
void 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) {
|
|
if (GetData(instance).driver.DebugReportMessageEXT) {
|
|
GetData(instance).driver.DebugReportMessageEXT(
|
|
instance, flags, object_type, object, location, message_code,
|
|
layer_prefix, message);
|
|
} else {
|
|
GetData(instance).debug_report_callbacks.Message(
|
|
flags, object_type, object, location, message_code, layer_prefix,
|
|
message);
|
|
}
|
|
}
|
|
|
|
} // namespace driver
|
|
} // namespace vulkan
|