vulkan: Support VK_EXT_debug_report in loader and nulldrv
* Add extension to vulkan.api.
* Fix a few errors in upstream vk_ext_debug_report.h; bugs filed.
* Loader enumerates extension iff the driver supports it.
- TODO: Also enumerate if any layers that support it are implicitly
enabled.
- Note extension may still be enabled if any layer supports it.
* Add loader bottom procs for the extension functions. These will call
through to the driver version if the driver supports the extension.
* Add no-op support to nulldrv, mostly for testing the loader.
Change-Id: I092d2da56ee4c64498f8edae75e0d995478bb6f2
(cherry picked from commit a5ef7c27bc85e3628814532a32ffb9a5c33c4b73)
diff --git a/vulkan/libvulkan/debug_report.cpp b/vulkan/libvulkan/debug_report.cpp
new file mode 100644
index 0000000..fea9f18
--- /dev/null
+++ b/vulkan/libvulkan/debug_report.cpp
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "loader.h"
+
+namespace vulkan {
+
+VkResult DebugReportCallbackList::CreateCallback(
+ VkInstance instance,
+ const VkDebugReportCallbackCreateInfoEXT* create_info,
+ const VkAllocationCallbacks* allocator,
+ VkDebugReportCallbackEXT* callback) {
+ VkDebugReportCallbackEXT driver_callback;
+ VkResult result = GetDriverDispatch(instance).CreateDebugReportCallbackEXT(
+ GetDriverInstance(instance), create_info, allocator, &driver_callback);
+ if (result != VK_SUCCESS)
+ return result;
+
+ const VkAllocationCallbacks* alloc =
+ allocator ? allocator : GetAllocator(instance);
+ void* mem =
+ alloc->pfnAllocation(alloc->pUserData, sizeof(Node), alignof(Node),
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ if (!mem) {
+ GetDriverDispatch(instance).DestroyDebugReportCallbackEXT(
+ GetDriverInstance(instance), driver_callback, allocator);
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+
+ 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;
+}
+
+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();
+
+ GetDriverDispatch(instance).DestroyDebugReportCallbackEXT(
+ GetDriverInstance(instance), node->driver_callback, allocator);
+
+ const VkAllocationCallbacks* alloc =
+ allocator ? allocator : GetAllocator(instance);
+ alloc->pfnFree(alloc->pUserData, node);
+}
+
+void DebugReportCallbackList::Message(VkDebugReportFlagsEXT flags,
+ VkDebugReportObjectTypeEXT object_type,
+ uint64_t object,
+ size_t location,
+ int32_t message_code,
+ const char* layer_prefix,
+ const char* message) {
+ std::shared_lock<decltype(rwmutex_)> lock(rwmutex_);
+ 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);
+ }
+ }
+}
+
+VkResult CreateDebugReportCallbackEXT_Bottom(
+ VkInstance instance,
+ const VkDebugReportCallbackCreateInfoEXT* create_info,
+ const VkAllocationCallbacks* allocator,
+ VkDebugReportCallbackEXT* callback) {
+ return GetDebugReportCallbacks(instance).CreateCallback(
+ instance, create_info, allocator, callback);
+}
+
+void DestroyDebugReportCallbackEXT_Bottom(
+ VkInstance instance,
+ VkDebugReportCallbackEXT callback,
+ const VkAllocationCallbacks* allocator) {
+ if (callback)
+ GetDebugReportCallbacks(instance).DestroyCallback(instance, callback,
+ allocator);
+}
+
+void DebugReportMessageEXT_Bottom(VkInstance instance,
+ VkDebugReportFlagsEXT flags,
+ VkDebugReportObjectTypeEXT object_type,
+ uint64_t object,
+ size_t location,
+ int32_t message_code,
+ const char* layer_prefix,
+ const char* message) {
+ GetDriverDispatch(instance).DebugReportMessageEXT(
+ GetDriverInstance(instance), flags, object_type, object, location,
+ message_code, layer_prefix, message);
+ GetDebugReportCallbacks(instance).Message(flags, object_type, object,
+ location, message_code,
+ layer_prefix, message);
+}
+
+} // namespace vulkan