Commit 199f4294 by Yuly Novikov Committed by Commit Bot

Vulkan: Enable on Android

Add Android DisplayVk and WindowSurfaceVk variants. Build Vulkan backend and validation layers on Android if toolchain uses required NDK API level. Fix validation layers discovery to work on Android. BUG=angleproject:2314 TEST=angle_end2end_tests builds and runs on Nexus 5X, 12 VULKAN tests pass Change-Id: Iac2ec4ecd6470a7552f9f60c023ba1760aa090c5 Reviewed-on: https://chromium-review.googlesource.com/887797Reviewed-by: 's avatarYuly Novikov <ynovikov@chromium.org> Commit-Queue: Yuly Novikov <ynovikov@chromium.org>
parent bd6ae4aa
...@@ -505,6 +505,10 @@ static_library("libANGLE") { ...@@ -505,6 +505,10 @@ static_library("libANGLE") {
if (is_linux) { if (is_linux) {
sources += rebase_path(gles_gypi.libangle_vulkan_xcb_sources, ".", "src") sources += rebase_path(gles_gypi.libangle_vulkan_xcb_sources, ".", "src")
} }
if (is_android) {
sources +=
rebase_path(gles_gypi.libangle_vulkan_android_sources, ".", "src")
}
deps += [ "src/vulkan_support:angle_vulkan" ] deps += [ "src/vulkan_support:angle_vulkan" ]
public_deps += [ "src/vulkan_support:vulkan_headers" ] public_deps += [ "src/vulkan_support:vulkan_headers" ]
} }
......
...@@ -4,6 +4,9 @@ ...@@ -4,6 +4,9 @@
import("//build_overrides/build.gni") import("//build_overrides/build.gni")
import("//build/config/ui.gni") # import the use_x11 variable import("//build/config/ui.gni") # import the use_x11 variable
if (is_android) {
import("//build/config/android/config.gni")
}
if (build_with_chromium) { if (build_with_chromium) {
angle_root = "//third_party/angle" angle_root = "//third_party/angle"
...@@ -18,10 +21,21 @@ if (build_with_chromium) { ...@@ -18,10 +21,21 @@ if (build_with_chromium) {
} }
declare_args() { declare_args() {
if (!is_android) {
ndk_supports_vulkan = false
} else {
ndk_supports_vulkan =
(current_cpu == "arm" && android32_ndk_api_level >= 24) ||
(current_cpu == "arm64" && android64_ndk_api_level >= 24)
}
}
declare_args() {
angle_enable_d3d9 = is_win angle_enable_d3d9 = is_win
angle_enable_d3d11 = is_win angle_enable_d3d11 = is_win
angle_enable_gl = ozone_platform_gbm || !is_linux || (use_x11 && !is_chromeos) angle_enable_gl = ozone_platform_gbm || !is_linux || (use_x11 && !is_chromeos)
angle_enable_vulkan = is_win || (is_linux && use_x11 && !is_chromeos) angle_enable_vulkan = is_win || (is_linux && use_x11 && !is_chromeos) ||
(is_android && ndk_supports_vulkan)
angle_enable_null = true angle_enable_null = true
angle_enable_essl = true angle_enable_essl = true
angle_enable_glsl = true angle_enable_glsl = true
......
...@@ -64,6 +64,8 @@ ...@@ -64,6 +64,8 @@
#include "libANGLE/renderer/vulkan/win32/DisplayVkWin32.h" #include "libANGLE/renderer/vulkan/win32/DisplayVkWin32.h"
#elif defined(ANGLE_PLATFORM_LINUX) #elif defined(ANGLE_PLATFORM_LINUX)
#include "libANGLE/renderer/vulkan/xcb/DisplayVkXcb.h" #include "libANGLE/renderer/vulkan/xcb/DisplayVkXcb.h"
#elif defined(ANGLE_PLATFORM_ANDROID)
#include "libANGLE/renderer/vulkan/android/DisplayVkAndroid.h"
#else #else
#error Unsupported Vulkan platform. #error Unsupported Vulkan platform.
#endif #endif
...@@ -210,6 +212,8 @@ rx::DisplayImpl *CreateDisplayFromAttribs(const AttributeMap &attribMap, const D ...@@ -210,6 +212,8 @@ rx::DisplayImpl *CreateDisplayFromAttribs(const AttributeMap &attribMap, const D
impl = new rx::DisplayVkWin32(state); impl = new rx::DisplayVkWin32(state);
#elif defined(ANGLE_PLATFORM_LINUX) #elif defined(ANGLE_PLATFORM_LINUX)
impl = new rx::DisplayVkXcb(state); impl = new rx::DisplayVkXcb(state);
#elif defined(ANGLE_PLATFORM_ANDROID)
impl = new rx::DisplayVkAndroid(state);
#else #else
#error Unsupported Vulkan platform. #error Unsupported Vulkan platform.
#endif #endif
......
...@@ -47,51 +47,6 @@ egl::Error DisplayVk::makeCurrent(egl::Surface * /*drawSurface*/, ...@@ -47,51 +47,6 @@ egl::Error DisplayVk::makeCurrent(egl::Surface * /*drawSurface*/,
return egl::NoError(); return egl::NoError();
} }
egl::ConfigSet DisplayVk::generateConfigs()
{
// TODO(jmadill): Multiple configs, pbuffers, and proper checking of config attribs.
egl::Config singleton;
singleton.renderTargetFormat = GL_BGRA8_EXT;
singleton.depthStencilFormat = GL_NONE;
singleton.bufferSize = 32;
singleton.redSize = 8;
singleton.greenSize = 8;
singleton.blueSize = 8;
singleton.alphaSize = 8;
singleton.alphaMaskSize = 0;
singleton.bindToTextureRGB = EGL_FALSE;
singleton.bindToTextureRGBA = EGL_FALSE;
singleton.colorBufferType = EGL_RGB_BUFFER;
singleton.configCaveat = EGL_NONE;
singleton.conformant = 0;
singleton.depthSize = 0;
singleton.stencilSize = 0;
singleton.level = 0;
singleton.matchNativePixmap = EGL_NONE;
singleton.maxPBufferWidth = 0;
singleton.maxPBufferHeight = 0;
singleton.maxPBufferPixels = 0;
singleton.maxSwapInterval = 1;
singleton.minSwapInterval = 1;
singleton.nativeRenderable = EGL_TRUE;
singleton.nativeVisualID = 0;
singleton.nativeVisualType = EGL_NONE;
singleton.renderableType = EGL_OPENGL_ES2_BIT;
singleton.sampleBuffers = 0;
singleton.samples = 0;
singleton.surfaceType = EGL_WINDOW_BIT;
singleton.optimalOrientation = 0;
singleton.transparentType = EGL_NONE;
singleton.transparentRedValue = 0;
singleton.transparentGreenValue = 0;
singleton.transparentBlueValue = 0;
singleton.colorComponentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
egl::ConfigSet configSet;
configSet.add(singleton);
return configSet;
}
bool DisplayVk::testDeviceLost() bool DisplayVk::testDeviceLost()
{ {
// TODO(jmadill): Figure out how to do device lost in Vulkan. // TODO(jmadill): Figure out how to do device lost in Vulkan.
......
...@@ -29,8 +29,6 @@ class DisplayVk : public DisplayImpl ...@@ -29,8 +29,6 @@ class DisplayVk : public DisplayImpl
egl::Surface *readSurface, egl::Surface *readSurface,
gl::Context *context) override; gl::Context *context) override;
egl::ConfigSet generateConfigs() override;
bool testDeviceLost() override; bool testDeviceLost() override;
egl::Error restoreLostDevice(const egl::Display *display) override; egl::Error restoreLostDevice(const egl::Display *display) override;
......
...@@ -55,14 +55,14 @@ VkResult VerifyExtensionsPresent(const std::vector<VkExtensionProperties> &exten ...@@ -55,14 +55,14 @@ VkResult VerifyExtensionsPresent(const std::vector<VkExtensionProperties> &exten
return VK_SUCCESS; return VK_SUCCESS;
} }
VkBool32 VKAPI_CALL DebugReportCallback(VkDebugReportFlagsEXT flags, VKAPI_ATTR VkBool32 VKAPI_CALL DebugReportCallback(VkDebugReportFlagsEXT flags,
VkDebugReportObjectTypeEXT objectType, VkDebugReportObjectTypeEXT objectType,
uint64_t object, uint64_t object,
size_t location, size_t location,
int32_t messageCode, int32_t messageCode,
const char *layerPrefix, const char *layerPrefix,
const char *message, const char *message,
void *userData) void *userData)
{ {
if ((flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) != 0) if ((flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) != 0)
{ {
...@@ -85,6 +85,71 @@ VkBool32 VKAPI_CALL DebugReportCallback(VkDebugReportFlagsEXT flags, ...@@ -85,6 +85,71 @@ VkBool32 VKAPI_CALL DebugReportCallback(VkDebugReportFlagsEXT flags,
return VK_FALSE; return VK_FALSE;
} }
// If we're loading the validation layers, we could be running from any random directory.
// Change to the executable directory so we can find the layers, then change back to the
// previous directory to be safe we don't disrupt the application.
class ScopedVkLoaderEnvironment : angle::NonCopyable
{
public:
ScopedVkLoaderEnvironment(bool enableValidationLayers)
: mEnableValidationLayers(enableValidationLayers), mChangedCWD(false)
{
// Changing CWD and setting environment variables makes no sense on Android,
// since this code is a part of Java application there.
// Android Vulkan loader doesn't need this either.
#if !defined(ANGLE_PLATFORM_ANDROID)
if (mEnableValidationLayers)
{
const auto &cwd = angle::GetCWD();
if (!cwd.valid())
{
ERR() << "Error getting CWD for Vulkan layers init.";
mEnableValidationLayers = false;
}
else
{
mPreviousCWD = cwd.value();
const char *exeDir = angle::GetExecutableDirectory();
mChangedCWD = angle::SetCWD(exeDir);
if (!mChangedCWD)
{
ERR() << "Error setting CWD for Vulkan layers init.";
mEnableValidationLayers = false;
}
}
}
// Override environment variable to use the ANGLE layers.
if (mEnableValidationLayers)
{
if (!angle::SetEnvironmentVar(g_VkLoaderLayersPathEnv, ANGLE_VK_LAYERS_DIR))
{
ERR() << "Error setting environment for Vulkan layers init.";
mEnableValidationLayers = false;
}
}
#endif // !defined(ANGLE_PLATFORM_ANDROID)
}
~ScopedVkLoaderEnvironment()
{
if (mChangedCWD)
{
#if !defined(ANGLE_PLATFORM_ANDROID)
ASSERT(mPreviousCWD.valid());
angle::SetCWD(mPreviousCWD.value().c_str());
#endif // !defined(ANGLE_PLATFORM_ANDROID)
}
}
bool canEnableValidationLayers() { return mEnableValidationLayers; }
private:
bool mEnableValidationLayers;
bool mChangedCWD;
Optional<std::string> mPreviousCWD;
};
} // anonymous namespace } // anonymous namespace
// CommandBatch implementation. // CommandBatch implementation.
...@@ -187,40 +252,8 @@ vk::Error RendererVk::initialize(const egl::AttributeMap &attribs, const char *w ...@@ -187,40 +252,8 @@ vk::Error RendererVk::initialize(const egl::AttributeMap &attribs, const char *w
{ {
mEnableValidationLayers = ShouldUseDebugLayers(attribs); mEnableValidationLayers = ShouldUseDebugLayers(attribs);
// If we're loading the validation layers, we could be running from any random directory. ScopedVkLoaderEnvironment scopedEnvironment(mEnableValidationLayers);
// Change to the executable directory so we can find the layers, then change back to the mEnableValidationLayers = scopedEnvironment.canEnableValidationLayers();
// previous directory to be safe we don't disrupt the application.
std::string previousCWD;
if (mEnableValidationLayers)
{
const auto &cwd = angle::GetCWD();
if (!cwd.valid())
{
ERR() << "Error getting CWD for Vulkan layers init.";
mEnableValidationLayers = false;
}
else
{
previousCWD = cwd.value();
const char *exeDir = angle::GetExecutableDirectory();
if (!angle::SetCWD(exeDir))
{
ERR() << "Error setting CWD for Vulkan layers init.";
mEnableValidationLayers = false;
}
}
}
// Override environment variable to use the ANGLE layers.
if (mEnableValidationLayers)
{
if (!angle::SetEnvironmentVar(g_VkLoaderLayersPathEnv, ANGLE_VK_LAYERS_DIR))
{
ERR() << "Error setting environment for Vulkan layers init.";
mEnableValidationLayers = false;
}
}
// Gather global layer properties. // Gather global layer properties.
uint32_t instanceLayerCount = 0; uint32_t instanceLayerCount = 0;
...@@ -243,23 +276,14 @@ vk::Error RendererVk::initialize(const egl::AttributeMap &attribs, const char *w ...@@ -243,23 +276,14 @@ vk::Error RendererVk::initialize(const egl::AttributeMap &attribs, const char *w
instanceExtensionProps.data())); instanceExtensionProps.data()));
} }
const char *const *enabledLayerNames = nullptr;
uint32_t enabledLayerCount = 0;
if (mEnableValidationLayers) if (mEnableValidationLayers)
{ {
// Verify the standard validation layers are available. bool layersRequested =
if (!HasStandardValidationLayer(instanceLayerProps)) (attribs.get(EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE, EGL_DONT_CARE) == EGL_TRUE);
{ mEnableValidationLayers = GetAvailableValidationLayers(
// Generate an error if the attribute was requested, warning otherwise. instanceLayerProps, layersRequested, &enabledLayerNames, &enabledLayerCount);
if (attribs.get(EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE, EGL_DONT_CARE) ==
EGL_TRUE)
{
ERR() << "Vulkan standard validation layers are missing.";
}
else
{
WARN() << "Vulkan standard validation layers are missing.";
}
mEnableValidationLayers = false;
}
} }
std::vector<const char *> enabledInstanceExtensions; std::vector<const char *> enabledInstanceExtensions;
...@@ -294,18 +318,13 @@ vk::Error RendererVk::initialize(const egl::AttributeMap &attribs, const char *w ...@@ -294,18 +318,13 @@ vk::Error RendererVk::initialize(const egl::AttributeMap &attribs, const char *w
instanceInfo.enabledExtensionCount = static_cast<uint32_t>(enabledInstanceExtensions.size()); instanceInfo.enabledExtensionCount = static_cast<uint32_t>(enabledInstanceExtensions.size());
instanceInfo.ppEnabledExtensionNames = instanceInfo.ppEnabledExtensionNames =
enabledInstanceExtensions.empty() ? nullptr : enabledInstanceExtensions.data(); enabledInstanceExtensions.empty() ? nullptr : enabledInstanceExtensions.data();
instanceInfo.enabledLayerCount = mEnableValidationLayers ? 1u : 0u; instanceInfo.enabledLayerCount = enabledLayerCount;
instanceInfo.ppEnabledLayerNames = instanceInfo.ppEnabledLayerNames = enabledLayerNames;
mEnableValidationLayers ? &g_VkStdValidationLayerName : nullptr;
ANGLE_VK_TRY(vkCreateInstance(&instanceInfo, nullptr, &mInstance)); ANGLE_VK_TRY(vkCreateInstance(&instanceInfo, nullptr, &mInstance));
if (mEnableValidationLayers) if (mEnableValidationLayers)
{ {
// Change back to the previous working directory now that we've loaded the instance -
// the validation layers should be loaded at this point.
angle::SetCWD(previousCWD.c_str());
VkDebugReportCallbackCreateInfoEXT debugReportInfo; VkDebugReportCallbackCreateInfoEXT debugReportInfo;
debugReportInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; debugReportInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
...@@ -406,13 +425,12 @@ vk::Error RendererVk::initializeDevice(uint32_t queueFamilyIndex) ...@@ -406,13 +425,12 @@ vk::Error RendererVk::initializeDevice(uint32_t queueFamilyIndex)
mPhysicalDevice, nullptr, &deviceExtensionCount, deviceExtensionProps.data())); mPhysicalDevice, nullptr, &deviceExtensionCount, deviceExtensionProps.data()));
} }
const char *const *enabledLayerNames = nullptr;
uint32_t enabledLayerCount = 0;
if (mEnableValidationLayers) if (mEnableValidationLayers)
{ {
if (!HasStandardValidationLayer(deviceLayerProps)) mEnableValidationLayers = GetAvailableValidationLayers(
{ deviceLayerProps, false, &enabledLayerNames, &enabledLayerCount);
WARN() << "Vulkan standard validation layer is missing.";
mEnableValidationLayers = false;
}
} }
std::vector<const char *> enabledDeviceExtensions; std::vector<const char *> enabledDeviceExtensions;
...@@ -439,9 +457,8 @@ vk::Error RendererVk::initializeDevice(uint32_t queueFamilyIndex) ...@@ -439,9 +457,8 @@ vk::Error RendererVk::initializeDevice(uint32_t queueFamilyIndex)
createInfo.flags = 0; createInfo.flags = 0;
createInfo.queueCreateInfoCount = 1; createInfo.queueCreateInfoCount = 1;
createInfo.pQueueCreateInfos = &queueCreateInfo; createInfo.pQueueCreateInfos = &queueCreateInfo;
createInfo.enabledLayerCount = mEnableValidationLayers ? 1u : 0u; createInfo.enabledLayerCount = enabledLayerCount;
createInfo.ppEnabledLayerNames = createInfo.ppEnabledLayerNames = enabledLayerNames;
mEnableValidationLayers ? &g_VkStdValidationLayerName : nullptr;
createInfo.enabledExtensionCount = static_cast<uint32_t>(enabledDeviceExtensions.size()); createInfo.enabledExtensionCount = static_cast<uint32_t>(enabledDeviceExtensions.size());
createInfo.ppEnabledExtensionNames = createInfo.ppEnabledExtensionNames =
enabledDeviceExtensions.empty() ? nullptr : enabledDeviceExtensions.data(); enabledDeviceExtensions.empty() ? nullptr : enabledDeviceExtensions.data();
......
//
// Copyright 2018 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.
//
// DisplayVkAndroid.cpp:
// Implements the class methods for DisplayVkAndroid.
//
#include "libANGLE/renderer/vulkan/android/DisplayVkAndroid.h"
#include <android/native_window.h>
#include <vulkan/vulkan.h>
#include "libANGLE/renderer/vulkan/android/WindowSurfaceVkAndroid.h"
namespace rx
{
DisplayVkAndroid::DisplayVkAndroid(const egl::DisplayState &state) : DisplayVk(state)
{
}
bool DisplayVkAndroid::isValidNativeWindow(EGLNativeWindowType window) const
{
return (ANativeWindow_getFormat(window) >= 0);
}
SurfaceImpl *DisplayVkAndroid::createWindowSurfaceVk(const egl::SurfaceState &state,
EGLNativeWindowType window,
EGLint width,
EGLint height)
{
return new WindowSurfaceVkAndroid(state, window, width, height);
}
egl::ConfigSet DisplayVkAndroid::generateConfigs()
{
// TODO(jmadill): Multiple configs, pbuffers, and proper checking of config attribs.
egl::Config singleton;
singleton.renderTargetFormat = GL_RGBA8;
singleton.depthStencilFormat = GL_NONE;
singleton.bufferSize = 32;
singleton.redSize = 8;
singleton.greenSize = 8;
singleton.blueSize = 8;
singleton.alphaSize = 8;
singleton.alphaMaskSize = 0;
singleton.bindToTextureRGB = EGL_FALSE;
singleton.bindToTextureRGBA = EGL_FALSE;
singleton.colorBufferType = EGL_RGB_BUFFER;
singleton.configCaveat = EGL_NONE;
singleton.conformant = 0;
singleton.depthSize = 0;
singleton.stencilSize = 0;
singleton.level = 0;
singleton.matchNativePixmap = EGL_NONE;
singleton.maxPBufferWidth = 0;
singleton.maxPBufferHeight = 0;
singleton.maxPBufferPixels = 0;
singleton.maxSwapInterval = 1;
singleton.minSwapInterval = 1;
singleton.nativeRenderable = EGL_TRUE;
singleton.nativeVisualID = 0;
singleton.nativeVisualType = EGL_NONE;
singleton.renderableType = EGL_OPENGL_ES2_BIT;
singleton.sampleBuffers = 0;
singleton.samples = 0;
singleton.surfaceType = EGL_WINDOW_BIT;
singleton.optimalOrientation = 0;
singleton.transparentType = EGL_NONE;
singleton.transparentRedValue = 0;
singleton.transparentGreenValue = 0;
singleton.transparentBlueValue = 0;
singleton.colorComponentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
egl::ConfigSet configSet;
configSet.add(singleton);
return configSet;
}
const char *DisplayVkAndroid::getWSIName() const
{
return VK_KHR_ANDROID_SURFACE_EXTENSION_NAME;
}
} // namespace rx
//
// Copyright 2018 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.
//
// DisplayVkAndroid.h:
// Defines the class interface for DisplayVkAndroid, implementing DisplayVk for Android.
//
#ifndef LIBANGLE_RENDERER_VULKAN_ANDROID_DISPLAYVKANDROID_H_
#define LIBANGLE_RENDERER_VULKAN_ANDROID_DISPLAYVKANDROID_H_
#include "libANGLE/renderer/vulkan/DisplayVk.h"
namespace rx
{
class DisplayVkAndroid : public DisplayVk
{
public:
DisplayVkAndroid(const egl::DisplayState &state);
bool isValidNativeWindow(EGLNativeWindowType window) const override;
SurfaceImpl *createWindowSurfaceVk(const egl::SurfaceState &state,
EGLNativeWindowType window,
EGLint width,
EGLint height) override;
egl::ConfigSet generateConfigs() override;
const char *getWSIName() const override;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_ANDROID_DISPLAYVKANDROID_H_
//
// Copyright 2018 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.
//
// WindowSurfaceVkAndroid.cpp:
// Implements the class methods for WindowSurfaceVkAndroid.
//
#include "libANGLE/renderer/vulkan/android/WindowSurfaceVkAndroid.h"
#include <android/native_window.h>
#include "libANGLE/renderer/vulkan/RendererVk.h"
namespace rx
{
WindowSurfaceVkAndroid::WindowSurfaceVkAndroid(const egl::SurfaceState &surfaceState,
EGLNativeWindowType window,
EGLint width,
EGLint height)
: WindowSurfaceVk(surfaceState, window, width, height)
{
}
vk::ErrorOrResult<gl::Extents> WindowSurfaceVkAndroid::createSurfaceVk(RendererVk *renderer)
{
VkAndroidSurfaceCreateInfoKHR createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
createInfo.pNext = nullptr;
createInfo.flags = 0;
createInfo.window = mNativeWindowType;
ANGLE_VK_TRY(
vkCreateAndroidSurfaceKHR(renderer->getInstance(), &createInfo, nullptr, &mSurface));
int32_t width = ANativeWindow_getWidth(mNativeWindowType);
int32_t height = ANativeWindow_getHeight(mNativeWindowType);
ANGLE_VK_CHECK(width > 0 && height > 0, VK_ERROR_INITIALIZATION_FAILED);
return gl::Extents(width, height, 0);
}
} // namespace rx
//
// Copyright 2018 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.
//
// WindowSurfaceVkAndroid.h:
// Defines the class interface for WindowSurfaceVkAndroid, implementing WindowSurfaceVk.
//
#ifndef LIBANGLE_RENDERER_VULKAN_ANDROID_WINDOWSURFACEVKANDROID_H_
#define LIBANGLE_RENDERER_VULKAN_ANDROID_WINDOWSURFACEVKANDROID_H_
#include "libANGLE/renderer/vulkan/SurfaceVk.h"
namespace rx
{
class WindowSurfaceVkAndroid : public WindowSurfaceVk
{
public:
WindowSurfaceVkAndroid(const egl::SurfaceState &surfaceState,
EGLNativeWindowType window,
EGLint width,
EGLint height);
private:
vk::ErrorOrResult<gl::Extents> createSurfaceVk(RendererVk *renderer) override;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_ANDROID_WINDOWSURFACEVKANDROID_H_
...@@ -107,11 +107,48 @@ VkImageUsageFlags GetStagingBufferUsageFlags(vk::StagingUsage usage) ...@@ -107,11 +107,48 @@ VkImageUsageFlags GetStagingBufferUsageFlags(vk::StagingUsage usage)
} }
} }
// Mirrors std_validation_str in loader.c
const char *g_VkStdValidationLayerName = "VK_LAYER_LUNARG_standard_validation";
const char *g_VkValidationLayerNames[] = {
"VK_LAYER_GOOGLE_threading", "VK_LAYER_LUNARG_parameter_validation",
"VK_LAYER_LUNARG_object_tracker", "VK_LAYER_LUNARG_core_validation",
"VK_LAYER_GOOGLE_unique_objects"};
const uint32_t g_VkNumValidationLayerNames =
sizeof(g_VkValidationLayerNames) / sizeof(g_VkValidationLayerNames[0]);
bool HasValidationLayer(const std::vector<VkLayerProperties> &layerProps, const char *layerName)
{
for (const auto &layerProp : layerProps)
{
if (std::string(layerProp.layerName) == layerName)
{
return true;
}
}
return false;
}
bool HasStandardValidationLayer(const std::vector<VkLayerProperties> &layerProps)
{
return HasValidationLayer(layerProps, g_VkStdValidationLayerName);
}
bool HasValidationLayers(const std::vector<VkLayerProperties> &layerProps)
{
for (const auto &layerName : g_VkValidationLayerNames)
{
if (!HasValidationLayer(layerProps, layerName))
{
return false;
}
}
return true;
}
} // anonymous namespace } // 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 *g_VkLoaderLayersPathEnv = "VK_LAYER_PATH"; const char *g_VkLoaderLayersPathEnv = "VK_LAYER_PATH";
const char *VulkanResultString(VkResult result) const char *VulkanResultString(VkResult result)
...@@ -175,17 +212,39 @@ const char *VulkanResultString(VkResult result) ...@@ -175,17 +212,39 @@ const char *VulkanResultString(VkResult result)
} }
} }
bool HasStandardValidationLayer(const std::vector<VkLayerProperties> &layerProps) bool GetAvailableValidationLayers(const std::vector<VkLayerProperties> &layerProps,
bool mustHaveLayers,
const char *const **enabledLayerNames,
uint32_t *enabledLayerCount)
{ {
for (const auto &layerProp : layerProps) if (HasStandardValidationLayer(layerProps))
{ {
if (std::string(layerProp.layerName) == g_VkStdValidationLayerName) *enabledLayerNames = &g_VkStdValidationLayerName;
*enabledLayerCount = 1;
}
else if (HasValidationLayers(layerProps))
{
*enabledLayerNames = g_VkValidationLayerNames;
*enabledLayerCount = g_VkNumValidationLayerNames;
}
else
{
// Generate an error if the layers were explicitly requested, warning otherwise.
if (mustHaveLayers)
{ {
return true; ERR() << "Vulkan validation layers are missing.";
} }
else
{
WARN() << "Vulkan validation layers are missing.";
}
*enabledLayerNames = nullptr;
*enabledLayerCount = 0;
return false;
} }
return false; return true;
} }
namespace vk namespace vk
......
...@@ -65,9 +65,12 @@ enum class DrawType ...@@ -65,9 +65,12 @@ enum class DrawType
ANGLE_GL_OBJECTS_X(ANGLE_PRE_DECLARE_VK_OBJECT); ANGLE_GL_OBJECTS_X(ANGLE_PRE_DECLARE_VK_OBJECT);
const char *VulkanResultString(VkResult result); const char *VulkanResultString(VkResult result);
bool HasStandardValidationLayer(const std::vector<VkLayerProperties> &layerProps); // Verify that validation layers are available.
bool GetAvailableValidationLayers(const std::vector<VkLayerProperties> &layerProps,
bool mustHaveLayers,
const char *const **enabledLayerNames,
uint32_t *enabledLayerCount);
extern const char *g_VkStdValidationLayerName;
extern const char *g_VkLoaderLayersPathEnv; extern const char *g_VkLoaderLayersPathEnv;
enum class TextureDimension enum class TextureDimension
......
...@@ -33,6 +33,51 @@ SurfaceImpl *DisplayVkWin32::createWindowSurfaceVk(const egl::SurfaceState &stat ...@@ -33,6 +33,51 @@ SurfaceImpl *DisplayVkWin32::createWindowSurfaceVk(const egl::SurfaceState &stat
return new WindowSurfaceVkWin32(state, window, width, height); return new WindowSurfaceVkWin32(state, window, width, height);
} }
egl::ConfigSet DisplayVkWin32::generateConfigs()
{
// TODO(jmadill): Multiple configs, pbuffers, and proper checking of config attribs.
egl::Config singleton;
singleton.renderTargetFormat = GL_BGRA8_EXT;
singleton.depthStencilFormat = GL_NONE;
singleton.bufferSize = 32;
singleton.redSize = 8;
singleton.greenSize = 8;
singleton.blueSize = 8;
singleton.alphaSize = 8;
singleton.alphaMaskSize = 0;
singleton.bindToTextureRGB = EGL_FALSE;
singleton.bindToTextureRGBA = EGL_FALSE;
singleton.colorBufferType = EGL_RGB_BUFFER;
singleton.configCaveat = EGL_NONE;
singleton.conformant = 0;
singleton.depthSize = 0;
singleton.stencilSize = 0;
singleton.level = 0;
singleton.matchNativePixmap = EGL_NONE;
singleton.maxPBufferWidth = 0;
singleton.maxPBufferHeight = 0;
singleton.maxPBufferPixels = 0;
singleton.maxSwapInterval = 1;
singleton.minSwapInterval = 1;
singleton.nativeRenderable = EGL_TRUE;
singleton.nativeVisualID = 0;
singleton.nativeVisualType = EGL_NONE;
singleton.renderableType = EGL_OPENGL_ES2_BIT;
singleton.sampleBuffers = 0;
singleton.samples = 0;
singleton.surfaceType = EGL_WINDOW_BIT;
singleton.optimalOrientation = 0;
singleton.transparentType = EGL_NONE;
singleton.transparentRedValue = 0;
singleton.transparentGreenValue = 0;
singleton.transparentBlueValue = 0;
singleton.colorComponentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
egl::ConfigSet configSet;
configSet.add(singleton);
return configSet;
}
const char *DisplayVkWin32::getWSIName() const const char *DisplayVkWin32::getWSIName() const
{ {
return VK_KHR_WIN32_SURFACE_EXTENSION_NAME; return VK_KHR_WIN32_SURFACE_EXTENSION_NAME;
......
...@@ -26,6 +26,8 @@ class DisplayVkWin32 : public DisplayVk ...@@ -26,6 +26,8 @@ class DisplayVkWin32 : public DisplayVk
EGLint width, EGLint width,
EGLint height) override; EGLint height) override;
egl::ConfigSet generateConfigs() override;
const char *getWSIName() const override; const char *getWSIName() const override;
}; };
......
...@@ -61,6 +61,51 @@ SurfaceImpl *DisplayVkXcb::createWindowSurfaceVk(const egl::SurfaceState &state, ...@@ -61,6 +61,51 @@ SurfaceImpl *DisplayVkXcb::createWindowSurfaceVk(const egl::SurfaceState &state,
return new WindowSurfaceVkXcb(state, window, width, height, mXcbConnection); return new WindowSurfaceVkXcb(state, window, width, height, mXcbConnection);
} }
egl::ConfigSet DisplayVkXcb::generateConfigs()
{
// TODO(jmadill): Multiple configs, pbuffers, and proper checking of config attribs.
egl::Config singleton;
singleton.renderTargetFormat = GL_BGRA8_EXT;
singleton.depthStencilFormat = GL_NONE;
singleton.bufferSize = 32;
singleton.redSize = 8;
singleton.greenSize = 8;
singleton.blueSize = 8;
singleton.alphaSize = 8;
singleton.alphaMaskSize = 0;
singleton.bindToTextureRGB = EGL_FALSE;
singleton.bindToTextureRGBA = EGL_FALSE;
singleton.colorBufferType = EGL_RGB_BUFFER;
singleton.configCaveat = EGL_NONE;
singleton.conformant = 0;
singleton.depthSize = 0;
singleton.stencilSize = 0;
singleton.level = 0;
singleton.matchNativePixmap = EGL_NONE;
singleton.maxPBufferWidth = 0;
singleton.maxPBufferHeight = 0;
singleton.maxPBufferPixels = 0;
singleton.maxSwapInterval = 1;
singleton.minSwapInterval = 1;
singleton.nativeRenderable = EGL_TRUE;
singleton.nativeVisualID = 0;
singleton.nativeVisualType = EGL_NONE;
singleton.renderableType = EGL_OPENGL_ES2_BIT;
singleton.sampleBuffers = 0;
singleton.samples = 0;
singleton.surfaceType = EGL_WINDOW_BIT;
singleton.optimalOrientation = 0;
singleton.transparentType = EGL_NONE;
singleton.transparentRedValue = 0;
singleton.transparentGreenValue = 0;
singleton.transparentBlueValue = 0;
singleton.colorComponentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
egl::ConfigSet configSet;
configSet.add(singleton);
return configSet;
}
const char *DisplayVkXcb::getWSIName() const const char *DisplayVkXcb::getWSIName() const
{ {
return VK_KHR_XCB_SURFACE_EXTENSION_NAME; return VK_KHR_XCB_SURFACE_EXTENSION_NAME;
......
...@@ -32,6 +32,8 @@ class DisplayVkXcb : public DisplayVk ...@@ -32,6 +32,8 @@ class DisplayVkXcb : public DisplayVk
EGLint width, EGLint width,
EGLint height) override; EGLint height) override;
egl::ConfigSet generateConfigs() override;
const char *getWSIName() const override; const char *getWSIName() const override;
private: private:
......
...@@ -765,6 +765,13 @@ ...@@ -765,6 +765,13 @@
'libANGLE/renderer/vulkan/vk_utils.cpp', 'libANGLE/renderer/vulkan/vk_utils.cpp',
'libANGLE/renderer/vulkan/vk_utils.h', 'libANGLE/renderer/vulkan/vk_utils.h',
], ],
'libangle_vulkan_android_sources':
[
'libANGLE/renderer/vulkan/android/DisplayVkAndroid.cpp',
'libANGLE/renderer/vulkan/android/DisplayVkAndroid.h',
'libANGLE/renderer/vulkan/android/WindowSurfaceVkAndroid.cpp',
'libANGLE/renderer/vulkan/android/WindowSurfaceVkAndroid.h',
],
'libangle_vulkan_win32_sources': 'libangle_vulkan_win32_sources':
[ [
'libANGLE/renderer/vulkan/win32/DisplayVkWin32.cpp', 'libANGLE/renderer/vulkan/win32/DisplayVkWin32.cpp',
......
...@@ -227,6 +227,13 @@ config("vulkan_config") { ...@@ -227,6 +227,13 @@ config("vulkan_config") {
"VK_USE_PLATFORM_XCB_KHX", "VK_USE_PLATFORM_XCB_KHX",
] ]
} }
if (is_android) {
defines = [
"VK_USE_PLATFORM_ANDROID_KHR",
"VK_USE_PLATFORM_ANDROID_KHX",
]
libs = [ "vulkan" ]
}
} }
config("vulkan_internal_config") { config("vulkan_internal_config") {
...@@ -270,61 +277,63 @@ config("vulkan_loader_config") { ...@@ -270,61 +277,63 @@ config("vulkan_loader_config") {
} }
} }
static_library("vulkan_loader") { if (!is_android) {
sources = [ static_library("vulkan_loader") {
"$vulkan_layers_dir/loader/cJSON.c", sources = [
"$vulkan_layers_dir/loader/cJSON.h", "$vulkan_layers_dir/loader/cJSON.c",
"$vulkan_layers_dir/loader/debug_report.c", "$vulkan_layers_dir/loader/cJSON.h",
"$vulkan_layers_dir/loader/debug_report.h", "$vulkan_layers_dir/loader/debug_report.c",
"$vulkan_layers_dir/loader/dev_ext_trampoline.c", "$vulkan_layers_dir/loader/debug_report.h",
"$vulkan_layers_dir/loader/extension_manual.c", "$vulkan_layers_dir/loader/dev_ext_trampoline.c",
"$vulkan_layers_dir/loader/extension_manual.h", "$vulkan_layers_dir/loader/extension_manual.c",
"$vulkan_layers_dir/loader/gpa_helper.h", "$vulkan_layers_dir/loader/extension_manual.h",
"$vulkan_layers_dir/loader/loader.c", "$vulkan_layers_dir/loader/gpa_helper.h",
"$vulkan_layers_dir/loader/loader.h", "$vulkan_layers_dir/loader/loader.c",
"$vulkan_layers_dir/loader/murmurhash.c", "$vulkan_layers_dir/loader/loader.h",
"$vulkan_layers_dir/loader/murmurhash.h", "$vulkan_layers_dir/loader/murmurhash.c",
"$vulkan_layers_dir/loader/phys_dev_ext.c", "$vulkan_layers_dir/loader/murmurhash.h",
"$vulkan_layers_dir/loader/trampoline.c", "$vulkan_layers_dir/loader/phys_dev_ext.c",
"$vulkan_layers_dir/loader/trampoline.c",
# TODO(jmadill): Use assembler where available.
"$vulkan_layers_dir/loader/unknown_ext_chain.c", # TODO(jmadill): Use assembler where available.
"$vulkan_layers_dir/loader/vk_loader_platform.h", "$vulkan_layers_dir/loader/unknown_ext_chain.c",
"$vulkan_layers_dir/loader/wsi.c", "$vulkan_layers_dir/loader/vk_loader_platform.h",
"$vulkan_layers_dir/loader/wsi.h", "$vulkan_layers_dir/loader/wsi.c",
] "$vulkan_layers_dir/loader/wsi.h",
if (is_win) {
sources += [
"$vulkan_layers_dir/loader/dirent_on_windows.c",
"$vulkan_layers_dir/loader/dirent_on_windows.h",
] ]
if (!is_clang) { if (is_win) {
cflags = [ sources += [
"/wd4054", # Type cast from function pointer "$vulkan_layers_dir/loader/dirent_on_windows.c",
"/wd4055", # Type cast from data pointer "$vulkan_layers_dir/loader/dirent_on_windows.h",
"/wd4100", # Unreferenced formal parameter
"/wd4152", # Nonstandard extension used (pointer conversion)
"/wd4201", # Nonstandard extension used: nameless struct/union
"/wd4214", # Nonstandard extension used: bit field types other than int
"/wd4232", # Nonstandard extension used: address of dllimport is not static
"/wd4305", # Type cast truncation
"/wd4706", # Assignment within conditional expression
"/wd4996", # Unsafe stdlib function
] ]
if (!is_clang) {
cflags = [
"/wd4054", # Type cast from function pointer
"/wd4055", # Type cast from data pointer
"/wd4100", # Unreferenced formal parameter
"/wd4152", # Nonstandard extension used (pointer conversion)
"/wd4201", # Nonstandard extension used: nameless struct/union
"/wd4214", # Nonstandard extension used: bit field types other than int
"/wd4232", # Nonstandard extension used: address of dllimport is not static
"/wd4305", # Type cast truncation
"/wd4706", # Assignment within conditional expression
"/wd4996", # Unsafe stdlib function
]
}
} }
deps = [
":vulkan_generate_helper_files",
]
public_deps = [
":vulkan_headers",
]
configs += [ ":vulkan_internal_config" ]
public_configs = [
":vulkan_config",
":vulkan_loader_config",
]
configs -= vulkan_undefine_configs
} }
deps = [
":vulkan_generate_helper_files",
]
public_deps = [
":vulkan_headers",
]
configs += [ ":vulkan_internal_config" ]
public_configs = [
":vulkan_config",
":vulkan_loader_config",
]
configs -= vulkan_undefine_configs
} }
# SPIRV-tools # SPIRV-tools
...@@ -680,7 +689,7 @@ static_library("glslang") { ...@@ -680,7 +689,7 @@ static_library("glslang") {
sources += [ "$glslang_dir/glslang/OSDependent/Windows/ossource.cpp" ] sources += [ "$glslang_dir/glslang/OSDependent/Windows/ossource.cpp" ]
} }
if (is_linux) { if (is_linux || is_android) {
sources += [ "$glslang_dir/glslang/OSDependent/Unix/ossource.cpp" ] sources += [ "$glslang_dir/glslang/OSDependent/Unix/ossource.cpp" ]
} }
} }
...@@ -782,41 +791,43 @@ layers = [ ...@@ -782,41 +791,43 @@ layers = [
], ],
] ]
vulkan_gen_json_files_outputs = [ if (!is_android) {
"$root_out_dir/$data_dir/VkLayer_core_validation.json", vulkan_gen_json_files_outputs = [
"$root_out_dir/$data_dir/VkLayer_object_tracker.json", "$root_out_dir/$data_dir/VkLayer_core_validation.json",
"$root_out_dir/$data_dir/VkLayer_parameter_validation.json", "$root_out_dir/$data_dir/VkLayer_object_tracker.json",
"$root_out_dir/$data_dir/VkLayer_threading.json", "$root_out_dir/$data_dir/VkLayer_parameter_validation.json",
"$root_out_dir/$data_dir/VkLayer_unique_objects.json", "$root_out_dir/$data_dir/VkLayer_threading.json",
] "$root_out_dir/$data_dir/VkLayer_unique_objects.json",
]
action("vulkan_gen_json_files") { action("vulkan_gen_json_files") {
script = "$angle_root/scripts/generate_vulkan_layers_json.py" script = "$angle_root/scripts/generate_vulkan_layers_json.py"
if (is_win) { if (is_win) {
sources = [ sources = [
"$vulkan_layers_dir/layers/windows/VkLayer_core_validation.json", "$vulkan_layers_dir/layers/windows/VkLayer_core_validation.json",
"$vulkan_layers_dir/layers/windows/VkLayer_object_tracker.json", "$vulkan_layers_dir/layers/windows/VkLayer_object_tracker.json",
"$vulkan_layers_dir/layers/windows/VkLayer_parameter_validation.json", "$vulkan_layers_dir/layers/windows/VkLayer_parameter_validation.json",
"$vulkan_layers_dir/layers/windows/VkLayer_threading.json", "$vulkan_layers_dir/layers/windows/VkLayer_threading.json",
"$vulkan_layers_dir/layers/windows/VkLayer_unique_objects.json", "$vulkan_layers_dir/layers/windows/VkLayer_unique_objects.json",
] ]
args = [ "$raw_vulkan_layers_dir/layers/windows" ] args = [ "$raw_vulkan_layers_dir/layers/windows" ]
} }
if (is_linux) { if (is_linux) {
sources = [ sources = [
"$vulkan_layers_dir/layers/linux/VkLayer_core_validation.json", "$vulkan_layers_dir/layers/linux/VkLayer_core_validation.json",
"$vulkan_layers_dir/layers/linux/VkLayer_object_tracker.json", "$vulkan_layers_dir/layers/linux/VkLayer_object_tracker.json",
"$vulkan_layers_dir/layers/linux/VkLayer_parameter_validation.json", "$vulkan_layers_dir/layers/linux/VkLayer_parameter_validation.json",
"$vulkan_layers_dir/layers/linux/VkLayer_threading.json", "$vulkan_layers_dir/layers/linux/VkLayer_threading.json",
"$vulkan_layers_dir/layers/linux/VkLayer_unique_objects.json", "$vulkan_layers_dir/layers/linux/VkLayer_unique_objects.json",
] ]
args = [ "$raw_vulkan_layers_dir/layers/linux" ] args = [ "$raw_vulkan_layers_dir/layers/linux" ]
} }
# The layer JSON files are part of the necessary data deps. # The layer JSON files are part of the necessary data deps.
outputs = vulkan_gen_json_files_outputs outputs = vulkan_gen_json_files_outputs
data = vulkan_gen_json_files_outputs data = vulkan_gen_json_files_outputs
args += [ rebase_path("$root_out_dir/$data_dir", root_build_dir) ] args += [ rebase_path("$root_out_dir/$data_dir", root_build_dir) ]
}
} }
source_set("vulkan_layer_utils") { source_set("vulkan_layer_utils") {
...@@ -900,9 +911,13 @@ foreach(layer_info, layers) { ...@@ -900,9 +911,13 @@ foreach(layer_info, layers) {
if (is_win) { if (is_win) {
sources += [ "$vulkan_layers_dir/layers/VkLayer_$name.def" ] sources += [ "$vulkan_layers_dir/layers/VkLayer_$name.def" ]
} }
if (is_linux) { if (is_linux || is_android) {
ldflags = [ "-Wl,-Bsymbolic,--exclude-libs,ALL" ] ldflags = [ "-Wl,-Bsymbolic,--exclude-libs,ALL" ]
} }
if (is_android) {
libs = [ "log" ]
configs -= [ "//build/config/android:hide_all_but_jni_onload" ]
}
} }
} }
...@@ -910,21 +925,22 @@ foreach(layer_info, layers) { ...@@ -910,21 +925,22 @@ foreach(layer_info, layers) {
group("angle_vulkan") { group("angle_vulkan") {
deps = [ deps = [
":glslang", ":glslang",
":vulkan_loader",
] ]
public_deps = [ public_deps = [
":vulkan_headers", ":vulkan_headers",
] ]
data_deps = [ data_deps = []
":vulkan_gen_json_files",
]
foreach(layer_info, layers) { foreach(layer_info, layers) {
name = layer_info[0] name = layer_info[0]
data_deps += [ ":VkLayer_$name" ] data_deps += [ ":VkLayer_$name" ]
} }
public_configs = [ public_configs = [
":vulkan_config",
":vulkan_loader_config",
":glslang_config", ":glslang_config",
":vulkan_config",
] ]
if (!is_android) {
deps += [ ":vulkan_loader" ]
data_deps += [ ":vulkan_gen_json_files" ]
public_configs += [ ":vulkan_loader_config" ]
}
} }
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