Reland: [Vulkan] Add DisplayVkNull Currently all DisplayVk implementations depend on VK_KHR_swapchain and VK_KHR_surface extensions. When running Chromium on Fuchsia these extensions are never used (content is shown on the screen using ImagePipe API without dependency on swapchain). ANGLE still depended on these extensions for DisplayVkFuchsia. This CL adds DisplayVkNull, which allows to run ANGLE without dependency on swapchain. It's usable only offscreen and cannot present content on a surface. Bug: chromium:1203879 Change-Id: I5cadcdf46ed1cfb5ebb3cb69dbfef063e9e2b826 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3012368 Reviewed-by: Jamie Madill <jmadill@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
diff --git a/BUILD.gn b/BUILD.gn index facbacd..7c28746 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -138,7 +138,9 @@ defines += [ "__ggp__" ] } - if (angle_use_vulkan_display) { + if (angle_use_vulkan_null_display) { + defines += [ "ANGLE_USE_VULKAN_NULL_DISPLAY" ] + } else if (angle_use_vulkan_display) { defines += [ "ANGLE_USE_VULKAN_DISPLAY", "EGL_NO_X11",
diff --git a/gni/angle.gni b/gni/angle.gni index 2a62aa5..92c409a 100644 --- a/gni/angle.gni +++ b/gni/angle.gni
@@ -130,6 +130,10 @@ (is_linux && (angle_use_x11 || angle_use_vulkan_display) && !is_chromeos) || is_android || is_fuchsia || is_ggp || is_mac) + # When set to true, ANGLE will not use VK_KHR_surface and VK_KHR_swapchain + # extensions. Content can be rendered only off-screen. + angle_use_vulkan_null_display = build_with_chromium && is_fuchsia + # Disable null backend to save space for official build. angle_enable_null = !is_official_build angle_enable_gl_desktop = !is_android && !is_ios
diff --git a/src/common/vulkan/BUILD.gn b/src/common/vulkan/BUILD.gn index 0e993e1..4d119d2 100644 --- a/src/common/vulkan/BUILD.gn +++ b/src/common/vulkan/BUILD.gn
@@ -54,9 +54,11 @@ if (is_fuchsia) { public_deps += [ "$angle_root/src/common/fuchsia_egl", - "//third_party/fuchsia-sdk:vulkan_base", "//third_party/fuchsia-sdk/sdk/pkg/vulkan", ] + if (!angle_use_vulkan_null_display) { + public_deps += [ "//third_party/fuchsia-sdk/sdk/pkg/vulkan_layers:VkLayer_image_pipe_swapchain" ] + } } else if (!is_android && !is_ggp) { if (angle_shared_libvulkan) { data_deps = [ "$angle_vulkan_loader_dir:libvulkan" ]
diff --git a/src/libANGLE/Display.cpp b/src/libANGLE/Display.cpp index 318cc90..f38885b 100644 --- a/src/libANGLE/Display.cpp +++ b/src/libANGLE/Display.cpp
@@ -365,7 +365,13 @@ case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE: #if defined(ANGLE_ENABLE_VULKAN) -# if defined(ANGLE_PLATFORM_WINDOWS) +# if defined(ANGLE_USE_VULKAN_NULL_DISPLAY) + if (rx::IsVulkanNullDisplayAvailable()) + { + impl = rx::CreateVulkanNullDisplay(state); + } + break; +# elif defined(ANGLE_PLATFORM_WINDOWS) if (rx::IsVulkanWin32DisplayAvailable()) { impl = rx::CreateVulkanWin32Display(state);
diff --git a/src/libANGLE/renderer/vulkan/BUILD.gn b/src/libANGLE/renderer/vulkan/BUILD.gn index f2fae77..d60dd37 100644 --- a/src/libANGLE/renderer/vulkan/BUILD.gn +++ b/src/libANGLE/renderer/vulkan/BUILD.gn
@@ -127,6 +127,15 @@ ] } +if (angle_use_vulkan_null_display) { + _vulkan_backend_sources += [ + "null/DisplayVkNull.cpp", + "null/DisplayVkNull.h", + "null/WindowSurfaceVkNull.cpp", + "null/WindowSurfaceVkNull.h", + ] +} + if (is_linux) { _vulkan_backend_sources += [ "display/DisplayVkSimple.cpp",
diff --git a/src/libANGLE/renderer/vulkan/DisplayVk.cpp b/src/libANGLE/renderer/vulkan/DisplayVk.cpp index 3c64c18..f4e6ecb 100644 --- a/src/libANGLE/renderer/vulkan/DisplayVk.cpp +++ b/src/libANGLE/renderer/vulkan/DisplayVk.cpp
@@ -258,6 +258,11 @@ return nullptr; } +bool DisplayVk::isUsingSwapchain() const +{ + return true; +} + bool DisplayVk::getScratchBuffer(size_t requstedSizeBytes, angle::MemoryBuffer **scratchBufferOut) const {
diff --git a/src/libANGLE/renderer/vulkan/DisplayVk.h b/src/libANGLE/renderer/vulkan/DisplayVk.h index c9da3f1..fec7fd7 100644 --- a/src/libANGLE/renderer/vulkan/DisplayVk.h +++ b/src/libANGLE/renderer/vulkan/DisplayVk.h
@@ -123,6 +123,7 @@ virtual const char *getWSIExtension() const = 0; virtual const char *getWSILayer() const; + virtual bool isUsingSwapchain() const; // Determine if a config with given formats and sample counts is supported. This callback may // modify the config to add or remove platform specific attributes such as nativeVisualID. If
diff --git a/src/libANGLE/renderer/vulkan/DisplayVk_api.h b/src/libANGLE/renderer/vulkan/DisplayVk_api.h index 1637942..39fd2cb 100644 --- a/src/libANGLE/renderer/vulkan/DisplayVk_api.h +++ b/src/libANGLE/renderer/vulkan/DisplayVk_api.h
@@ -14,6 +14,10 @@ namespace rx { + +bool IsVulkanNullDisplayAvailable(); +DisplayImpl *CreateVulkanNullDisplay(const egl::DisplayState &state); + #if defined(ANGLE_PLATFORM_WINDOWS) bool IsVulkanWin32DisplayAvailable(); DisplayImpl *CreateVulkanWin32Display(const egl::DisplayState &state);
diff --git a/src/libANGLE/renderer/vulkan/RendererVk.cpp b/src/libANGLE/renderer/vulkan/RendererVk.cpp index 8731af5..daae5f6 100644 --- a/src/libANGLE/renderer/vulkan/RendererVk.cpp +++ b/src/libANGLE/renderer/vulkan/RendererVk.cpp
@@ -937,8 +937,15 @@ } vk::ExtensionNameList enabledInstanceExtensions; - enabledInstanceExtensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME); - enabledInstanceExtensions.push_back(wsiExtension); + if (displayVk->isUsingSwapchain()) + { + enabledInstanceExtensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME); + } + if (wsiExtension) + { + enabledInstanceExtensions.push_back(wsiExtension); + } + mEnableDebugUtils = canLoadDebugUtils && mEnableValidationLayers && ExtensionFound(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, instanceExtensionNames); @@ -1462,7 +1469,10 @@ } vk::ExtensionNameList enabledDeviceExtensions; - enabledDeviceExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME); + if (displayVk->isUsingSwapchain()) + { + enabledDeviceExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME); + } // Queues: map low, med, high priority to whatever is supported up to 3 queues uint32_t queueCount = std::min(mQueueFamilyProperties[queueFamilyIndex].queueCount,
diff --git a/src/libANGLE/renderer/vulkan/null/DisplayVkNull.cpp b/src/libANGLE/renderer/vulkan/null/DisplayVkNull.cpp new file mode 100644 index 0000000..4753f4b --- /dev/null +++ b/src/libANGLE/renderer/vulkan/null/DisplayVkNull.cpp
@@ -0,0 +1,65 @@ +// +// Copyright 2021 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. +// +// DisplayVkNull.cpp: +// Implements the class methods for DisplayVkNull. +// + +#include "DisplayVkNull.h" +#include "WindowSurfaceVkNull.h" + +#include "libANGLE/Display.h" +#include "libANGLE/renderer/vulkan/RendererVk.h" +#include "libANGLE/renderer/vulkan/vk_caps_utils.h" + +namespace rx +{ + +DisplayVkNull::DisplayVkNull(const egl::DisplayState &state) : DisplayVk(state) {} + +bool DisplayVkNull::isValidNativeWindow(EGLNativeWindowType window) const +{ + return false; +} + +SurfaceImpl *DisplayVkNull::createWindowSurfaceVk(const egl::SurfaceState &state, + EGLNativeWindowType window) +{ + return new WindowSurfaceVkNull(state, window); +} + +const char *DisplayVkNull::getWSIExtension() const +{ + return nullptr; +} + +bool DisplayVkNull::isUsingSwapchain() const +{ + return false; +} + +egl::ConfigSet DisplayVkNull::generateConfigs() +{ + constexpr GLenum kColorFormats[] = {GL_RGBA8, GL_BGRA8_EXT, GL_RGB565, GL_RGB8}; + + return egl_vk::GenerateConfigs(kColorFormats, egl_vk::kConfigDepthStencilFormats, this); +} + +void DisplayVkNull::checkConfigSupport(egl::Config *config) +{ + config->surfaceType &= ~EGL_WINDOW_BIT; +} + +bool IsVulkanNullDisplayAvailable() +{ + return true; +} + +DisplayImpl *CreateVulkanNullDisplay(const egl::DisplayState &state) +{ + return new DisplayVkNull(state); +} + +} // namespace rx
diff --git a/src/libANGLE/renderer/vulkan/null/DisplayVkNull.h b/src/libANGLE/renderer/vulkan/null/DisplayVkNull.h new file mode 100644 index 0000000..657a75d --- /dev/null +++ b/src/libANGLE/renderer/vulkan/null/DisplayVkNull.h
@@ -0,0 +1,41 @@ +// +// Copyright 2021 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. +// +// DisplayVkNull.h: +// Defines the class interface for DisplayVkNull, implementing +// DisplayVk that doesn't depend on Vulkan extensions. It cannot be +// used to output any content to a surface. +// + +#ifndef LIBANGLE_RENDERER_VULKAN_NULL_DISPLAYVKNULL_H_ +#define LIBANGLE_RENDERER_VULKAN_NULL_DISPLAYVKNULL_H_ + +#include "libANGLE/renderer/vulkan/DisplayVk.h" + +namespace rx +{ + +class DisplayVkNull : public DisplayVk +{ + public: + DisplayVkNull(const egl::DisplayState &state); + + bool isValidNativeWindow(EGLNativeWindowType window) const override; + + SurfaceImpl *createWindowSurfaceVk(const egl::SurfaceState &state, + EGLNativeWindowType window) override; + + virtual const char *getWSIExtension() const override; + bool isUsingSwapchain() const override; + egl::ConfigSet generateConfigs() override; + void checkConfigSupport(egl::Config *config) override; + + private: + std::vector<VkSurfaceFormatKHR> mSurfaceFormats; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_VULKAN_NULL_DISPLAYVKNULL_H_
diff --git a/src/libANGLE/renderer/vulkan/null/WindowSurfaceVkNull.cpp b/src/libANGLE/renderer/vulkan/null/WindowSurfaceVkNull.cpp new file mode 100644 index 0000000..cfd3dfb --- /dev/null +++ b/src/libANGLE/renderer/vulkan/null/WindowSurfaceVkNull.cpp
@@ -0,0 +1,34 @@ +// +// Copyright 2021 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. +// +// WindowSurfaceVkNull.cpp: +// Implements the class methods for WindowSurfaceVkNull. +// + +#include "WindowSurfaceVkNull.h" +#include "libANGLE/renderer/vulkan/RendererVk.h" + +namespace rx +{ + +WindowSurfaceVkNull::WindowSurfaceVkNull(const egl::SurfaceState &surfaceState, + EGLNativeWindowType window) + : WindowSurfaceVk(surfaceState, window) +{} + +WindowSurfaceVkNull::~WindowSurfaceVkNull() {} + +angle::Result WindowSurfaceVkNull::createSurfaceVk(vk::Context *context, gl::Extents *extentsOut) +{ + return angle::Result::Stop; +} + +angle::Result WindowSurfaceVkNull::getCurrentWindowSize(vk::Context *context, + gl::Extents *extentsOut) +{ + return angle::Result::Stop; +} + +} // namespace rx
diff --git a/src/libANGLE/renderer/vulkan/null/WindowSurfaceVkNull.h b/src/libANGLE/renderer/vulkan/null/WindowSurfaceVkNull.h new file mode 100644 index 0000000..30a4557 --- /dev/null +++ b/src/libANGLE/renderer/vulkan/null/WindowSurfaceVkNull.h
@@ -0,0 +1,31 @@ +// +// Copyright 2021 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. +// +// WindowSurfaceVkNull.h: +// Defines the class interface for WindowSurfaceVkNull, implementing WindowSurfaceVk. +// + +#ifndef LIBANGLE_RENDERER_VULKAN_NULL_WINDOWSURFACEVKNULL_H_ +#define LIBANGLE_RENDERER_VULKAN_NULL_WINDOWSURFACEVKNULL_H_ + +#include "libANGLE/renderer/vulkan/SurfaceVk.h" + +namespace rx +{ + +class WindowSurfaceVkNull final : public WindowSurfaceVk +{ + public: + WindowSurfaceVkNull(const egl::SurfaceState &surfaceState, EGLNativeWindowType window); + ~WindowSurfaceVkNull() final; + + private: + angle::Result createSurfaceVk(vk::Context *context, gl::Extents *extentsOut) override; + angle::Result getCurrentWindowSize(vk::Context *context, gl::Extents *extentsOut) override; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_VULKAN_NULL_WINDOWSURFACEVKNULL_H_