Fix several vulkan backend problem on Android.

* Load AHardwarebuffer API dynamically, so vulkan backend can be
  built with old NDK, but can work with newer android releases.
* Do not link with libvulkan on android.
* Expose EGL_ANDROID_get_native_client_buffer extension with vulkan
  backend.

Bug: chromium:1170339
Change-Id: Idf7f6867a86ae40ba6d57a86e419c610ba404ba8
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2653506
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Commit-Queue: Peng Huang <penghuang@chromium.org>
This commit is contained in:
Peng Huang
2021-01-26 20:06:24 -05:00
committed by Commit Bot
parent 4ec7021ce5
commit 122a1cc583
12 changed files with 132 additions and 32 deletions

View File

@@ -204,6 +204,7 @@ IGNORED_INCLUDES = {
b'libANGLE/renderer/gl/wgl/DisplayWGL.h',
b'libANGLE/renderer/metal/DisplayMtl_api.h',
b'libANGLE/renderer/null/DisplayNULL.h',
b'libANGLE/renderer/vulkan/android/AHBFunctions.h',
b'libANGLE/renderer/vulkan/android/DisplayVkAndroid.h',
b'libANGLE/renderer/vulkan/fuchsia/DisplayVkFuchsia.h',
b'libANGLE/renderer/vulkan/ggp/DisplayVkGGP.h',

View File

@@ -7,12 +7,6 @@ import("../../../gni/angle.gni")
assert(angle_enable_vulkan)
config("angle_vulkan_lib_android") {
if (is_android) {
libs = [ "vulkan" ]
}
}
config("angle_vulkan_headers_config") {
if (angle_shared_libvulkan) {
defines = [ "ANGLE_SHARED_LIBVULKAN=1" ]
@@ -34,7 +28,6 @@ angle_source_set("angle_vulkan_headers") {
}
group("angle_vulkan_entry_points") {
public_configs = [ ":angle_vulkan_lib_android" ]
public_deps = [ ":angle_vulkan_headers" ]
if (is_fuchsia) {
public_deps += [

View File

@@ -118,6 +118,8 @@ if (is_linux) {
if (is_android) {
_vulkan_backend_sources += [
"android/AHBFunctions.cpp",
"android/AHBFunctions.h",
"android/DisplayVkAndroid.cpp",
"android/DisplayVkAndroid.h",
"android/HardwareBufferImageSiblingVkAndroid.cpp",
@@ -244,10 +246,6 @@ angle_source_set("angle_vulkan_backend") {
data_deps += [ "$angle_root/src/common/vulkan:vulkan_validation_layers" ]
}
if (is_android) {
libs += [ "vulkan" ]
}
if (is_fuchsia) {
public_deps += [ "$angle_root/src/common/fuchsia_egl:backend" ]
}

View File

@@ -212,7 +212,8 @@ void DisplayVk::generateExtensions(egl::DisplayExtensions *outExtensions) const
outExtensions->glColorspace && getRenderer()->getFeatures().supportsImageFormatList.enabled;
#if defined(ANGLE_PLATFORM_ANDROID)
outExtensions->framebufferTargetANDROID = true;
outExtensions->getNativeClientBufferANDROID = true;
outExtensions->framebufferTargetANDROID = true;
#endif // defined(ANGLE_PLATFORM_ANDROID)
// Disable context priority when non-zero memory init is enabled. This enforces a queue order.

View File

@@ -292,6 +292,8 @@ class RendererVk : angle::NonCopyable
}
}
egl::Display *getDisplay() const { return mDisplay; }
VkResult getLastPresentResult(VkSwapchainKHR swapchain)
{
return mCommandProcessor.getLastPresentResult(swapchain);

View File

@@ -0,0 +1,35 @@
//
// 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.
//
#include "libANGLE/renderer/vulkan/android/AHBFunctions.h"
#include <dlfcn.h>
namespace rx
{
namespace
{
template <class T>
void AssignFn(void *handle, const char *name, T &fn)
{
fn = reinterpret_cast<T>(dlsym(handle, name));
}
} // namespace
AHBFunctions::AHBFunctions()
{
void *handle = dlopen(nullptr, RTLD_NOW);
AssignFn(handle, "AHardwareBuffer_acquire", mAcquireFn);
AssignFn(handle, "AHardwareBuffer_describe", mDescribeFn);
AssignFn(handle, "AHardwareBuffer_release", mReleaseFn);
}
AHBFunctions::~AHBFunctions() = default;
} // namespace rx

View File

@@ -0,0 +1,43 @@
//
// 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.
//
#ifndef LIBANGLE_RENDERER_VULKAN_ANDROID_AHBFUNCTIONS_H_
#define LIBANGLE_RENDERER_VULKAN_ANDROID_AHBFUNCTIONS_H_
#include <android/hardware_buffer.h>
namespace rx
{
class AHBFunctions
{
public:
AHBFunctions();
~AHBFunctions();
void acquire(AHardwareBuffer *buffer) const { mAcquireFn(buffer); }
void describe(const AHardwareBuffer *buffer, AHardwareBuffer_Desc *outDesc) const
{
mDescribeFn(buffer, outDesc);
}
void release(AHardwareBuffer *buffer) const { mReleaseFn(buffer); }
bool valid() const { return mAcquireFn && mDescribeFn && mReleaseFn; }
private:
using PFN_AHARDWAREBUFFER_acquire = void (*)(AHardwareBuffer *buffer);
using PFN_AHARDWAREBUFFER_describe = void (*)(const AHardwareBuffer *buffer,
AHardwareBuffer_Desc *outDesc);
using PFN_AHARDWAREBUFFER_release = void (*)(AHardwareBuffer *buffer);
PFN_AHARDWAREBUFFER_acquire mAcquireFn = nullptr;
PFN_AHARDWAREBUFFER_describe mDescribeFn = nullptr;
PFN_AHARDWAREBUFFER_release mReleaseFn = nullptr;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_ANDROID_AHBFUNCTIONS_H_

View File

@@ -11,6 +11,7 @@
#define LIBANGLE_RENDERER_VULKAN_ANDROID_DISPLAYVKANDROID_H_
#include "libANGLE/renderer/vulkan/DisplayVk.h"
#include "libANGLE/renderer/vulkan/android/AHBFunctions.h"
namespace rx
{
@@ -40,6 +41,11 @@ class DisplayVkAndroid : public DisplayVk
const egl::AttributeMap &attribs) override;
const char *getWSIExtension() const override;
const AHBFunctions &getAHBFunctions() const { return mAHBFunctions; }
private:
AHBFunctions mAHBFunctions;
};
} // namespace rx

View File

@@ -13,14 +13,15 @@
#include "libANGLE/Display.h"
#include "libANGLE/renderer/vulkan/DisplayVk.h"
#include "libANGLE/renderer/vulkan/RendererVk.h"
#include <android/hardware_buffer.h>
#include "libANGLE/renderer/vulkan/android/AHBFunctions.h"
#include "libANGLE/renderer/vulkan/android/DisplayVkAndroid.h"
namespace rx
{
namespace
{
VkImageTiling AhbDescUsageToVkImageTiling(const AHardwareBuffer_Desc &ahbDescription)
{
if ((ahbDescription.usage & AHARDWAREBUFFER_USAGE_CPU_READ_MASK) != 0 ||
@@ -140,6 +141,9 @@ VkImageUsageFlags AhbDescUsageToVkImageUsage(const AHardwareBuffer_Desc &ahbDesc
angle::Result HardwareBufferImageSiblingVkAndroid::initImpl(DisplayVk *displayVk)
{
const AHBFunctions &functions = static_cast<DisplayVkAndroid *>(displayVk)->getAHBFunctions();
ANGLE_VK_CHECK(displayVk, functions.valid(), VK_ERROR_INITIALIZATION_FAILED);
RendererVk *renderer = displayVk->getRenderer();
struct ANativeWindowBuffer *windowBuffer =
@@ -154,7 +158,7 @@ angle::Result HardwareBufferImageSiblingVkAndroid::initImpl(DisplayVk *displayVk
struct AHardwareBuffer *hardwareBuffer =
angle::android::ANativeWindowBufferToAHardwareBuffer(windowBuffer);
AHardwareBuffer_acquire(hardwareBuffer);
functions.acquire(hardwareBuffer);
VkAndroidHardwareBufferFormatPropertiesANDROID bufferFormatProperties;
bufferFormatProperties.sType =
VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID;
@@ -181,7 +185,7 @@ angle::Result HardwareBufferImageSiblingVkAndroid::initImpl(DisplayVk *displayVk
// 1. Derive VkImageTiling mode based on AHB usage flags
// 2. Map AHB usage flags to VkImageUsageFlags
AHardwareBuffer_Desc ahbDescription;
AHardwareBuffer_describe(hardwareBuffer, &ahbDescription);
functions.describe(hardwareBuffer, &ahbDescription);
VkImageTiling imageTilingMode = AhbDescUsageToVkImageTiling(ahbDescription);
VkImageUsageFlags usage = AhbDescUsageToVkImageUsage(ahbDescription, isDepthOrStencilFormat);
@@ -310,7 +314,10 @@ angle::Result HardwareBufferImageSiblingVkAndroid::initImpl(DisplayVk *displayVk
void HardwareBufferImageSiblingVkAndroid::onDestroy(const egl::Display *display)
{
AHardwareBuffer_release(angle::android::ANativeWindowBufferToAHardwareBuffer(
const AHBFunctions &functions = GetImplAs<DisplayVkAndroid>(display)->getAHBFunctions();
ASSERT(functions.valid());
functions.release(angle::android::ANativeWindowBufferToAHardwareBuffer(
angle::android::ClientBufferToANativeWindowBuffer(mBuffer)));
ASSERT(mImage == nullptr);

View File

@@ -12,10 +12,10 @@
#include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/vk_utils.h"
#if defined(ANGLE_PLATFORM_ANDROID) && __ANDROID_API__ >= 26
# define ANGLE_AHARDWARE_BUFFER_SUPPORT
// NDK header file for access to Android Hardware Buffers
# include <android/hardware_buffer.h>
#if defined(ANGLE_PLATFORM_ANDROID)
# include "libANGLE/Display.h"
# include "libANGLE/renderer/vulkan/android/AHBFunctions.h"
# include "libANGLE/renderer/vulkan/android/DisplayVkAndroid.h"
#endif
namespace rx
@@ -26,7 +26,10 @@ angle::Result GetClientBufferMemoryRequirements(ContextVk *contextVk,
const AHardwareBuffer *hardwareBuffer,
VkMemoryRequirements &memRequirements)
{
#if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
#if defined(ANGLE_PLATFORM_ANDROID)
ASSERT(GetImplAs<DisplayVkAndroid>(contextVk->getRenderer()->getDisplay())
->getAHBFunctions()
.valid());
// Get Android Buffer Properties
VkAndroidHardwareBufferFormatPropertiesANDROID bufferFormatProperties = {};
@@ -49,7 +52,8 @@ angle::Result GetClientBufferMemoryRequirements(ContextVk *contextVk,
#else
ANGLE_VK_UNREACHABLE(contextVk);
return angle::Result::Stop;
#endif // ANGLE_AHARDWARE_BUFFER_SUPPORT
#endif
}
angle::Result InitAndroidExternalMemory(ContextVk *contextVk,
@@ -59,7 +63,11 @@ angle::Result InitAndroidExternalMemory(ContextVk *contextVk,
VkMemoryPropertyFlags *memoryPropertyFlagsOut,
DeviceMemory *deviceMemoryOut)
{
#if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
#if defined(ANGLE_PLATFORM_ANDROID)
const AHBFunctions &functions =
GetImplAs<DisplayVkAndroid>(contextVk->getRenderer()->getDisplay())->getAHBFunctions();
ASSERT(functions.valid());
struct AHardwareBuffer *hardwareBuffer =
angle::android::ClientBufferToAHardwareBuffer(clientBuffer);
@@ -76,22 +84,25 @@ angle::Result InitAndroidExternalMemory(ContextVk *contextVk,
contextVk, memoryProperties, externalMemoryRequirements, &importHardwareBufferInfo, buffer,
memoryPropertyFlagsOut, deviceMemoryOut));
AHardwareBuffer_acquire(hardwareBuffer);
functions.acquire(hardwareBuffer);
return angle::Result::Continue;
#else
ANGLE_VK_UNREACHABLE(contextVk);
return angle::Result::Stop;
#endif // ANGLE_AHARDWARE_BUFFER_SUPPORT
#endif
}
void ReleaseAndroidExternalMemory(EGLClientBuffer clientBuffer)
void ReleaseAndroidExternalMemory(RendererVk *rendererVk, EGLClientBuffer clientBuffer)
{
#if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
#if defined(ANGLE_PLATFORM_ANDROID)
const AHBFunctions &functions =
GetImplAs<DisplayVkAndroid>(rendererVk->getDisplay())->getAHBFunctions();
ASSERT(functions.valid());
struct AHardwareBuffer *hardwareBuffer =
angle::android::ClientBufferToAHardwareBuffer(clientBuffer);
AHardwareBuffer_release(hardwareBuffer);
#endif // ANGLE_AHARDWARE_BUFFER_SUPPORT
functions.release(hardwareBuffer);
#endif
}
} // namespace vk
} // namespace rx

View File

@@ -20,6 +20,9 @@ class DeviceMemory;
namespace rx
{
class RendererVk;
namespace vk
{
angle::Result InitAndroidExternalMemory(ContextVk *contextVk,
@@ -29,7 +32,7 @@ angle::Result InitAndroidExternalMemory(ContextVk *contextVk,
VkMemoryPropertyFlags *memoryPropertyFlagsOut,
DeviceMemory *deviceMemoryOut);
void ReleaseAndroidExternalMemory(EGLClientBuffer clientBuffer);
void ReleaseAndroidExternalMemory(RendererVk *rendererVk, EGLClientBuffer clientBuffer);
} // namespace vk
} // namespace rx

View File

@@ -3044,7 +3044,7 @@ void BufferMemory::destroy(RendererVk *renderer)
if (isExternalBuffer())
{
mExternalMemory.destroy(renderer->getDevice());
ReleaseAndroidExternalMemory(mClientBuffer);
ReleaseAndroidExternalMemory(renderer, mClientBuffer);
}
else
{