Commit 5afd5ec6 by Jonah Ryan-Davis Committed by Commit Bot

Vulkan support for MacOS (using SwiftShader)

Created a new WindowSurface/Display for MacOS/Vulkan, along with some GN changes to get it working. Bug: 1015454 Change-Id: I3f7a12f173795efe598856c702ce53b1e50831eb Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1880163 Commit-Queue: Jonah Ryan-Davis <jonahr@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 39f3ccda
......@@ -449,6 +449,10 @@ angle_static_library("translator") {
defines += [ "ANGLE_ENABLE_METAL" ]
}
if (angle_enable_swiftshader) {
defines += [ "ANGLE_ENABLE_SWIFTSHADER" ]
}
public_configs += [ ":external_config" ]
deps = [
......@@ -549,12 +553,14 @@ config("angle_backend_config") {
defines += [ "ANGLE_ENABLE_NULL" ]
}
configs = []
if (angle_enable_metal) {
configs = [ "src/libANGLE/renderer/metal:angle_metal_backend_config" ]
configs += [ "src/libANGLE/renderer/metal:angle_metal_backend_config" ]
}
if (angle_enable_vulkan) {
configs = [ "src/libANGLE/renderer/vulkan:angle_vulkan_backend_config" ]
configs += [ "src/libANGLE/renderer/vulkan:angle_vulkan_backend_config" ]
}
}
......
......@@ -47,7 +47,7 @@ To specify the exact platform for ANGLE + dEQP, use the arguments:
* `--deqp-egl-display-type=angle-gl` for OpenGL Desktop (OSX, Linux and Windows)
* `--deqp-egl-display-type=angle-gles` for OpenGL ES (Android/ChromeOS, some Windows platforms)
* `--deqp-egl-display-type=angle-vulkan` for Vulkan (Android, Linux, Windows)
* `--deqp-egl-display-type=angle-swiftshader` for Vulkan with SwiftShader as driver (Android, Linux, Windows)
* `--deqp-egl-display-type=angle-swiftshader` for Vulkan with SwiftShader as driver (Android, Linux, Mac, Windows)
The flag `--use-angle=X` has the same effect as `--deqp-egl-display-type=angle-X`.
......
......@@ -93,10 +93,10 @@ declare_args() {
# Vulkan Validation Layers compatibility issues, see http://crrev/c/1405714.
# Otherwise, API level 24 would have been enough.
angle_enable_vulkan =
angle_has_build &&
((is_win && !angle_is_winuwp) ||
(is_linux && angle_use_x11 && !is_chromeos) ||
(is_android && ndk_api_level_at_least_26) || is_fuchsia || is_ggp)
angle_has_build && ((is_win && !angle_is_winuwp) ||
(is_linux && angle_use_x11 && !is_chromeos) ||
(is_android && ndk_api_level_at_least_26) ||
is_fuchsia || is_ggp || is_mac)
angle_enable_null = true
angle_enable_essl = true
angle_enable_glsl = true
......@@ -106,14 +106,21 @@ declare_args() {
}
declare_args() {
# Currently SwiftShader's Vulkan front-end doesn't build on Android.
# SwiftShader is not needed on Fuchsia because Vulkan is supported on all
# devices that run Fuchsia.
angle_enable_swiftshader =
angle_enable_vulkan && !is_android && !is_fuchsia && !is_ggp
angle_enable_gl_null = angle_enable_gl
angle_enable_hlsl = angle_enable_d3d9 || angle_enable_d3d11
angle_enable_trace = false
# Disable the layers in ubsan builds because of really slow builds.
# TODO(anglebug.com/4082) enable validation layers on mac for swiftshader
angle_enable_vulkan_validation_layers =
angle_enable_vulkan && !is_ubsan && !is_tsan && !is_asan &&
(is_debug || dcheck_always_on)
(is_debug || dcheck_always_on) && !is_mac
# Disable overlay by default
angle_enable_overlay = false
......
......@@ -193,6 +193,7 @@ IGNORED_INCLUDES = {
b'libANGLE/renderer/vulkan/android/DisplayVkAndroid.h',
b'libANGLE/renderer/vulkan/fuchsia/DisplayVkFuchsia.h',
b'libANGLE/renderer/vulkan/ggp/DisplayVkGGP.h',
b'libANGLE/renderer/vulkan/mac/DisplayVkMac.h',
b'libANGLE/renderer/vulkan/win32/DisplayVkWin32.h',
b'libANGLE/renderer/vulkan/xcb/DisplayVkXcb.h',
b'kernel/image.h',
......
......@@ -289,6 +289,11 @@ rx::DisplayImpl *CreateDisplayFromAttribs(const AttributeMap &attribMap, const D
{
impl = rx::CreateVulkanGGPDisplay(state);
}
# elif defined(ANGLE_PLATFORM_APPLE)
if (rx::IsVulkanMacDisplayAvailable())
{
impl = rx::CreateVulkanMacDisplay(state);
}
# else
# error Unsupported Vulkan platform.
# endif
......@@ -1279,7 +1284,10 @@ static ClientExtensions GenerateClientExtensions()
#endif
#if defined(ANGLE_ENABLE_VULKAN)
extensions.platformANGLEVulkan = true;
extensions.platformANGLEVulkan = true;
#endif
#if defined(ANGLE_ENABLE_SWIFTSHADER)
extensions.platformANGLEDeviceTypeSwiftShader = true;
#endif
......
......@@ -15,11 +15,6 @@ declare_args() {
# Enable Vulkan GPU trace event capability
angle_enable_vulkan_gpu_trace_events = false
# Currently SwiftShader's Vulkan front-end doesn't build on Android.
# SwiftShader is not needed on Fuchsia because Vulkan is supported on all
# devices that run Fuchsia.
angle_swiftshader = !is_android && !is_fuchsia && !is_ggp
}
_vulkan_backend_sources = [
......@@ -147,6 +142,15 @@ if (is_ggp) {
]
}
if (is_mac) {
_vulkan_backend_sources += [
"mac/DisplayVkMac.mm",
"mac/DisplayVkMac.h",
"mac/WindowSurfaceVkMac.mm",
"mac/WindowSurfaceVkMac.h",
]
}
config("vulkan_config") {
_sws_icd = "./libvk_swiftshader_icd.json"
if (is_win) {
......@@ -166,7 +170,7 @@ config("vulkan_config") {
}
}
if (angle_swiftshader) {
if (angle_enable_swiftshader) {
copy("angle_swiftshader_icd_rename") {
sources = [
"$swiftshader_dir/src/Vulkan/vk_swiftshader_icd.json",
......@@ -241,6 +245,9 @@ group("angle_vulkan_entry_points") {
config("angle_vulkan_backend_config") {
defines = [ "ANGLE_ENABLE_VULKAN" ]
if (angle_enable_swiftshader) {
defines += [ "ANGLE_ENABLE_SWIFTSHADER" ]
}
if (angle_enable_custom_vulkan_cmd_buffers) {
defines += [ "ANGLE_USE_CUSTOM_VULKAN_CMD_BUFFERS=1" ]
}
......@@ -288,7 +295,7 @@ angle_source_set("angle_vulkan_backend") {
}
}
if (angle_swiftshader) {
if (angle_enable_swiftshader) {
data_deps += [
":angle_swiftshader_icd",
"$swiftshader_dir/src/Vulkan:swiftshader_libvulkan",
......
......@@ -38,6 +38,11 @@ DisplayImpl *CreateVulkanFuchsiaDisplay(const egl::DisplayState &state);
bool IsVulkanGGPDisplayAvailable();
DisplayImpl *CreateVulkanGGPDisplay(const egl::DisplayState &state);
#endif // defined(ANGLE_PLATFORM_GGP)
#if defined(ANGLE_PLATFORM_APPLE)
bool IsVulkanMacDisplayAvailable();
DisplayImpl *CreateVulkanMacDisplay(const egl::DisplayState &state);
#endif // defined(ANGLE_PLATFORM_APPLE)
} // namespace rx
#endif /* LIBANGLE_RENDERER_VULKAN_DISPLAYVK_API_H_ */
......@@ -3,7 +3,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// DisplayVkFuchsia.h:
// DisplayVkFuchsia.cpp:
// Implements methods from DisplayVkFuchsia
//
......
//
// Copyright 2019 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.
//
// DisplayVkMac.h:
// Subclasses DisplayVk for the Mac platform.
//
#ifndef LIBANGLE_RENDERER_VULKAN_MAC_DISPLAYVKMAC_H_
#define LIBANGLE_RENDERER_VULKAN_MAC_DISPLAYVKMAC_H_
#include "libANGLE/renderer/vulkan/DisplayVk.h"
namespace rx
{
class DisplayVkMac : public DisplayVk
{
public:
DisplayVkMac(const egl::DisplayState &state);
bool isValidNativeWindow(EGLNativeWindowType window) const override;
SurfaceImpl *createWindowSurfaceVk(const egl::SurfaceState &state,
EGLNativeWindowType window) override;
egl::ConfigSet generateConfigs() override;
bool checkConfigSupport(egl::Config *config) override;
const char *getWSIExtension() const override;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_MAC_DISPLAYVKMAC_H_
//
// Copyright 2019 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.
//
// DisplayVkMac.mm:
// Implements methods from DisplayVkMac
//
#include "libANGLE/renderer/vulkan/mac/DisplayVkMac.h"
#include <vulkan/vulkan.h>
#include "libANGLE/renderer/vulkan/mac/WindowSurfaceVkMac.h"
#include "libANGLE/renderer/vulkan/vk_caps_utils.h"
#import <Cocoa/Cocoa.h>
namespace rx
{
DisplayVkMac::DisplayVkMac(const egl::DisplayState &state) : DisplayVk(state) {}
bool DisplayVkMac::isValidNativeWindow(EGLNativeWindowType window) const
{
NSObject *layer = reinterpret_cast<NSObject *>(window);
return [layer isKindOfClass:[CALayer class]];
}
SurfaceImpl *DisplayVkMac::createWindowSurfaceVk(const egl::SurfaceState &state,
EGLNativeWindowType window)
{
ASSERT(isValidNativeWindow(window));
return new WindowSurfaceVkMac(state, window);
}
egl::ConfigSet DisplayVkMac::generateConfigs()
{
constexpr GLenum kColorFormats[] = {GL_BGRA8_EXT, GL_BGRX8_ANGLEX};
return egl_vk::GenerateConfigs(kColorFormats, egl_vk::kConfigDepthStencilFormats, this);
}
bool DisplayVkMac::checkConfigSupport(egl::Config *config)
{
// TODO(geofflang): Test for native support and modify the config accordingly.
// anglebug.com/2692
return true;
}
const char *DisplayVkMac::getWSIExtension() const
{
return VK_EXT_METAL_SURFACE_EXTENSION_NAME;
}
bool IsVulkanMacDisplayAvailable()
{
return true;
}
DisplayImpl *CreateVulkanMacDisplay(const egl::DisplayState &state)
{
return new DisplayVkMac(state);
}
} // namespace rx
//
// Copyright 2019 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.
//
// WindowSurfaceVkMac.h:
// Subclasses WindowSurfaceVk for the Mac platform.
//
#ifndef LIBANGLE_RENDERER_VULKAN_MAC_WINDOWSURFACEVKMAC_H_
#define LIBANGLE_RENDERER_VULKAN_MAC_WINDOWSURFACEVKMAC_H_
#include "libANGLE/renderer/vulkan/SurfaceVk.h"
#include <Cocoa/Cocoa.h>
namespace rx
{
class WindowSurfaceVkMac : public WindowSurfaceVk
{
public:
WindowSurfaceVkMac(const egl::SurfaceState &surfaceState, EGLNativeWindowType window);
~WindowSurfaceVkMac() override;
private:
angle::Result createSurfaceVk(vk::Context *context, gl::Extents *extentsOut) override;
angle::Result getCurrentWindowSize(vk::Context *context, gl::Extents *extentsOut) override;
CAMetalLayer *mMetalLayer;
id<MTLDevice> mMetalDevice;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_MAC_WINDOWSURFACEVKMAC_H_
//
// Copyright 2019 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.
//
// WindowSurfaceVkMac.mm:
// Implements methods from WindowSurfaceVkMac.
//
#include "libANGLE/renderer/vulkan/mac/WindowSurfaceVkMac.h"
#include <Metal/Metal.h>
#include <QuartzCore/CAMetalLayer.h>
#include "libANGLE/renderer/vulkan/RendererVk.h"
#include "libANGLE/renderer/vulkan/vk_utils.h"
namespace rx
{
WindowSurfaceVkMac::WindowSurfaceVkMac(const egl::SurfaceState &surfaceState,
EGLNativeWindowType window)
: WindowSurfaceVk(surfaceState, window), mMetalLayer(nullptr)
{}
WindowSurfaceVkMac::~WindowSurfaceVkMac()
{
[mMetalDevice release];
[mMetalLayer release];
}
angle::Result WindowSurfaceVkMac::createSurfaceVk(vk::Context *context, gl::Extents *extentsOut)
API_AVAILABLE(macosx(10.11))
{
mMetalDevice = MTLCreateSystemDefaultDevice();
CALayer *layer = reinterpret_cast<CALayer *>(mNativeWindowType);
mMetalLayer = [[CAMetalLayer alloc] init];
mMetalLayer.frame = layer.frame;
mMetalLayer.device = mMetalDevice;
mMetalLayer.drawableSize =
CGSizeMake(mMetalLayer.bounds.size.width * mMetalLayer.contentsScale,
mMetalLayer.bounds.size.height * mMetalLayer.contentsScale);
mMetalLayer.framebufferOnly = NO;
mMetalLayer.autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;
mMetalLayer.contentsScale = layer.contentsScale;
[layer addSublayer:mMetalLayer];
VkMetalSurfaceCreateInfoEXT createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT;
createInfo.flags = 0;
createInfo.pNext = nullptr;
createInfo.pLayer = mMetalLayer;
ANGLE_VK_TRY(context, vkCreateMetalSurfaceEXT(context->getRenderer()->getInstance(),
&createInfo, nullptr, &mSurface));
return getCurrentWindowSize(context, extentsOut);
}
angle::Result WindowSurfaceVkMac::getCurrentWindowSize(vk::Context *context,
gl::Extents *extentsOut)
API_AVAILABLE(macosx(10.11))
{
ANGLE_VK_CHECK(context, (mMetalLayer != nullptr), VK_ERROR_INITIALIZATION_FAILED);
mMetalLayer.drawableSize =
CGSizeMake(mMetalLayer.bounds.size.width * mMetalLayer.contentsScale,
mMetalLayer.bounds.size.height * mMetalLayer.contentsScale);
*extentsOut = gl::Extents(static_cast<int>(mMetalLayer.drawableSize.width),
static_cast<int>(mMetalLayer.drawableSize.height), 1);
return angle::Result::Continue;
}
} // namespace rx
......@@ -227,7 +227,9 @@ if (is_win || is_linux || is_android || is_mac) {
sources += angle_white_box_perf_tests_win_sources
}
if (angle_enable_vulkan) {
# These tests depend on vulkan_command_buffer_utils, which is
# not yet compatible with mac
if (angle_enable_vulkan && !is_mac) {
sources += angle_white_box_perf_tests_vulkan_sources
deps += [
"$angle_glslang_dir:glslang_sources",
......
......@@ -97,7 +97,7 @@ ANGLEPlatform::ANGLEPlatform(angle::LogErrorFunc logErrorFunc)
}
#endif
#if (DE_OS == DE_OS_WIN32) || (DE_OS == DE_OS_UNIX)
#if (DE_OS == DE_OS_WIN32) || (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_OSX)
{
std::vector<eglw::EGLAttrib> swsAttribs = initAttribs(
EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE);
......
......@@ -313,23 +313,29 @@ bool IsConfigWhitelisted(const SystemInfo &systemInfo, const PlatformParameters
return false;
}
// OSX does not support ES 3.1 features.
if (param.majorVersion == 3 && param.minorVersion > 0)
{
return false;
}
if (param.getRenderer() == EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE &&
(!IsMetalRendererAvailable() || IsIntel(vendorID)))
switch (param.getRenderer())
{
// TODO(hqle): Intel metal tests seem to have problems. Disable for now.
// http://anglebug.com/4133
return false;
case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
// ES 3.1+ back-end is not supported properly.
if (param.majorVersion == 3 && param.minorVersion > 0)
{
return false;
}
return true;
case EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE:
if (!IsMetalRendererAvailable() || IsIntel(vendorID))
{
// TODO(hqle): Intel metal tests seem to have problems. Disable for now.
// http://anglebug.com/4133
return false;
}
return true;
case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
// OSX does not support native vulkan
return param.getDeviceType() == EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE;
default:
return false;
}
// Currently we only support the OpenGL & Metal back-end on OSX.
return (param.getRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE ||
param.getRenderer() == EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE);
}
#endif // #if defined(ANGLE_PLATFORM_APPLE)
......@@ -401,6 +407,11 @@ bool IsConfigWhitelisted(const SystemInfo &systemInfo, const PlatformParameters
{
case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
// Swiftshader's vulkan frontend doesn't build on Android.
if (param.getDeviceType() == EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE)
{
return false;
}
return true;
default:
return false;
......
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