diff options
| -rw-r--r-- | vulkan/libvulkan/api.cpp | 35 | ||||
| -rw-r--r-- | vulkan/libvulkan/api_gen.cpp | 61 | ||||
| -rw-r--r-- | vulkan/libvulkan/code-generator.tmpl | 32 | ||||
| -rw-r--r-- | vulkan/libvulkan/debug_report.cpp | 174 | ||||
| -rw-r--r-- | vulkan/libvulkan/debug_report.h | 119 | ||||
| -rw-r--r-- | vulkan/libvulkan/driver.cpp | 19 | ||||
| -rw-r--r-- | vulkan/libvulkan/driver.h | 14 | ||||
| -rw-r--r-- | vulkan/libvulkan/driver_gen.cpp | 10 |
8 files changed, 320 insertions, 144 deletions
diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp index 28b172d4fe..805366820f 100644 --- a/vulkan/libvulkan/api.cpp +++ b/vulkan/libvulkan/api.cpp @@ -394,7 +394,9 @@ class LayerChain { uint32_t& count); private: - LayerChain(bool is_instance, const VkAllocationCallbacks& allocator); + LayerChain(bool is_instance, + const driver::DebugReportLogger& logger, + const VkAllocationCallbacks& allocator); ~LayerChain(); VkResult ActivateLayers(const char* const* layer_names, @@ -455,6 +457,7 @@ class LayerChain { void* user_data); const bool is_instance_; + const driver::DebugReportLogger& logger_; const VkAllocationCallbacks& allocator_; OverrideLayerNames override_layers_; @@ -476,8 +479,11 @@ class LayerChain { std::bitset<driver::ProcHook::EXTENSION_COUNT> enabled_extensions_; }; -LayerChain::LayerChain(bool is_instance, const VkAllocationCallbacks& allocator) +LayerChain::LayerChain(bool is_instance, + const driver::DebugReportLogger& logger, + const VkAllocationCallbacks& allocator) : is_instance_(is_instance), + logger_(logger), allocator_(allocator), override_layers_(is_instance, allocator), override_extensions_(is_instance, allocator), @@ -562,12 +568,9 @@ VkResult LayerChain::ActivateLayers(VkPhysicalDevice physical_dev, } if (!exact_match) { - ALOGW("Device layers"); - for (uint32_t i = 0; i < layer_count; i++) - ALOGW(" %s", layer_names[i]); - ALOGW( - "disagree with instance layers and are overridden by " - "instance layers"); + logger_.Warn(physical_dev, + "Device layers disagree with instance layers and are " + "overridden by instance layers"); } } @@ -617,7 +620,7 @@ LayerChain::ActiveLayer* LayerChain::AllocateLayerArray(uint32_t count) const { VkResult LayerChain::LoadLayer(ActiveLayer& layer, const char* name) { const Layer* l = FindLayer(name); if (!l) { - ALOGW("Failed to find layer %s", name); + logger_.Err(VK_NULL_HANDLE, "Failed to find layer %s", name); return VK_ERROR_LAYER_NOT_PRESENT; } @@ -882,7 +885,8 @@ VkResult LayerChain::ValidateExtensions(const char* const* extension_names, for (uint32_t i = 0; i < extension_count; i++) { const char* name = extension_names[i]; if (!IsLayerExtension(name) && !IsDriverExtension(name)) { - ALOGE("Failed to enable missing instance extension %s", name); + logger_.Err(VK_NULL_HANDLE, + "Failed to enable missing instance extension %s", name); return VK_ERROR_EXTENSION_NOT_PRESENT; } @@ -919,7 +923,8 @@ VkResult LayerChain::ValidateExtensions(VkPhysicalDevice physical_dev, for (uint32_t i = 0; i < extension_count; i++) { const char* name = extension_names[i]; if (!IsLayerExtension(name) && !IsDriverExtension(name)) { - ALOGE("Failed to enable missing device extension %s", name); + logger_.Err(physical_dev, + "Failed to enable missing device extension %s", name); return VK_ERROR_EXTENSION_NOT_PRESENT; } @@ -1036,7 +1041,7 @@ VkBool32 LayerChain::DebugReportCallback(VkDebugReportFlagsEXT flags, VkResult LayerChain::CreateInstance(const VkInstanceCreateInfo* create_info, const VkAllocationCallbacks* allocator, VkInstance* instance_out) { - LayerChain chain(true, + LayerChain chain(true, driver::DebugReportLogger(*create_info), (allocator) ? *allocator : driver::GetDefaultAllocator()); VkResult result = chain.ActivateLayers(create_info->ppEnabledLayerNames, @@ -1061,9 +1066,9 @@ VkResult LayerChain::CreateDevice(VkPhysicalDevice physical_dev, const VkDeviceCreateInfo* create_info, const VkAllocationCallbacks* allocator, VkDevice* dev_out) { - LayerChain chain(false, (allocator) - ? *allocator - : driver::GetData(physical_dev).allocator); + LayerChain chain( + false, driver::Logger(physical_dev), + (allocator) ? *allocator : driver::GetData(physical_dev).allocator); VkResult result = chain.ActivateLayers( physical_dev, create_info->ppEnabledLayerNames, diff --git a/vulkan/libvulkan/api_gen.cpp b/vulkan/libvulkan/api_gen.cpp index fe4136fe61..155a599a1e 100644 --- a/vulkan/libvulkan/api_gen.cpp +++ b/vulkan/libvulkan/api_gen.cpp @@ -51,56 +51,56 @@ namespace { // clang-format off -VKAPI_ATTR void disabledDestroySurfaceKHR(VkInstance, VkSurfaceKHR, const VkAllocationCallbacks*) { - ALOGE("VK_KHR_surface not enabled. vkDestroySurfaceKHR not executed."); +VKAPI_ATTR void disabledDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR, const VkAllocationCallbacks*) { + driver::Logger(instance).Err(instance, "VK_KHR_surface not enabled. Exported vkDestroySurfaceKHR not executed."); } -VKAPI_ATTR VkResult disabledGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice, uint32_t, VkSurfaceKHR, VkBool32*) { - ALOGE("VK_KHR_surface not enabled. vkGetPhysicalDeviceSurfaceSupportKHR not executed."); +VKAPI_ATTR VkResult disabledGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice, uint32_t, VkSurfaceKHR, VkBool32*) { + driver::Logger(physicalDevice).Err(physicalDevice, "VK_KHR_surface not enabled. Exported vkGetPhysicalDeviceSurfaceSupportKHR not executed."); return VK_SUCCESS; } -VKAPI_ATTR VkResult disabledGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice, VkSurfaceKHR, VkSurfaceCapabilitiesKHR*) { - ALOGE("VK_KHR_surface not enabled. vkGetPhysicalDeviceSurfaceCapabilitiesKHR not executed."); +VKAPI_ATTR VkResult disabledGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR, VkSurfaceCapabilitiesKHR*) { + driver::Logger(physicalDevice).Err(physicalDevice, "VK_KHR_surface not enabled. Exported vkGetPhysicalDeviceSurfaceCapabilitiesKHR not executed."); return VK_SUCCESS; } -VKAPI_ATTR VkResult disabledGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice, VkSurfaceKHR, uint32_t*, VkSurfaceFormatKHR*) { - ALOGE("VK_KHR_surface not enabled. vkGetPhysicalDeviceSurfaceFormatsKHR not executed."); +VKAPI_ATTR VkResult disabledGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR, uint32_t*, VkSurfaceFormatKHR*) { + driver::Logger(physicalDevice).Err(physicalDevice, "VK_KHR_surface not enabled. Exported vkGetPhysicalDeviceSurfaceFormatsKHR not executed."); return VK_SUCCESS; } -VKAPI_ATTR VkResult disabledGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice, VkSurfaceKHR, uint32_t*, VkPresentModeKHR*) { - ALOGE("VK_KHR_surface not enabled. vkGetPhysicalDeviceSurfacePresentModesKHR not executed."); +VKAPI_ATTR VkResult disabledGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR, uint32_t*, VkPresentModeKHR*) { + driver::Logger(physicalDevice).Err(physicalDevice, "VK_KHR_surface not enabled. Exported vkGetPhysicalDeviceSurfacePresentModesKHR not executed."); return VK_SUCCESS; } -VKAPI_ATTR VkResult disabledCreateSwapchainKHR(VkDevice, const VkSwapchainCreateInfoKHR*, const VkAllocationCallbacks*, VkSwapchainKHR*) { - ALOGE("VK_KHR_swapchain not enabled. vkCreateSwapchainKHR not executed."); +VKAPI_ATTR VkResult disabledCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR*, const VkAllocationCallbacks*, VkSwapchainKHR*) { + driver::Logger(device).Err(device, "VK_KHR_swapchain not enabled. Exported vkCreateSwapchainKHR not executed."); return VK_SUCCESS; } -VKAPI_ATTR void disabledDestroySwapchainKHR(VkDevice, VkSwapchainKHR, const VkAllocationCallbacks*) { - ALOGE("VK_KHR_swapchain not enabled. vkDestroySwapchainKHR not executed."); +VKAPI_ATTR void disabledDestroySwapchainKHR(VkDevice device, VkSwapchainKHR, const VkAllocationCallbacks*) { + driver::Logger(device).Err(device, "VK_KHR_swapchain not enabled. Exported vkDestroySwapchainKHR not executed."); } -VKAPI_ATTR VkResult disabledGetSwapchainImagesKHR(VkDevice, VkSwapchainKHR, uint32_t*, VkImage*) { - ALOGE("VK_KHR_swapchain not enabled. vkGetSwapchainImagesKHR not executed."); +VKAPI_ATTR VkResult disabledGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR, uint32_t*, VkImage*) { + driver::Logger(device).Err(device, "VK_KHR_swapchain not enabled. Exported vkGetSwapchainImagesKHR not executed."); return VK_SUCCESS; } -VKAPI_ATTR VkResult disabledAcquireNextImageKHR(VkDevice, VkSwapchainKHR, uint64_t, VkSemaphore, VkFence, uint32_t*) { - ALOGE("VK_KHR_swapchain not enabled. vkAcquireNextImageKHR not executed."); +VKAPI_ATTR VkResult disabledAcquireNextImageKHR(VkDevice device, VkSwapchainKHR, uint64_t, VkSemaphore, VkFence, uint32_t*) { + driver::Logger(device).Err(device, "VK_KHR_swapchain not enabled. Exported vkAcquireNextImageKHR not executed."); return VK_SUCCESS; } -VKAPI_ATTR VkResult disabledQueuePresentKHR(VkQueue, const VkPresentInfoKHR*) { - ALOGE("VK_KHR_swapchain not enabled. vkQueuePresentKHR not executed."); +VKAPI_ATTR VkResult disabledQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR*) { + driver::Logger(queue).Err(queue, "VK_KHR_swapchain not enabled. Exported vkQueuePresentKHR not executed."); return VK_SUCCESS; } -VKAPI_ATTR VkResult disabledCreateAndroidSurfaceKHR(VkInstance, const VkAndroidSurfaceCreateInfoKHR*, const VkAllocationCallbacks*, VkSurfaceKHR*) { - ALOGE("VK_KHR_android_surface not enabled. vkCreateAndroidSurfaceKHR not executed."); +VKAPI_ATTR VkResult disabledCreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR*, const VkAllocationCallbacks*, VkSurfaceKHR*) { + driver::Logger(instance).Err(instance, "VK_KHR_android_surface not enabled. Exported vkCreateAndroidSurfaceKHR not executed."); return VK_SUCCESS; } @@ -304,7 +304,7 @@ VKAPI_ATTR VkResult vkEnumeratePhysicalDevices(VkInstance instance, uint32_t* pP __attribute__((visibility("default"))) VKAPI_ATTR PFN_vkVoidFunction vkGetDeviceProcAddr(VkDevice device, const char* pName) { if (device == VK_NULL_HANDLE) { - ALOGE("vkGetDeviceProcAddr called with invalid device"); + ALOGE("invalid vkGetDeviceProcAddr(VK_NULL_HANDLE, ...) call"); return nullptr; } @@ -342,7 +342,9 @@ VKAPI_ATTR PFN_vkVoidFunction vkGetDeviceProcAddr(VkDevice device, const char* p std::binary_search( known_non_device_names, known_non_device_names + count, pName, [](const char* a, const char* b) { return (strcmp(a, b) < 0); })) { - ALOGE("vkGetDeviceProcAddr called with %s", (pName) ? pName : "(null)"); + vulkan::driver::Logger(device).Err( + device, "invalid vkGetDeviceProcAddr(%p, \"%s\") call", device, + (pName) ? pName : "(null)"); return nullptr; } // clang-format off @@ -356,12 +358,12 @@ VKAPI_ATTR PFN_vkVoidFunction vkGetDeviceProcAddr(VkDevice device, const char* p __attribute__((visibility("default"))) VKAPI_ATTR PFN_vkVoidFunction vkGetInstanceProcAddr(VkInstance instance, const char* pName) { // global functions - if (!instance) { + if (instance == VK_NULL_HANDLE) { if (strcmp(pName, "vkCreateInstance") == 0) return reinterpret_cast<PFN_vkVoidFunction>(vulkan::api::CreateInstance); if (strcmp(pName, "vkEnumerateInstanceLayerProperties") == 0) return reinterpret_cast<PFN_vkVoidFunction>(vulkan::api::EnumerateInstanceLayerProperties); if (strcmp(pName, "vkEnumerateInstanceExtensionProperties") == 0) return reinterpret_cast<PFN_vkVoidFunction>(vulkan::api::EnumerateInstanceExtensionProperties); - ALOGE("vkGetInstanceProcAddr called with %s without instance", pName); + ALOGE("invalid vkGetInstanceProcAddr(VK_NULL_HANDLE, \"%s\") call", pName); return nullptr; } @@ -510,8 +512,11 @@ VKAPI_ATTR PFN_vkVoidFunction vkGetInstanceProcAddr(VkInstance instance, const c hooks, hooks + count, pName, [](const Hook& h, const char* n) { return strcmp(h.name, n) < 0; }); if (hook < hooks + count && strcmp(hook->name, pName) == 0) { - if (!hook->proc) - ALOGE("vkGetInstanceProcAddr called with %s with instance", pName); + if (!hook->proc) { + vulkan::driver::Logger(instance).Err( + instance, "invalid vkGetInstanceProcAddr(%p, \"%s\") call", + instance, pName); + } return hook->proc; } // clang-format off diff --git a/vulkan/libvulkan/code-generator.tmpl b/vulkan/libvulkan/code-generator.tmpl index 3968371972..1f7054949c 100644 --- a/vulkan/libvulkan/code-generator.tmpl +++ b/vulkan/libvulkan/code-generator.tmpl @@ -482,10 +482,16 @@ bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc, {{$ext_name := index $ext.Arguments 0}} {{$base := (Macro "BaseName" $)}} - {{$unnamed_params := (ForEach $.CallParameters "ParameterType" | JoinWith ", ")}} - VKAPI_ATTR {{Node "Type" $.Return}} disabled{{$base}}({{$unnamed_params}}) { - ALOGE("{{$ext_name}} not enabled. {{$.Name}} not executed."); + {{$p0 := (index $.CallParameters 0)}} + {{$ptail := (Tail 1 $.CallParameters)}} + + {{$first_type := (Macro "Parameter" $p0)}} + {{$tail_types := (ForEach $ptail "ParameterType" | JoinWith ", ")}} + + VKAPI_ATTR {{Node "Type" $.Return}} disabled{{$base}}({{$first_type}}, {{$tail_types}}) { + driver::Logger({{$p0.Name}}).Err({{$p0.Name}}, § + "{{$ext_name}} not enabled. Exported {{$.Name}} not executed."); {{if not (IsVoid $.Return.Type)}}return VK_SUCCESS;{{end}} } ¶ @@ -502,7 +508,7 @@ bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc, {{AssertType $ "API"}} // global functions - if (!instance) { + if (instance == VK_NULL_HANDLE) { {{range $f := AllCommands $}} {{if (Macro "IsGloballyDispatched" $f)}} if (strcmp(pName, "{{$f.Name}}") == 0) return § @@ -511,7 +517,7 @@ bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc, {{end}} {{end}} ¶ - ALOGE("vkGetInstanceProcAddr called with %s without instance", pName); + ALOGE("invalid vkGetInstanceProcAddr(VK_NULL_HANDLE, \"%s\") call", pName); return nullptr; } ¶ @@ -549,8 +555,11 @@ bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc, hooks, hooks + count, pName, [](const Hook& h, const char* n) { return strcmp(h.name, n) < 0; }); if (hook < hooks + count && strcmp(hook->name, pName) == 0) { - if (!hook->proc) - ALOGE("vkGetInstanceProcAddr called with %s with instance", pName); + if (!hook->proc) { + vulkan::driver::Logger(instance).Err( + instance, "invalid vkGetInstanceProcAddr(%p, \"%s\") call", + instance, pName); + } return hook->proc; } // clang-format off @@ -567,7 +576,7 @@ bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc, {{AssertType $ "API"}} if (device == VK_NULL_HANDLE) { - ALOGE("vkGetDeviceProcAddr called with invalid device"); + ALOGE("invalid vkGetDeviceProcAddr(VK_NULL_HANDLE, ...) call"); return nullptr; } ¶ @@ -587,7 +596,9 @@ bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc, std::binary_search( known_non_device_names, known_non_device_names + count, pName, [](const char* a, const char* b) { return (strcmp(a, b) < 0); })) { - ALOGE("vkGetDeviceProcAddr called with %s", (pName) ? pName : "(null)"); + vulkan::driver::Logger(device).Err(§ + device, "invalid vkGetDeviceProcAddr(%p, \"%s\") call", device,§ + (pName) ? pName : "(null)"); return nullptr; } // clang-format off @@ -775,7 +786,6 @@ VK_KHR_swapchain {{$ext_name := index $ext.Arguments 0}} {{$base := (Macro "BaseName" $)}} - {{$unnamed_params := (ForEach $.CallParameters "ParameterType" | JoinWith ", ")}} VKAPI_ATTR {{Node "Type" $.Return}} checked{{$base}}({{Macro "Parameters" $}}) { {{$p0 := index $.CallParameters 0}} @@ -785,7 +795,7 @@ VK_KHR_swapchain {{if not (IsVoid $.Return.Type)}}return §{{end}} {{$base}}({{Macro "Arguments" $}}); } else { - ALOGE("{{$ext_name}} not enabled. {{$.Name}} not executed."); + Logger({{$p0.Name}}).Err({{$p0.Name}}, "{{$ext_name}} not enabled. {{$.Name}} not executed."); {{if not (IsVoid $.Return.Type)}}return VK_SUCCESS;{{end}} } } diff --git a/vulkan/libvulkan/debug_report.cpp b/vulkan/libvulkan/debug_report.cpp index c4a1174191..2a34613180 100644 --- a/vulkan/libvulkan/debug_report.cpp +++ b/vulkan/libvulkan/debug_report.cpp @@ -19,62 +19,37 @@ namespace vulkan { namespace driver { -VkResult DebugReportCallbackList::CreateCallback( - VkInstance instance, - const VkDebugReportCallbackCreateInfoEXT* create_info, - const VkAllocationCallbacks* allocator, - VkDebugReportCallbackEXT* callback) { - VkDebugReportCallbackEXT driver_callback = VK_NULL_HANDLE; - - if (GetData(instance).driver.CreateDebugReportCallbackEXT) { - VkResult result = GetData(instance).driver.CreateDebugReportCallbackEXT( - instance, create_info, allocator, &driver_callback); - if (result != VK_SUCCESS) - return result; - } - - const VkAllocationCallbacks* alloc = - allocator ? allocator : &GetData(instance).allocator; - void* mem = - alloc->pfnAllocation(alloc->pUserData, sizeof(Node), alignof(Node), - VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); - if (!mem) { - if (GetData(instance).driver.DestroyDebugReportCallbackEXT) { - GetData(instance).driver.DestroyDebugReportCallbackEXT( - instance, driver_callback, allocator); - } - return VK_ERROR_OUT_OF_HOST_MEMORY; - } +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, create_info->flags, create_info->pfnCallback, - create_info->pUserData, driver_callback}; - *callback = - VkDebugReportCallbackEXT(reinterpret_cast<uintptr_t>(head_.next)); - return VK_SUCCESS; + head_.next = new (mem) Node{head_.next, info.flags, info.pfnCallback, + info.pUserData, driver_handle}; + + return head_.next; } -void DebugReportCallbackList::DestroyCallback( - VkInstance instance, - VkDebugReportCallbackEXT callback, - const VkAllocationCallbacks* allocator) { - Node* node = reinterpret_cast<Node*>(uintptr_t(callback)); - std::unique_lock<decltype(rwmutex_)> lock(rwmutex_); - Node* prev = &head_; - while (prev && prev->next != node) - prev = prev->next; - prev->next = node->next; - lock.unlock(); - - if (GetData(instance).driver.DestroyDebugReportCallbackEXT) { - GetData(instance).driver.DestroyDebugReportCallbackEXT( - instance, node->driver_callback, allocator); +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; + prev->next = node->next; } - const VkAllocationCallbacks* alloc = - allocator ? allocator : &GetData(instance).allocator; - alloc->pfnFree(alloc->pUserData, node); + allocator.pfnFree(allocator.pUserData, node); } void DebugReportCallbackList::Message(VkDebugReportFlagsEXT flags, @@ -83,32 +58,108 @@ void DebugReportCallbackList::Message(VkDebugReportFlagsEXT flags, size_t location, int32_t message_code, const char* layer_prefix, - const char* message) { + const char* message) const { std::shared_lock<decltype(rwmutex_)> lock(rwmutex_); - Node* node = &head_; + 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->data); + 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_CREATE_INFO_EXT) { + 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) { - return GetData(instance).debug_report_callbacks.CreateCallback( - instance, create_info, allocator, 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) - GetData(instance).debug_report_callbacks.DestroyCallback( - instance, callback, 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, @@ -123,10 +174,11 @@ void DebugReportMessageEXT(VkInstance instance, 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); } - GetData(instance).debug_report_callbacks.Message(flags, object_type, object, - location, message_code, - layer_prefix, message); } } // namespace driver diff --git a/vulkan/libvulkan/debug_report.h b/vulkan/libvulkan/debug_report.h index 72b1887b1c..be9b645aa7 100644 --- a/vulkan/libvulkan/debug_report.h +++ b/vulkan/libvulkan/debug_report.h @@ -17,8 +17,9 @@ #ifndef LIBVULKAN_DEBUG_REPORT_H #define LIBVULKAN_DEBUG_REPORT_H 1 -#include <vulkan/vulkan.h> +#include <stdarg.h> #include <shared_mutex> +#include <vulkan/vulkan.h> namespace vulkan { namespace driver { @@ -30,6 +31,10 @@ VKAPI_ATTR void DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT // clang-format on class DebugReportCallbackList { + private: + // forward declaration + struct Node; + public: DebugReportCallbackList() : head_{nullptr, 0, nullptr, nullptr, VK_NULL_HANDLE} {} @@ -37,36 +42,124 @@ class DebugReportCallbackList { DebugReportCallbackList& operator=(const DebugReportCallbackList&) = delete; ~DebugReportCallbackList() = default; - VkResult CreateCallback( - VkInstance instance, - const VkDebugReportCallbackCreateInfoEXT* create_info, - const VkAllocationCallbacks* allocator, - VkDebugReportCallbackEXT* callback); - void DestroyCallback(VkInstance instance, - VkDebugReportCallbackEXT callback, - const VkAllocationCallbacks* allocator); + Node* AddCallback(const VkDebugReportCallbackCreateInfoEXT& info, + VkDebugReportCallbackEXT driver_handle, + const VkAllocationCallbacks& allocator); + void RemoveCallback(Node* node, const VkAllocationCallbacks& allocator); + void Message(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT object_type, uint64_t object, size_t location, int32_t message_code, const char* layer_prefix, - const char* message); + const char* message) const; + + static Node* FromHandle(VkDebugReportCallbackEXT handle) { + return reinterpret_cast<Node*>(uintptr_t(handle)); + } + + static VkDebugReportCallbackEXT GetHandle(const Node* node) { + return VkDebugReportCallbackEXT(reinterpret_cast<uintptr_t>(node)); + } + + static VkDebugReportCallbackEXT GetDriverHandle(const Node* node) { + return node->driver_handle; + } private: struct Node { Node* next; + VkDebugReportFlagsEXT flags; PFN_vkDebugReportCallbackEXT callback; - void* data; - VkDebugReportCallbackEXT driver_callback; + void* user_data; + + VkDebugReportCallbackEXT driver_handle; }; // TODO(jessehall): replace with std::shared_mutex when available in libc++ - std::shared_timed_mutex rwmutex_; + mutable std::shared_timed_mutex rwmutex_; Node head_; }; +class DebugReportLogger { + public: + DebugReportLogger(const VkInstanceCreateInfo& info) + : instance_pnext_(info.pNext), callbacks_(nullptr) {} + DebugReportLogger(const DebugReportCallbackList& callbacks) + : instance_pnext_(nullptr), callbacks_(&callbacks) {} + + void Message(VkDebugReportFlagsEXT flags, + VkDebugReportObjectTypeEXT object_type, + uint64_t object, + size_t location, + int32_t message_code, + const char* layer_prefix, + const char* message) const; + +#define DEBUG_REPORT_LOGGER_PRINTF(fmt, args) \ + __attribute__((format(printf, (fmt) + 1, (args) + 1))) + template <typename ObjectType> + void Info(ObjectType object, const char* format, ...) const + DEBUG_REPORT_LOGGER_PRINTF(2, 3) { + va_list ap; + va_start(ap, format); + PrintV(VK_DEBUG_REPORT_INFORMATION_BIT_EXT, GetObjectType(object), + GetObjectUInt64(object), format, ap); + va_end(ap); + } + + template <typename ObjectType> + void Warn(ObjectType object, const char* format, ...) const + DEBUG_REPORT_LOGGER_PRINTF(2, 3) { + va_list ap; + va_start(ap, format); + PrintV(VK_DEBUG_REPORT_WARNING_BIT_EXT, GetObjectType(object), + GetObjectUInt64(object), format, ap); + va_end(ap); + } + + template <typename ObjectType> + void Err(ObjectType object, const char* format, ...) const + DEBUG_REPORT_LOGGER_PRINTF(2, 3) { + va_list ap; + va_start(ap, format); + PrintV(VK_DEBUG_REPORT_ERROR_BIT_EXT, GetObjectType(object), + GetObjectUInt64(object), format, ap); + va_end(ap); + } + + private: + template <typename ObjectType> + static VkDebugReportObjectTypeEXT GetObjectType(ObjectType) { + if (std::is_same<ObjectType, VkInstance>::value) + return VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT; + else if (std::is_same<ObjectType, VkPhysicalDevice>::value) + return VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT; + else if (std::is_same<ObjectType, VkDevice>::value) + return VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT; + else + return VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT; + } + + template <typename ObjectType> + static uint64_t GetObjectUInt64(ObjectType object) { + return uint64_t(object); + } + +#define DEBUG_REPORT_LOGGER_VPRINTF(fmt) \ + __attribute__((format(printf, (fmt) + 1, 0))) + void PrintV(VkDebugReportFlagsEXT flags, + VkDebugReportObjectTypeEXT object_type, + uint64_t object, + const char* format, + va_list ap) const DEBUG_REPORT_LOGGER_VPRINTF(4); + + const void* const instance_pnext_; + const DebugReportCallbackList* const callbacks_; +}; + } // namespace driver } // namespace vulkan diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp index b02f5b4324..0e64b24309 100644 --- a/vulkan/libvulkan/driver.cpp +++ b/vulkan/libvulkan/driver.cpp @@ -409,14 +409,16 @@ void FreeInstanceData(InstanceData* data, allocator.pfnFree(allocator.pUserData, data); } -DeviceData* AllocateDeviceData(const VkAllocationCallbacks& allocator) { +DeviceData* AllocateDeviceData( + const VkAllocationCallbacks& allocator, + const DebugReportCallbackList& debug_report_callbacks) { void* data_mem = allocator.pfnAllocation( allocator.pUserData, sizeof(DeviceData), alignof(DeviceData), VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); if (!data_mem) return nullptr; - return new (data_mem) DeviceData(allocator); + return new (data_mem) DeviceData(allocator, debug_report_callbacks); } void FreeDeviceData(DeviceData* data, const VkAllocationCallbacks& allocator) { @@ -440,7 +442,7 @@ bool OpenHAL() { int result = hw_get_module("vulkan", reinterpret_cast<const hw_module_t**>(&module)); if (result != 0) { - ALOGV("no Vulkan HAL present, using stub HAL"); + ALOGI("no Vulkan HAL present, using stub HAL"); return true; } @@ -489,8 +491,7 @@ PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName) { return hook->proc; ALOGE( - "Invalid use of vkGetInstanceProcAddr to query %s without an " - "instance", + "internal vkGetInstanceProcAddr called for %s without an instance", pName); return nullptr; @@ -511,8 +512,7 @@ PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName) { break; default: ALOGE( - "Invalid use of vkGetInstanceProcAddr to query %s with an " - "instance", + "internal vkGetInstanceProcAddr called for %s with an instance", pName); proc = nullptr; break; @@ -527,7 +527,7 @@ PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName) { return GetData(device).driver.GetDeviceProcAddr(device, pName); if (hook->type != ProcHook::DEVICE) { - ALOGE("Invalid use of vkGetDeviceProcAddr to query %s", pName); + ALOGE("internal vkGetDeviceProcAddr called for %s", pName); return nullptr; } @@ -684,7 +684,8 @@ VkResult CreateDevice(VkPhysicalDevice physicalDevice, if (result != VK_SUCCESS) return result; - DeviceData* data = AllocateDeviceData(data_allocator); + DeviceData* data = AllocateDeviceData(data_allocator, + instance_data.debug_report_callbacks); if (!data) return VK_ERROR_OUT_OF_HOST_MEMORY; diff --git a/vulkan/libvulkan/driver.h b/vulkan/libvulkan/driver.h index 2b1f545ace..210c3c7323 100644 --- a/vulkan/libvulkan/driver.h +++ b/vulkan/libvulkan/driver.h @@ -82,14 +82,19 @@ struct InstanceData { }; struct DeviceData { - DeviceData(const VkAllocationCallbacks& alloc) - : opaque_api_data(), allocator(alloc), driver() { + DeviceData(const VkAllocationCallbacks& alloc, + const DebugReportCallbackList& debug_report_callbacks_) + : opaque_api_data(), + allocator(alloc), + debug_report_callbacks(debug_report_callbacks_), + driver() { hook_extensions.set(ProcHook::EXTENSION_CORE); } api::DeviceData opaque_api_data; const VkAllocationCallbacks allocator; + const DebugReportCallbackList& debug_report_callbacks; std::bitset<ProcHook::EXTENSION_COUNT> hook_extensions; @@ -214,6 +219,11 @@ inline DeviceData& GetData(DeviceDispatchable dispatchable) { return *reinterpret_cast<DeviceData*>(GetDataInternal(dispatchable)); } +template <typename DispatchableType> +const DebugReportLogger Logger(DispatchableType dispatchable) { + return DebugReportLogger(GetData(dispatchable).debug_report_callbacks); +} + } // namespace driver } // namespace vulkan diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp index 5bd21590c8..29351a189e 100644 --- a/vulkan/libvulkan/driver_gen.cpp +++ b/vulkan/libvulkan/driver_gen.cpp @@ -33,7 +33,7 @@ VKAPI_ATTR VkResult checkedCreateSwapchainKHR(VkDevice device, const VkSwapchain if (GetData(device).hook_extensions[ProcHook::KHR_swapchain]) { return CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain); } else { - ALOGE("VK_KHR_swapchain not enabled. vkCreateSwapchainKHR not executed."); + Logger(device).Err(device, "VK_KHR_swapchain not enabled. vkCreateSwapchainKHR not executed."); return VK_SUCCESS; } } @@ -42,7 +42,7 @@ VKAPI_ATTR void checkedDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapc if (GetData(device).hook_extensions[ProcHook::KHR_swapchain]) { DestroySwapchainKHR(device, swapchain, pAllocator); } else { - ALOGE("VK_KHR_swapchain not enabled. vkDestroySwapchainKHR not executed."); + Logger(device).Err(device, "VK_KHR_swapchain not enabled. vkDestroySwapchainKHR not executed."); } } @@ -50,7 +50,7 @@ VKAPI_ATTR VkResult checkedGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR if (GetData(device).hook_extensions[ProcHook::KHR_swapchain]) { return GetSwapchainImagesKHR(device, swapchain, pSwapchainImageCount, pSwapchainImages); } else { - ALOGE("VK_KHR_swapchain not enabled. vkGetSwapchainImagesKHR not executed."); + Logger(device).Err(device, "VK_KHR_swapchain not enabled. vkGetSwapchainImagesKHR not executed."); return VK_SUCCESS; } } @@ -59,7 +59,7 @@ VKAPI_ATTR VkResult checkedAcquireNextImageKHR(VkDevice device, VkSwapchainKHR s if (GetData(device).hook_extensions[ProcHook::KHR_swapchain]) { return AcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex); } else { - ALOGE("VK_KHR_swapchain not enabled. vkAcquireNextImageKHR not executed."); + Logger(device).Err(device, "VK_KHR_swapchain not enabled. vkAcquireNextImageKHR not executed."); return VK_SUCCESS; } } @@ -68,7 +68,7 @@ VKAPI_ATTR VkResult checkedQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR if (GetData(queue).hook_extensions[ProcHook::KHR_swapchain]) { return QueuePresentKHR(queue, pPresentInfo); } else { - ALOGE("VK_KHR_swapchain not enabled. vkQueuePresentKHR not executed."); + Logger(queue).Err(queue, "VK_KHR_swapchain not enabled. vkQueuePresentKHR not executed."); return VK_SUCCESS; } } |