1715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall/*
2715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall * Copyright 2016 The Android Open Source Project
3715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall *
4715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall * Licensed under the Apache License, Version 2.0 (the "License");
5715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall * you may not use this file except in compliance with the License.
6715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall * You may obtain a copy of the License at
7715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall *
8715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall *      http://www.apache.org/licenses/LICENSE-2.0
9715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall *
10715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall * Unless required by applicable law or agreed to in writing, software
11715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall * distributed under the License is distributed on an "AS IS" BASIS,
12715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall * See the License for the specific language governing permissions and
14715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall * limitations under the License.
15715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall */
16715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall
174a6a91647c57abb5c06cde57c57afe944f8cefa4Chia-I Wu#include "driver.h"
18715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall
19715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hallnamespace vulkan {
20622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wunamespace driver {
21715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall
22a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I WuDebugReportCallbackList::Node* DebugReportCallbackList::AddCallback(
23a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu    const VkDebugReportCallbackCreateInfoEXT& info,
24a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu    VkDebugReportCallbackEXT driver_handle,
25a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu    const VkAllocationCallbacks& allocator) {
26a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu    void* mem = allocator.pfnAllocation(allocator.pUserData, sizeof(Node),
27a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu                                        alignof(Node),
28a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu                                        VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
29a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu    if (!mem)
30a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu        return nullptr;
31715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall
32a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu    // initialize and prepend node to the list
33715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall    std::lock_guard<decltype(rwmutex_)> lock(rwmutex_);
34a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu    head_.next = new (mem) Node{head_.next, info.flags, info.pfnCallback,
35a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu                                info.pUserData, driver_handle};
36a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu
37a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu    return head_.next;
38715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall}
39715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall
40a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wuvoid DebugReportCallbackList::RemoveCallback(
41a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu    Node* node,
42a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu    const VkAllocationCallbacks& allocator) {
43a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu    // remove node from the list
44a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu    {
45a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu        std::lock_guard<decltype(rwmutex_)> lock(rwmutex_);
46a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu        Node* prev = &head_;
47a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu        while (prev && prev->next != node)
48a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu            prev = prev->next;
49a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu        prev->next = node->next;
506fecdd563f3bf94dadedc78512a1b28c08c67e07Courtney Goeltzenleuchter    }
51715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall
52a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu    allocator.pfnFree(allocator.pUserData, node);
53715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall}
54715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall
55715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hallvoid DebugReportCallbackList::Message(VkDebugReportFlagsEXT flags,
56715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall                                      VkDebugReportObjectTypeEXT object_type,
57715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall                                      uint64_t object,
58715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall                                      size_t location,
59715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall                                      int32_t message_code,
60715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall                                      const char* layer_prefix,
61b3055f34650cd066a349e1e8cba294b05513ef2eChia-I Wu                                      const char* message) const {
62715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall    std::shared_lock<decltype(rwmutex_)> lock(rwmutex_);
63b3055f34650cd066a349e1e8cba294b05513ef2eChia-I Wu    const Node* node = &head_;
64715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall    while ((node = node->next)) {
65715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall        if ((node->flags & flags) != 0) {
66715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall            node->callback(flags, object_type, object, location, message_code,
67a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu                           layer_prefix, message, node->user_data);
68715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall        }
69715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall    }
70715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall}
71715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall
72bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wuvoid DebugReportLogger::Message(VkDebugReportFlagsEXT flags,
73bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu                                VkDebugReportObjectTypeEXT object_type,
74bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu                                uint64_t object,
75bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu                                size_t location,
76bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu                                int32_t message_code,
77bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu                                const char* layer_prefix,
78bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu                                const char* message) const {
79bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu    const VkDebugReportCallbackCreateInfoEXT* info =
80bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu        reinterpret_cast<const VkDebugReportCallbackCreateInfoEXT*>(
81bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu            instance_pnext_);
82bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu    while (info) {
832676338dd692b7d1e1c276d82e6b0492db53ab2eJesse Hall        if (info->sType ==
842676338dd692b7d1e1c276d82e6b0492db53ab2eJesse Hall                VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT &&
85ede02ac245b5f2aa1139d6cb0e2dc7c0f8f290d2Chia-I Wu            (info->flags & flags) != 0) {
86bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu            info->pfnCallback(flags, object_type, object, location,
87bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu                              message_code, layer_prefix, message,
88bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu                              info->pUserData);
89bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu        }
90bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu
91bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu        info = reinterpret_cast<const VkDebugReportCallbackCreateInfoEXT*>(
92bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu            info->pNext);
93bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu    }
94bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu
95bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu    if (callbacks_) {
96bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu        callbacks_->Message(flags, object_type, object, location, message_code,
97bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu                            layer_prefix, message);
98bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu    }
99bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu}
100bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu
101bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wuvoid DebugReportLogger::PrintV(VkDebugReportFlagsEXT flags,
102bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu                               VkDebugReportObjectTypeEXT object_type,
103bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu                               uint64_t object,
104bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu                               const char* format,
105bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu                               va_list ap) const {
106bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu    char buf[1024];
107bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu    int len = vsnprintf(buf, sizeof(buf), format, ap);
108bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu
109bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu    // message truncated
110bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu    if (len >= static_cast<int>(sizeof(buf)))
111bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu        memcpy(buf + sizeof(buf) - 4, "...", 4);
112bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu
113bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu    Message(flags, object_type, object, 0, 0, LOG_TAG, buf);
114bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu}
115bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu
116622622377a1ac71a81a88e335f170c4a08835f06Chia-I WuVkResult CreateDebugReportCallbackEXT(
117715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall    VkInstance instance,
118715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall    const VkDebugReportCallbackCreateInfoEXT* create_info,
119715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall    const VkAllocationCallbacks* allocator,
120715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall    VkDebugReportCallbackEXT* callback) {
121a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu    const auto& driver = GetData(instance).driver;
122a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu    VkDebugReportCallbackEXT driver_handle = VK_NULL_HANDLE;
123a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu    if (driver.CreateDebugReportCallbackEXT) {
124a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu        VkResult result = driver.CreateDebugReportCallbackEXT(
125a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu            instance, create_info, allocator, &driver_handle);
126a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu        if (result != VK_SUCCESS)
127a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu            return result;
128a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu    }
129a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu
130a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu    auto& callbacks = GetData(instance).debug_report_callbacks;
131a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu    auto node = callbacks.AddCallback(
132a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu        *create_info, driver_handle,
133a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu        (allocator) ? *allocator : GetData(instance).allocator);
134a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu    if (!node) {
135a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu        if (driver_handle != VK_NULL_HANDLE) {
136a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu            driver.DestroyDebugReportCallbackEXT(instance, driver_handle,
137a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu                                                 allocator);
138a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu        }
139a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu
140a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu        return VK_ERROR_OUT_OF_HOST_MEMORY;
141a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu    }
142a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu
143a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu    *callback = callbacks.GetHandle(node);
144a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu
145a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu    return VK_SUCCESS;
146715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall}
147715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall
148622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wuvoid DestroyDebugReportCallbackEXT(VkInstance instance,
149622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                                   VkDebugReportCallbackEXT callback,
150622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                                   const VkAllocationCallbacks* allocator) {
151a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu    if (callback == VK_NULL_HANDLE)
152a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu        return;
153a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu
154a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu    auto& callbacks = GetData(instance).debug_report_callbacks;
155a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu    auto node = callbacks.FromHandle(callback);
156a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu    auto driver_handle = callbacks.GetDriverHandle(node);
157a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu
158a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu    callbacks.RemoveCallback(
159a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu        node, (allocator) ? *allocator : GetData(instance).allocator);
160a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu
161a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu    if (driver_handle != VK_NULL_HANDLE) {
162a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu        GetData(instance).driver.DestroyDebugReportCallbackEXT(
163a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu            instance, driver_handle, allocator);
164a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu    }
165715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall}
166715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall
167622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wuvoid DebugReportMessageEXT(VkInstance instance,
168622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                           VkDebugReportFlagsEXT flags,
169622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                           VkDebugReportObjectTypeEXT object_type,
170622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                           uint64_t object,
171622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                           size_t location,
172622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                           int32_t message_code,
173622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                           const char* layer_prefix,
174622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu                           const char* message) {
1754a6a91647c57abb5c06cde57c57afe944f8cefa4Chia-I Wu    if (GetData(instance).driver.DebugReportMessageEXT) {
1764a6a91647c57abb5c06cde57c57afe944f8cefa4Chia-I Wu        GetData(instance).driver.DebugReportMessageEXT(
1774a6a91647c57abb5c06cde57c57afe944f8cefa4Chia-I Wu            instance, flags, object_type, object, location, message_code,
1784a6a91647c57abb5c06cde57c57afe944f8cefa4Chia-I Wu            layer_prefix, message);
1792e6736699471dbe7ec185667240089dcbccdd9bdChia-I Wu    } else {
1802e6736699471dbe7ec185667240089dcbccdd9bdChia-I Wu        GetData(instance).debug_report_callbacks.Message(
1812e6736699471dbe7ec185667240089dcbccdd9bdChia-I Wu            flags, object_type, object, location, message_code, layer_prefix,
1822e6736699471dbe7ec185667240089dcbccdd9bdChia-I Wu            message);
1836fecdd563f3bf94dadedc78512a1b28c08c67e07Courtney Goeltzenleuchter    }
184715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall}
185715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall
186622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu}  // namespace driver
187715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall}  // namespace vulkan
188