Vulkan: Enable validation layers on request.
Also adds the build files for the Vulkan layers.
The layers are enabled by default for the tests.
BUG=angleproject:1319
Change-Id: I0b442b36312a1299a932922e1c4e39f00801de49
Reviewed-on: https://chromium-review.googlesource.com/367751
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/renderer/vulkan/RendererVk.cpp b/src/libANGLE/renderer/vulkan/RendererVk.cpp
index 14c3c14..ecbca12 100644
--- a/src/libANGLE/renderer/vulkan/RendererVk.cpp
+++ b/src/libANGLE/renderer/vulkan/RendererVk.cpp
@@ -45,19 +45,72 @@
return VK_SUCCESS;
}
+VkBool32 VKAPI_CALL DebugReportCallback(VkDebugReportFlagsEXT flags,
+ VkDebugReportObjectTypeEXT objectType,
+ uint64_t object,
+ size_t location,
+ int32_t messageCode,
+ const char *layerPrefix,
+ const char *message,
+ void *userData)
+{
+ if ((flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) != 0)
+ {
+ ANGLEPlatformCurrent()->logError(message);
+#if !defined(NDEBUG)
+ // Abort the call in Debug builds.
+ return VK_TRUE;
+#endif
+ }
+ else if ((flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) != 0)
+ {
+ ANGLEPlatformCurrent()->logWarning(message);
+ }
+ else
+ {
+ ANGLEPlatformCurrent()->logInfo(message);
+ }
+
+ return VK_FALSE;
+}
+
} // anonymous namespace
-RendererVk::RendererVk() : mCapsInitialized(false), mInstance(VK_NULL_HANDLE)
+RendererVk::RendererVk()
+ : mCapsInitialized(false),
+ mInstance(VK_NULL_HANDLE),
+ mEnableValidationLayers(false),
+ mDebugReportCallback(VK_NULL_HANDLE)
{
}
RendererVk::~RendererVk()
{
+ if (mDebugReportCallback)
+ {
+ ASSERT(mInstance);
+ auto destroyDebugReportCallback = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(
+ vkGetInstanceProcAddr(mInstance, "vkDestroyDebugReportCallbackEXT"));
+ ASSERT(destroyDebugReportCallback);
+ destroyDebugReportCallback(mInstance, mDebugReportCallback, nullptr);
+ }
+
vkDestroyInstance(mInstance, nullptr);
}
vk::Error RendererVk::initialize(const egl::AttributeMap &attribs)
{
+ // Gather global layer properties.
+ uint32_t instanceLayerCount = 0;
+ ANGLE_VK_TRY(vkEnumerateInstanceLayerProperties(&instanceLayerCount, nullptr));
+
+ std::vector<VkLayerProperties> instanceLayerProps(instanceLayerCount);
+ if (instanceLayerCount > 0)
+ {
+ ANGLE_VK_TRY(
+ vkEnumerateInstanceLayerProperties(&instanceLayerCount, instanceLayerProps.data()));
+ }
+
uint32_t instanceExtensionCount = 0;
ANGLE_VK_TRY(vkEnumerateInstanceExtensionProperties(nullptr, &instanceExtensionCount, nullptr));
@@ -68,6 +121,37 @@
instanceExtensionProps.data()));
}
+#if !defined(NDEBUG)
+ // Validation layers enabled by default in Debug.
+ mEnableValidationLayers = true;
+#endif
+
+ // If specified in the attributes, override the default.
+ if (attribs.contains(EGL_PLATFORM_ANGLE_ENABLE_VALIDATION_LAYER_ANGLE))
+ {
+ mEnableValidationLayers =
+ (attribs.get(EGL_PLATFORM_ANGLE_ENABLE_VALIDATION_LAYER_ANGLE, EGL_FALSE) == EGL_TRUE);
+ }
+
+ if (mEnableValidationLayers)
+ {
+ // Verify the standard validation layers are available.
+ if (!HasStandardValidationLayer(instanceLayerProps))
+ {
+ // Generate an error if the attribute was requested, warning otherwise.
+ if (attribs.contains(EGL_PLATFORM_ANGLE_ENABLE_VALIDATION_LAYER_ANGLE))
+ {
+ ANGLEPlatformCurrent()->logError("Vulkan standard validation layers are missing.");
+ }
+ else
+ {
+ ANGLEPlatformCurrent()->logWarning(
+ "Vulkan standard validation layers are missing.");
+ }
+ mEnableValidationLayers = false;
+ }
+ }
+
std::vector<const char *> enabledInstanceExtensions;
enabledInstanceExtensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
#if defined(ANGLE_PLATFORM_WINDOWS)
@@ -76,6 +160,12 @@
#error Unsupported Vulkan platform.
#endif // defined(ANGLE_PLATFORM_WINDOWS)
+ // TODO(jmadill): Should be able to continue initialization if debug report ext missing.
+ if (mEnableValidationLayers)
+ {
+ enabledInstanceExtensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
+ }
+
// Verify the required extensions are in the extension names set. Fail if not.
ANGLE_VK_TRY(VerifyExtensionsPresent(instanceExtensionProps, enabledInstanceExtensions));
@@ -98,11 +188,31 @@
instanceInfo.enabledExtensionCount = static_cast<uint32_t>(enabledInstanceExtensions.size());
instanceInfo.ppEnabledExtensionNames =
enabledInstanceExtensions.empty() ? nullptr : enabledInstanceExtensions.data();
- instanceInfo.enabledLayerCount = 0u;
- instanceInfo.ppEnabledLayerNames = nullptr;
+ instanceInfo.enabledLayerCount = mEnableValidationLayers ? 1u : 0u;
+ instanceInfo.ppEnabledLayerNames =
+ mEnableValidationLayers ? &g_VkStdValidationLayerName : nullptr;
ANGLE_VK_TRY(vkCreateInstance(&instanceInfo, nullptr, &mInstance));
+ if (mEnableValidationLayers)
+ {
+ VkDebugReportCallbackCreateInfoEXT debugReportInfo;
+
+ debugReportInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
+ debugReportInfo.pNext = nullptr;
+ debugReportInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT |
+ VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT |
+ VK_DEBUG_REPORT_INFORMATION_BIT_EXT | VK_DEBUG_REPORT_DEBUG_BIT_EXT;
+ debugReportInfo.pfnCallback = &DebugReportCallback;
+ debugReportInfo.pUserData = this;
+
+ auto createDebugReportCallback = reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(
+ vkGetInstanceProcAddr(mInstance, "vkCreateDebugReportCallbackEXT"));
+ ASSERT(createDebugReportCallback);
+ ANGLE_VK_TRY(
+ createDebugReportCallback(mInstance, &debugReportInfo, nullptr, &mDebugReportCallback));
+ }
+
return vk::NoError();
}