Commit 0448ec84 by Jamie Madill Committed by Commit Bot

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: 's avatarGeoff Lang <geofflang@chromium.org>
parent b5693ff6
Debug/
Debug_Win32/
Debug_x64/
Debug_ARM/
Release/
Release_Win32/
Release_x64/
Release_ARM/
*.sdf
*.Makefile
*.ncb
*.suo
*.nvuser
*.opensdf
*.orig
*.psess
*.pyc
*.rej
*.sdf
*.sln
*.suo
*.target.mk
*.TMP
*.VC.db
*.VC.opendb
*.vcxproj
*.vcxproj.filters
*.vcxproj.user
*.VC.opendb
patches-*
*.target.mk
ipch
debug.txt
*.opensdf
*.orig
*.rej
*.vsp
*~
.gclient
.gclient_entries
/src/tests/third_party/gles_conformance_tests
/testing/gmock
/testing/gtest
/third_party/cherry
......@@ -33,19 +32,21 @@ debug.txt
/third_party/spirv-tools-angle/src
/third_party/vulkan-validation-layers/src
/third_party/zlib
/src/tests/third_party/gles_conformance_tests
out
angle_internal
buildtools/
debug.txt
Debug/
Debug_ARM/
Debug_Win32/
Debug_x64/
diag.txt
ipch
lib/*
Makefile
*.Makefile
*~
.gclient
angle_internal
out
patches-*
Release/
Release_ARM/
Release_Win32/
Release_x64/
TestResults.qpa
*.psess
*.vsp
*.nvuser
buildtools/
*.pyc
*.TMP
*.VC.db
......@@ -63,7 +63,7 @@ Additions to the EGL Specification
New Behavior
To request a display that is backed by a Vulken driver, the value of
To request a display that is backed by a Vulkan driver, the value of
EGL_PLATFORM_ANGLE_TYPE_ANGLE should be
EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE.
......
#!/usr/bin/python
#
# Copyright 2016 The ANGLE Project Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
# generate_vulkan_header.py:
# Workaround problems with Windows and GYP and the Vulkan loader paths.
import os, sys
if len(sys.argv) < 4:
print("Usage: " + sys.argv[0] + " <layers_source_path> <output_file> <default_vk_layers_path>")
sys.exit(1)
layers_source_path = sys.argv[1]
output_file = sys.argv[2]
default_vk_layers_path = sys.argv[3].rstrip("\"")
def fixpath(inpath):
return os.path.relpath(inpath).replace('\\', '/')
def all_paths(inpath):
return fixpath(inpath) + ";" + fixpath(os.path.join("..", fixpath(inpath)))
with open(output_file, "w") as outfile:
outfile.write("#define LAYERS_SOURCE_PATH \"" + all_paths(layers_source_path) + "\"\n")
outfile.write("#define DEFAULT_VK_LAYERS_PATH \"" + all_paths(default_vk_layers_path) + "\"\n")
#!/usr/bin/python
#
# Copyright 2016 The ANGLE Project Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
# generate_vulkan_layers_json.py:
# Generate copies of the Vulkan layers JSON files, with no paths, forcing
# Vulkan to use the default search path to look for layers.
import os, sys, json, glob
if len(sys.argv) < 3:
print("Usage: " + sys.argv[0] + " <source_dir> <target_dir>")
sys.exit(1)
source_dir = sys.argv[1]
target_dir = sys.argv[2]
if not os.path.isdir(source_dir):
print(source_dir + " is not a directory.")
sys.exit(1)
if not os.path.exists(target_dir):
os.makedirs(target_dir)
for json_fname in glob.glob(os.path.join(source_dir, "*.json")):
with open(json_fname) as infile:
data = json.load(infile)
# update the path
prev_name = os.path.basename(data['layer']['library_path'])
data['layer']['library_path'] = prev_name
target_fname = os.path.join(target_dir, os.path.basename(json_fname))
with open(target_fname, "w") as outfile:
json.dump(data, outfile)
......@@ -61,10 +61,8 @@
#include "libANGLE/renderer/vulkan/DisplayVk.h"
#endif // defined(ANGLE_ENABLE_VULKAN)
namespace egl
{
namespace
// The log messages prepend the class name, so make this part of the angle namespace.
namespace angle
{
class DefaultPlatform : public angle::Platform
......@@ -72,20 +70,49 @@ class DefaultPlatform : public angle::Platform
public:
DefaultPlatform() {}
~DefaultPlatform() override {}
void logError(const char *errorMessage) override;
void logWarning(const char *warningMessage) override;
void logInfo(const char *infoMessage) override;
};
DefaultPlatform *defaultPlatform = nullptr;
std::unique_ptr<DefaultPlatform> g_defaultPlatform = nullptr;
void DefaultPlatform::logError(const char *errorMessage)
{
ERR("%s", errorMessage);
}
void DefaultPlatform::logWarning(const char *warningMessage)
{
// TODO(jmadill): Fix this
ERR("%s", warningMessage);
}
void DefaultPlatform::logInfo(const char *infoMessage)
{
// Uncomment this if you want Vulkan spam.
// ERR("%s", infoMessage);
}
} // namespace angle
namespace egl
{
namespace
{
void InitDefaultPlatformImpl()
{
if (ANGLEPlatformCurrent() == nullptr)
{
if (defaultPlatform == nullptr)
if (!angle::g_defaultPlatform)
{
defaultPlatform = new DefaultPlatform();
angle::g_defaultPlatform.reset(new angle::DefaultPlatform());
}
ANGLEPlatformInitialize(defaultPlatform);
ANGLEPlatformInitialize(angle::g_defaultPlatform.get());
}
}
......
......@@ -45,19 +45,72 @@ VkResult VerifyExtensionsPresent(const std::vector<VkExtensionProperties> &exten
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 @@ vk::Error RendererVk::initialize(const egl::AttributeMap &attribs)
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 @@ vk::Error RendererVk::initialize(const egl::AttributeMap &attribs)
#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 @@ vk::Error RendererVk::initialize(const egl::AttributeMap &attribs)
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();
}
......
......@@ -55,6 +55,8 @@ class RendererVk : angle::NonCopyable
mutable gl::Limitations mNativeLimitations;
VkInstance mInstance;
bool mEnableValidationLayers;
VkDebugReportCallbackEXT mDebugReportCallback;
};
} // namespace rx
......
......@@ -48,6 +48,10 @@ EGLint DefaultEGLErrorCode(VkResult result)
}
} // anonymous namespace
// Mirrors std_validation_str in loader.h
// TODO(jmadill): Possibly wrap the loader into a safe source file. Can't be included trivially.
const char *g_VkStdValidationLayerName = "VK_LAYER_LUNARG_standard_validation";
const char *VulkanResultString(VkResult result)
{
switch (result)
......@@ -173,4 +177,17 @@ bool Error::isError() const
} // namespace vk
bool HasStandardValidationLayer(const std::vector<VkLayerProperties> &layerProps)
{
for (const auto &layerProp : layerProps)
{
if (std::string(layerProp.layerName) == g_VkStdValidationLayerName)
{
return true;
}
}
return false;
}
} // namespace rx
......@@ -18,6 +18,9 @@ namespace rx
{
const char *VulkanResultString(VkResult result);
bool HasStandardValidationLayer(const std::vector<VkLayerProperties> &layerProps);
extern const char *g_VkStdValidationLayerName;
namespace vk
{
......
......@@ -86,6 +86,7 @@
'<(angle_path)/src/tests/egl_tests/EGLRobustnessTest.cpp',
'<(angle_path)/src/tests/egl_tests/EGLSanityCheckTest.cpp',
'<(angle_path)/src/tests/egl_tests/EGLSurfaceTest.cpp',
'<(angle_path)/src/tests/egl_tests/EGLVulkanEXTTest.cpp',
'<(angle_path)/src/tests/test_utils/ANGLETest.cpp',
'<(angle_path)/src/tests/test_utils/ANGLETest.h',
'<(angle_path)/src/tests/test_utils/angle_test_configs.cpp',
......
//
// Copyright 2016 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// VulkanEXTTest:
// Tests specific to the ANGLE Vulkan extension.
//
#include "test_utils/ANGLETest.h"
using namespace angle;
namespace
{
class VulkanEXTTest : public ANGLETest
{
public:
VulkanEXTTest() {}
// Intentionally do not call base class so we can run EGL in the tests.
void SetUp() override {}
};
// ANGLE requires that the vulkan validation layers are available.
TEST_P(VulkanEXTTest, ValidationLayersAvaialable)
{
setVulkanLayersEnabled(true);
ASSERT_TRUE(getEGLWindow()->initializeGL(GetOSWindow()));
}
ANGLE_INSTANTIATE_TEST(VulkanEXTTest, ES2_VULKAN(), ES3_VULKAN());
} // anonymous namespace
......@@ -205,6 +205,12 @@ ANGLETest::ANGLETest()
{
mEGLWindow =
new EGLWindow(GetParam().majorVersion, GetParam().minorVersion, GetParam().eglParameters);
// Default vulkan layers to enabled.
if (GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE)
{
mEGLWindow->setVulkanLayersEnabled(true);
}
}
ANGLETest::~ANGLETest()
......@@ -644,6 +650,11 @@ void ANGLETest::setBindGeneratesResource(bool bindGeneratesResource)
mEGLWindow->setBindGeneratesResource(bindGeneratesResource);
}
void ANGLETest::setVulkanLayersEnabled(bool enabled)
{
mEGLWindow->setVulkanLayersEnabled(enabled);
}
int ANGLETest::getClientMajorVersion() const
{
return mEGLWindow->getClientMajorVersion();
......
......@@ -196,6 +196,7 @@ class ANGLETest : public ::testing::TestWithParam<angle::PlatformParameters>
void setNoErrorEnabled(bool enabled);
void setWebGLCompatibilityEnabled(bool webglCompatibility);
void setBindGeneratesResource(bool bindGeneratesResource);
void setVulkanLayersEnabled(bool enabled);
int getClientMajorVersion() const;
int getClientMinorVersion() const;
......@@ -209,6 +210,8 @@ class ANGLETest : public ::testing::TestWithParam<angle::PlatformParameters>
void ignoreD3D11SDKLayersWarnings();
static OSWindow *GetOSWindow() { return mOSWindow; }
private:
bool createEGLContext();
bool destroyEGLContext();
......
Name: Khronos reference front-end for GLSL and ESSL
Short Name: glslang
URL: https://github.com/google/glslang
Version: N/A
Security Critical: yes
License: MIT
License File: LICENSE
Description:
An OpenGL and OpenGL ES shader front end and validator.
Name: SPIR-V Headers
Short Name: spirv-headers
URL: https://github.com/KhronosGroup/SPIRV-Headers.git
Version: Unknown
Security Critical: yes
License: MIT
License File: LICENSE
Description:
This repository contains machine-readable files from the SPIR-V Registry. This includes:
* Header files for various languages.
* JSON files describing the grammar for the SPIR-V core instruction set, and for the GLSL.std.450 extended instruction set.
* The XML registry file.
Name: SPIR-V Tools
Short Name: SPIRV-Tools
URL: https://github.com/KhronosGroup/SPIRV-Tools.git
Version: Unknown
Security Critical: yes
License: MIT
License File: LICENSE
Description:
The SPIR-V Tools project provides an API and commands for processing
SPIR-V modules.
......@@ -181,6 +181,14 @@ bool EGLWindow::initializeGL(OSWindow *osWindow)
displayAttributes.push_back(EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE);
displayAttributes.push_back(mPlatform.presentPath);
}
// Set vulkan validation layer settings if requested.
if (mVulkanLayersEnabled.valid())
{
displayAttributes.push_back(EGL_PLATFORM_ANGLE_ENABLE_VALIDATION_LAYER_ANGLE);
displayAttributes.push_back(mVulkanLayersEnabled.value() ? EGL_TRUE : EGL_FALSE);
}
displayAttributes.push_back(EGL_NONE);
mDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE,
......
......@@ -20,6 +20,7 @@
#include <EGL/eglext.h>
#include "common/angleutils.h"
#include "common/Optional.h"
class OSWindow;
......@@ -76,6 +77,7 @@ class ANGLE_EXPORT EGLWindow : angle::NonCopyable
{
mBindGeneratesResource = bindGeneratesResource;
}
void setVulkanLayersEnabled(bool enabled) { mVulkanLayersEnabled = enabled; }
void setSwapInterval(EGLint swapInterval) { mSwapInterval = swapInterval; }
static EGLBoolean FindEGLConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *config);
......@@ -124,6 +126,7 @@ class ANGLE_EXPORT EGLWindow : angle::NonCopyable
bool mWebGLCompatibility;
bool mBindGeneratesResource;
EGLint mSwapInterval;
Optional<bool> mVulkanLayersEnabled;
};
#endif // UTIL_EGLWINDOW_H_
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment