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 17715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall#ifndef LIBVULKAN_DEBUG_REPORT_H 18715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall#define LIBVULKAN_DEBUG_REPORT_H 1 19715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall 20bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu#include <stdarg.h> 21715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall#include <shared_mutex> 22bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu#include <vulkan/vulkan.h> 23715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall 24715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hallnamespace vulkan { 25622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wunamespace driver { 26715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall 27715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall// clang-format off 28622622377a1ac71a81a88e335f170c4a08835f06Chia-I WuVKAPI_ATTR VkResult CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback); 29622622377a1ac71a81a88e335f170c4a08835f06Chia-I WuVKAPI_ATTR void DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks* pAllocator); 30622622377a1ac71a81a88e335f170c4a08835f06Chia-I WuVKAPI_ATTR void DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage); 31715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall// clang-format on 32715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall 33715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hallclass DebugReportCallbackList { 34a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu private: 35a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu // forward declaration 36a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu struct Node; 37a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu 38715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall public: 39715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall DebugReportCallbackList() 40715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall : head_{nullptr, 0, nullptr, nullptr, VK_NULL_HANDLE} {} 41715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall DebugReportCallbackList(const DebugReportCallbackList&) = delete; 42715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall DebugReportCallbackList& operator=(const DebugReportCallbackList&) = delete; 43715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall ~DebugReportCallbackList() = default; 44715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall 45a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu Node* AddCallback(const VkDebugReportCallbackCreateInfoEXT& info, 46a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu VkDebugReportCallbackEXT driver_handle, 47a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu const VkAllocationCallbacks& allocator); 48a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu void RemoveCallback(Node* node, const VkAllocationCallbacks& allocator); 49a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu 50715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall void Message(VkDebugReportFlagsEXT flags, 51715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall VkDebugReportObjectTypeEXT object_type, 52715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall uint64_t object, 53715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall size_t location, 54715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall int32_t message_code, 55715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall const char* layer_prefix, 56b3055f34650cd066a349e1e8cba294b05513ef2eChia-I Wu const char* message) const; 57715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall 58a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu static Node* FromHandle(VkDebugReportCallbackEXT handle) { 59a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu return reinterpret_cast<Node*>(uintptr_t(handle)); 60a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu } 61a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu 62a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu static VkDebugReportCallbackEXT GetHandle(const Node* node) { 63a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu return VkDebugReportCallbackEXT(reinterpret_cast<uintptr_t>(node)); 64a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu } 65a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu 66a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu static VkDebugReportCallbackEXT GetDriverHandle(const Node* node) { 67a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu return node->driver_handle; 68a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu } 69a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu 70715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall private: 71715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall struct Node { 72715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall Node* next; 73a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu 74715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall VkDebugReportFlagsEXT flags; 75715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall PFN_vkDebugReportCallbackEXT callback; 76a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu void* user_data; 77a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu 78a0d40aaf12435fe82bc9c1612dbe97ea2a60da31Chia-I Wu VkDebugReportCallbackEXT driver_handle; 79715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall }; 80715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall 81715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall // TODO(jessehall): replace with std::shared_mutex when available in libc++ 82b3055f34650cd066a349e1e8cba294b05513ef2eChia-I Wu mutable std::shared_timed_mutex rwmutex_; 83715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall Node head_; 84715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall}; 85715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall 86bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wuclass DebugReportLogger { 87bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu public: 88d56988d1fc3a42f5728f2ae707cc8faf73860745Chih-Hung Hsieh explicit DebugReportLogger(const VkInstanceCreateInfo& info) 89bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu : instance_pnext_(info.pNext), callbacks_(nullptr) {} 90d56988d1fc3a42f5728f2ae707cc8faf73860745Chih-Hung Hsieh explicit DebugReportLogger(const DebugReportCallbackList& callbacks) 91bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu : instance_pnext_(nullptr), callbacks_(&callbacks) {} 92bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu 93bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu void Message(VkDebugReportFlagsEXT flags, 94bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu VkDebugReportObjectTypeEXT object_type, 95bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu uint64_t object, 96bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu size_t location, 97bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu int32_t message_code, 98bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu const char* layer_prefix, 99bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu const char* message) const; 100bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu 101bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu#define DEBUG_REPORT_LOGGER_PRINTF(fmt, args) \ 102bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu __attribute__((format(printf, (fmt) + 1, (args) + 1))) 103bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu template <typename ObjectType> 104bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu void Info(ObjectType object, const char* format, ...) const 105bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu DEBUG_REPORT_LOGGER_PRINTF(2, 3) { 106bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu va_list ap; 107bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu va_start(ap, format); 108bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu PrintV(VK_DEBUG_REPORT_INFORMATION_BIT_EXT, GetObjectType(object), 109bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu GetObjectUInt64(object), format, ap); 110bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu va_end(ap); 111bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu } 112bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu 113bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu template <typename ObjectType> 114bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu void Warn(ObjectType object, const char* format, ...) const 115bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu DEBUG_REPORT_LOGGER_PRINTF(2, 3) { 116bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu va_list ap; 117bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu va_start(ap, format); 118bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu PrintV(VK_DEBUG_REPORT_WARNING_BIT_EXT, GetObjectType(object), 119bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu GetObjectUInt64(object), format, ap); 120bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu va_end(ap); 121bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu } 122bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu 123bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu template <typename ObjectType> 124bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu void Err(ObjectType object, const char* format, ...) const 125bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu DEBUG_REPORT_LOGGER_PRINTF(2, 3) { 126bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu va_list ap; 127bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu va_start(ap, format); 128bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu PrintV(VK_DEBUG_REPORT_ERROR_BIT_EXT, GetObjectType(object), 129bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu GetObjectUInt64(object), format, ap); 130bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu va_end(ap); 131bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu } 132bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu 133bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu private: 134bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu template <typename ObjectType> 135bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu static VkDebugReportObjectTypeEXT GetObjectType(ObjectType) { 136bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu if (std::is_same<ObjectType, VkInstance>::value) 137bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu return VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT; 138bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu else if (std::is_same<ObjectType, VkPhysicalDevice>::value) 139bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu return VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT; 140bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu else if (std::is_same<ObjectType, VkDevice>::value) 141bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu return VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT; 142bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu else 143bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu return VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT; 144bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu } 145bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu 146bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu template <typename ObjectType> 147bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu static uint64_t GetObjectUInt64(ObjectType object) { 148bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu return uint64_t(object); 149bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu } 150bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu 151bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu#define DEBUG_REPORT_LOGGER_VPRINTF(fmt) \ 152bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu __attribute__((format(printf, (fmt) + 1, 0))) 153bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu void PrintV(VkDebugReportFlagsEXT flags, 154bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu VkDebugReportObjectTypeEXT object_type, 155bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu uint64_t object, 156bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu const char* format, 157bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu va_list ap) const DEBUG_REPORT_LOGGER_VPRINTF(4); 158bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu 159bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu const void* const instance_pnext_; 160bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu const DebugReportCallbackList* const callbacks_; 161bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu}; 162bc011fc4d78442d1f0167b04aea3484c62e0a92bChia-I Wu 163622622377a1ac71a81a88e335f170c4a08835f06Chia-I Wu} // namespace driver 164715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall} // namespace vulkan 165715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall 166715b86ac7d0853131b375ff786c87d8d87a762a1Jesse Hall#endif // LIBVULKAN_DEBUG_REPORT_H 167