debug_report.cpp revision 6fecdd563f3bf94dadedc78512a1b28c08c67e07
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 "loader.h"
18
19namespace vulkan {
20
21VkResult DebugReportCallbackList::CreateCallback(
22    VkInstance instance,
23    const VkDebugReportCallbackCreateInfoEXT* create_info,
24    const VkAllocationCallbacks* allocator,
25    VkDebugReportCallbackEXT* callback) {
26    VkDebugReportCallbackEXT driver_callback = VK_NULL_HANDLE;
27
28    if (GetDriverDispatch(instance).CreateDebugReportCallbackEXT) {
29        VkResult result =
30            GetDriverDispatch(instance).CreateDebugReportCallbackEXT(
31                GetDriverInstance(instance), create_info, allocator,
32                &driver_callback);
33        if (result != VK_SUCCESS)
34            return result;
35    }
36
37    const VkAllocationCallbacks* alloc =
38        allocator ? allocator : GetAllocator(instance);
39    void* mem =
40        alloc->pfnAllocation(alloc->pUserData, sizeof(Node), alignof(Node),
41                             VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
42    if (!mem) {
43        if (GetDriverDispatch(instance).DestroyDebugReportCallbackEXT) {
44            GetDriverDispatch(instance).DestroyDebugReportCallbackEXT(
45                GetDriverInstance(instance), driver_callback, allocator);
46        }
47        return VK_ERROR_OUT_OF_HOST_MEMORY;
48    }
49
50    std::lock_guard<decltype(rwmutex_)> lock(rwmutex_);
51    head_.next =
52        new (mem) Node{head_.next, create_info->flags, create_info->pfnCallback,
53                       create_info->pUserData, driver_callback};
54    *callback =
55        VkDebugReportCallbackEXT(reinterpret_cast<uintptr_t>(head_.next));
56    return VK_SUCCESS;
57}
58
59void DebugReportCallbackList::DestroyCallback(
60    VkInstance instance,
61    VkDebugReportCallbackEXT callback,
62    const VkAllocationCallbacks* allocator) {
63    Node* node = reinterpret_cast<Node*>(uintptr_t(callback));
64    std::unique_lock<decltype(rwmutex_)> lock(rwmutex_);
65    Node* prev = &head_;
66    while (prev && prev->next != node)
67        prev = prev->next;
68    prev->next = node->next;
69    lock.unlock();
70
71    if (GetDriverDispatch(instance).DestroyDebugReportCallbackEXT) {
72        GetDriverDispatch(instance).DestroyDebugReportCallbackEXT(
73            GetDriverInstance(instance), node->driver_callback, allocator);
74    }
75
76    const VkAllocationCallbacks* alloc =
77        allocator ? allocator : GetAllocator(instance);
78    alloc->pfnFree(alloc->pUserData, node);
79}
80
81void DebugReportCallbackList::Message(VkDebugReportFlagsEXT flags,
82                                      VkDebugReportObjectTypeEXT object_type,
83                                      uint64_t object,
84                                      size_t location,
85                                      int32_t message_code,
86                                      const char* layer_prefix,
87                                      const char* message) {
88    std::shared_lock<decltype(rwmutex_)> lock(rwmutex_);
89    Node* node = &head_;
90    while ((node = node->next)) {
91        if ((node->flags & flags) != 0) {
92            node->callback(flags, object_type, object, location, message_code,
93                           layer_prefix, message, node->data);
94        }
95    }
96}
97
98VkResult CreateDebugReportCallbackEXT_Bottom(
99    VkInstance instance,
100    const VkDebugReportCallbackCreateInfoEXT* create_info,
101    const VkAllocationCallbacks* allocator,
102    VkDebugReportCallbackEXT* callback) {
103    return GetDebugReportCallbacks(instance).CreateCallback(
104        instance, create_info, allocator, callback);
105}
106
107void DestroyDebugReportCallbackEXT_Bottom(
108    VkInstance instance,
109    VkDebugReportCallbackEXT callback,
110    const VkAllocationCallbacks* allocator) {
111    if (callback)
112        GetDebugReportCallbacks(instance).DestroyCallback(instance, callback,
113                                                          allocator);
114}
115
116void DebugReportMessageEXT_Bottom(VkInstance instance,
117                                  VkDebugReportFlagsEXT flags,
118                                  VkDebugReportObjectTypeEXT object_type,
119                                  uint64_t object,
120                                  size_t location,
121                                  int32_t message_code,
122                                  const char* layer_prefix,
123                                  const char* message) {
124    if (GetDriverDispatch(instance).DebugReportMessageEXT) {
125        GetDriverDispatch(instance).DebugReportMessageEXT(
126            GetDriverInstance(instance), flags, object_type, object, location,
127            message_code, layer_prefix, message);
128    }
129    GetDebugReportCallbacks(instance).Message(flags, object_type, object,
130                                              location, message_code,
131                                              layer_prefix, message);
132}
133
134}  // namespace vulkan
135