Merge changes from topic 'vk-debug-report' into nyc-dev
* changes:
vulkan: improve vulkan::driver logcat messages
vulkan: use Logger in vulkan::api
vulkan: use Logger in the generated code
vulkan: add DebugReportLogger
vulkan: make debug report callbacks available in DeviceData
vulkan: avoid duplicated app messages
vulkan: constify DebugReportCallbackList::Message
vulkan: refactor DebugReportCallbackList
diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp
index 28b172d..8053668 100644
--- a/vulkan/libvulkan/api.cpp
+++ b/vulkan/libvulkan/api.cpp
@@ -394,7 +394,9 @@
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 @@
void* user_data);
const bool is_instance_;
+ const driver::DebugReportLogger& logger_;
const VkAllocationCallbacks& allocator_;
OverrideLayerNames override_layers_;
@@ -476,8 +479,11 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 fe4136f..155a599 100644
--- a/vulkan/libvulkan/api_gen.cpp
+++ b/vulkan/libvulkan/api_gen.cpp
@@ -51,56 +51,56 @@
// 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 @@
__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 @@
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 @@
__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 @@
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 3968371..1f70549 100644
--- a/vulkan/libvulkan/code-generator.tmpl
+++ b/vulkan/libvulkan/code-generator.tmpl
@@ -482,10 +482,16 @@
{{$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 @@
{{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 @@
{{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 @@
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 @@
{{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 @@
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 @@
{{$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 @@
{{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 c4a1174..2a34613 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;
+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;
- 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;
- }
-
+ // 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 @@
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 @@
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 72b1887..be9b645 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 @@
// clang-format on
class DebugReportCallbackList {
+ private:
+ // forward declaration
+ struct Node;
+
public:
DebugReportCallbackList()
: head_{nullptr, 0, nullptr, nullptr, VK_NULL_HANDLE} {}
@@ -37,36 +42,124 @@
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 b02f5b4..0e64b24 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -409,14 +409,16 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 2b1f545..210c3c7 100644
--- a/vulkan/libvulkan/driver.h
+++ b/vulkan/libvulkan/driver.h
@@ -82,14 +82,19 @@
};
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 @@
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 5bd2159..29351a1 100644
--- a/vulkan/libvulkan/driver_gen.cpp
+++ b/vulkan/libvulkan/driver_gen.cpp
@@ -33,7 +33,7 @@
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 @@
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 @@
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 @@
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 @@
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;
}
}