Commit 009696c5 by Geoff Lang Committed by Commit Bot

Vulkan: Support EGL_ANDROID_image_native_buffer on Android.

BUG=angleproject:2668 BUG=angleproject:3121 Change-Id: I0dfb2ec0737ebd963b0fadb78cf720a90874f00b Reviewed-on: https://chromium-review.googlesource.com/c/1452264 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org>
parent 46d32e0f
...@@ -62,6 +62,10 @@ struct FeaturesVk ...@@ -62,6 +62,10 @@ struct FeaturesVk
// Intel drivers on windows that have an issue with creating single-layer views on cube map // Intel drivers on windows that have an issue with creating single-layer views on cube map
// textures. // textures.
bool forceCpuPathForCubeMapCopy = false; bool forceCpuPathForCubeMapCopy = false;
// Whether the VkDevice supports the VK_ANDROID_external_memory_android_hardware_buffer
// extension, on which the EGL_ANDROID_image_native_buffer extension can be layered.
bool supportsAndroidHardwareBuffer = false;
}; };
} // namespace angle } // namespace angle
......
...@@ -6,13 +6,51 @@ ...@@ -6,13 +6,51 @@
// android_util.cpp: Utilities for the using the Android platform // android_util.cpp: Utilities for the using the Android platform
#include "libANGLE/renderer/gl/egl/android/android_util.h" #include "common/android_util.h"
namespace rx // Taken from cutils/native_handle.h:
// https://android.googlesource.com/platform/system/core/+/master/libcutils/include/cutils/native_handle.h
typedef struct native_handle
{ {
int version; /* sizeof(native_handle_t) */
int numFds; /* number of file-descriptors at &data[0] */
int numInts; /* number of ints at &data[numFds] */
int data[0]; /* numFds + numInts ints */
} native_handle_t;
namespace // Taken from nativebase/nativebase.h
// https://android.googlesource.com/platform/frameworks/native/+/master/libs/nativebase/include/nativebase/nativebase.h
typedef const native_handle_t *buffer_handle_t;
typedef struct android_native_base_t
{ {
/* a magic value defined by the actual EGL native type */
int magic;
/* the sizeof() of the actual EGL native type */
int version;
void *reserved[4];
/* reference-counting interface */
void (*incRef)(struct android_native_base_t *base);
void (*decRef)(struct android_native_base_t *base);
} android_native_base_t;
typedef struct ANativeWindowBuffer
{
struct android_native_base_t common;
int width;
int height;
int stride;
int format;
int usage_deprecated;
uintptr_t layerCount;
void *reserved[1];
const native_handle_t *handle;
uint64_t usage;
// we needed extra space for storing the 64-bits usage flags
// the number of slots to use from reserved_proc depends on the
// architecture.
void *reserved_proc[8 - (sizeof(uint64_t) / sizeof(void *))];
} ANativeWindowBuffer_t;
// Taken from android/hardware_buffer.h // Taken from android/hardware_buffer.h
// https://android.googlesource.com/platform/frameworks/native/+/master/libs/nativewindow/include/android/hardware_buffer.h // https://android.googlesource.com/platform/frameworks/native/+/master/libs/nativewindow/include/android/hardware_buffer.h
...@@ -31,6 +69,7 @@ enum { ...@@ -31,6 +69,7 @@ enum {
* OpenGL ES: GL_RGBA8 * OpenGL ES: GL_RGBA8
*/ */
AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM = 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM = 1,
/** /**
* 32 bits per pixel, 8 bits per channel format where alpha values are * 32 bits per pixel, 8 bits per channel format where alpha values are
* ignored (always opaque). * ignored (always opaque).
...@@ -39,68 +78,79 @@ enum { ...@@ -39,68 +78,79 @@ enum {
* OpenGL ES: GL_RGB8 * OpenGL ES: GL_RGB8
*/ */
AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM = 2, AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM = 2,
/** /**
* Corresponding formats: * Corresponding formats:
* Vulkan: VK_FORMAT_R8G8B8_UNORM * Vulkan: VK_FORMAT_R8G8B8_UNORM
* OpenGL ES: GL_RGB8 * OpenGL ES: GL_RGB8
*/ */
AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM = 3, AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM = 3,
/** /**
* Corresponding formats: * Corresponding formats:
* Vulkan: VK_FORMAT_R5G6B5_UNORM_PACK16 * Vulkan: VK_FORMAT_R5G6B5_UNORM_PACK16
* OpenGL ES: GL_RGB565 * OpenGL ES: GL_RGB565
*/ */
AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM = 4, AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM = 4,
AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM = 5, AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM = 5,
AHARDWAREBUFFER_FORMAT_B4G4R4A4_UNORM = 6, AHARDWAREBUFFER_FORMAT_B5G5R5A1_UNORM = 6,
AHARDWAREBUFFER_FORMAT_B5G5R5A1_UNORM = 7, AHARDWAREBUFFER_FORMAT_B4G4R4A4_UNORM = 7,
/** /**
* Corresponding formats: * Corresponding formats:
* Vulkan: VK_FORMAT_R16G16B16A16_SFLOAT * Vulkan: VK_FORMAT_R16G16B16A16_SFLOAT
* OpenGL ES: GL_RGBA16F * OpenGL ES: GL_RGBA16F
*/ */
AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT = 0x16, AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT = 0x16,
/** /**
* Corresponding formats: * Corresponding formats:
* Vulkan: VK_FORMAT_A2B10G10R10_UNORM_PACK32 * Vulkan: VK_FORMAT_A2B10G10R10_UNORM_PACK32
* OpenGL ES: GL_RGB10_A2 * OpenGL ES: GL_RGB10_A2
*/ */
AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM = 0x2b, AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM = 0x2b,
/** /**
* An opaque binary blob format that must have height 1, with width equal to * An opaque binary blob format that must have height 1, with width equal to
* the buffer size in bytes. * the buffer size in bytes.
*/ */
AHARDWAREBUFFER_FORMAT_BLOB = 0x21, AHARDWAREBUFFER_FORMAT_BLOB = 0x21,
/** /**
* Corresponding formats: * Corresponding formats:
* Vulkan: VK_FORMAT_D16_UNORM * Vulkan: VK_FORMAT_D16_UNORM
* OpenGL ES: GL_DEPTH_COMPONENT16 * OpenGL ES: GL_DEPTH_COMPONENT16
*/ */
AHARDWAREBUFFER_FORMAT_D16_UNORM = 0x30, AHARDWAREBUFFER_FORMAT_D16_UNORM = 0x30,
/** /**
* Corresponding formats: * Corresponding formats:
* Vulkan: VK_FORMAT_X8_D24_UNORM_PACK32 * Vulkan: VK_FORMAT_X8_D24_UNORM_PACK32
* OpenGL ES: GL_DEPTH_COMPONENT24 * OpenGL ES: GL_DEPTH_COMPONENT24
*/ */
AHARDWAREBUFFER_FORMAT_D24_UNORM = 0x31, AHARDWAREBUFFER_FORMAT_D24_UNORM = 0x31,
/** /**
* Corresponding formats: * Corresponding formats:
* Vulkan: VK_FORMAT_D24_UNORM_S8_UINT * Vulkan: VK_FORMAT_D24_UNORM_S8_UINT
* OpenGL ES: GL_DEPTH24_STENCIL8 * OpenGL ES: GL_DEPTH24_STENCIL8
*/ */
AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT = 0x32, AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT = 0x32,
/** /**
* Corresponding formats: * Corresponding formats:
* Vulkan: VK_FORMAT_D32_SFLOAT * Vulkan: VK_FORMAT_D32_SFLOAT
* OpenGL ES: GL_DEPTH_COMPONENT32F * OpenGL ES: GL_DEPTH_COMPONENT32F
*/ */
AHARDWAREBUFFER_FORMAT_D32_FLOAT = 0x33, AHARDWAREBUFFER_FORMAT_D32_FLOAT = 0x33,
/** /**
* Corresponding formats: * Corresponding formats:
* Vulkan: VK_FORMAT_D32_SFLOAT_S8_UINT * Vulkan: VK_FORMAT_D32_SFLOAT_S8_UINT
* OpenGL ES: GL_DEPTH32F_STENCIL8 * OpenGL ES: GL_DEPTH32F_STENCIL8
*/ */
AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT = 0x34, AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT = 0x34,
/** /**
* Corresponding formats: * Corresponding formats:
* Vulkan: VK_FORMAT_S8_UINT * Vulkan: VK_FORMAT_S8_UINT
...@@ -110,10 +160,41 @@ enum { ...@@ -110,10 +160,41 @@ enum {
}; };
// clang-format on // clang-format on
namespace
{
template <typename T1, typename T2>
T1 *offsetPointer(T2 *ptr, int bytes)
{
return reinterpret_cast<T1 *>(reinterpret_cast<intptr_t>(ptr) + bytes);
}
} // anonymous namespace } // anonymous namespace
namespace angle
{
namespace android namespace android
{ {
struct ANativeWindowBuffer *ClientBufferToANativeWindowBuffer(EGLClientBuffer clientBuffer)
{
return reinterpret_cast<struct ANativeWindowBuffer *>(clientBuffer);
}
void GetANativeWindowBufferProperties(const struct ANativeWindowBuffer *buffer,
int *width,
int *height,
int *depth,
int *pixelFormat)
{
*width = buffer->width;
*height = buffer->height;
*depth = static_cast<int>(buffer->layerCount);
*height = buffer->height;
*pixelFormat = buffer->format;
}
GLenum NativePixelFormatToGLInternalFormat(int pixelFormat) GLenum NativePixelFormatToGLInternalFormat(int pixelFormat)
{ {
switch (pixelFormat) switch (pixelFormat)
...@@ -128,10 +209,10 @@ GLenum NativePixelFormatToGLInternalFormat(int pixelFormat) ...@@ -128,10 +209,10 @@ GLenum NativePixelFormatToGLInternalFormat(int pixelFormat)
return GL_RGB565; return GL_RGB565;
case AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM: case AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM:
return GL_BGRA8_EXT; return GL_BGRA8_EXT;
case AHARDWAREBUFFER_FORMAT_B4G4R4A4_UNORM:
return GL_RGBA4;
case AHARDWAREBUFFER_FORMAT_B5G5R5A1_UNORM: case AHARDWAREBUFFER_FORMAT_B5G5R5A1_UNORM:
return GL_RGB5_A1; return GL_RGB5_A1;
case AHARDWAREBUFFER_FORMAT_B4G4R4A4_UNORM:
return GL_RGBA4;
case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT: case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
return GL_RGBA16F; return GL_RGBA16F;
case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM: case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
...@@ -154,5 +235,25 @@ GLenum NativePixelFormatToGLInternalFormat(int pixelFormat) ...@@ -154,5 +235,25 @@ GLenum NativePixelFormatToGLInternalFormat(int pixelFormat)
return GL_NONE; return GL_NONE;
} }
} }
struct AHardwareBuffer *ANativeWindowBufferToAHardwareBuffer(
struct ANativeWindowBuffer *windowBuffer)
{
// In the Android system:
// - AHardwareBuffer is essentially a typedef of GraphicBuffer. Conversion functions simply
// reinterpret_cast.
// - GraphicBuffer inherits from two base classes, ANativeWindowBuffer and RefBase.
//
// GraphicBuffer implements a getter for ANativeWindowBuffer (getNativeBuffer) by static_casting
// itself to its base class ANativeWindowBuffer. The offset of the ANativeWindowBuffer pointer
// from the GraphicBuffer pointer is 16 bytes. This is likely due to two pointers: The vtable of
// GraphicBuffer and the one pointer member of the RefBase class.
//
// This is not future proof at all. We need to look into getting utilities added to Android to
// perform this cast for us.
int offset = -(static_cast<int>(sizeof(void *)) * 2);
return offsetPointer<struct AHardwareBuffer>(windowBuffer, offset);
}
} // namespace android } // namespace android
} // namespace rx } // namespace angle
//
// 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.
//
// android_util.h: Utilities for the using the Android platform
#ifndef COMMON_ANDROIDUTIL_H_
#define COMMON_ANDROIDUTIL_H_
#include <EGL/egl.h>
#include "angle_gl.h"
struct ANativeWindowBuffer;
struct AHardwareBuffer;
namespace angle
{
namespace android
{
struct ANativeWindowBuffer *ClientBufferToANativeWindowBuffer(EGLClientBuffer clientBuffer);
void GetANativeWindowBufferProperties(const struct ANativeWindowBuffer *buffer,
int *width,
int *height,
int *depth,
int *pixelFormat);
GLenum NativePixelFormatToGLInternalFormat(int pixelFormat);
struct AHardwareBuffer *ANativeWindowBufferToAHardwareBuffer(
struct ANativeWindowBuffer *windowBuffer);
} // namespace android
} // namespace angle
#endif // COMMON_ANDROIDUTIL_H_
...@@ -139,6 +139,16 @@ ExternalImageSibling::ExternalImageSibling(rx::EGLImplFactory *factory, ...@@ -139,6 +139,16 @@ ExternalImageSibling::ExternalImageSibling(rx::EGLImplFactory *factory,
ExternalImageSibling::~ExternalImageSibling() = default; ExternalImageSibling::~ExternalImageSibling() = default;
void ExternalImageSibling::onDestroy(const egl::Display *display)
{
mImplementation->onDestroy(display);
}
Error ExternalImageSibling::initialize(const egl::Display *display)
{
return mImplementation->initialize(display);
}
gl::Extents ExternalImageSibling::getAttachmentSize(const gl::ImageIndex &imageIndex) const gl::Extents ExternalImageSibling::getAttachmentSize(const gl::ImageIndex &imageIndex) const
{ {
return mImplementation->getSize(); return mImplementation->getSize();
...@@ -201,9 +211,9 @@ ImageState::ImageState(EGLenum target, ImageSibling *buffer, const AttributeMap ...@@ -201,9 +211,9 @@ ImageState::ImageState(EGLenum target, ImageSibling *buffer, const AttributeMap
imageIndex(GetImageIndex(target, attribs)), imageIndex(GetImageIndex(target, attribs)),
source(buffer), source(buffer),
targets(), targets(),
format(buffer->getAttachmentFormat(GL_NONE, imageIndex)), format(GL_NONE),
size(buffer->getAttachmentSize(imageIndex)), size(),
samples(buffer->getAttachmentSamples(imageIndex)), samples(),
sourceType(target) sourceType(target)
{} {}
...@@ -238,7 +248,9 @@ void Image::onDestroy(const Display *display) ...@@ -238,7 +248,9 @@ void Image::onDestroy(const Display *display)
// If the source is an external object, delete it // If the source is an external object, delete it
if (IsExternalImageTarget(mState.sourceType)) if (IsExternalImageTarget(mState.sourceType))
{ {
delete mState.source; ExternalImageSibling *externalSibling = rx::GetAs<ExternalImageSibling>(mState.source);
externalSibling->onDestroy(display);
delete externalSibling;
} }
mState.source = nullptr; mState.source = nullptr;
...@@ -363,6 +375,15 @@ rx::ImageImpl *Image::getImplementation() const ...@@ -363,6 +375,15 @@ rx::ImageImpl *Image::getImplementation() const
Error Image::initialize(const Display *display) Error Image::initialize(const Display *display)
{ {
if (IsExternalImageTarget(mState.sourceType))
{
ANGLE_TRY(rx::GetAs<ExternalImageSibling>(mState.source)->initialize(display));
}
mState.format = mState.source->getAttachmentFormat(GL_NONE, mState.imageIndex);
mState.size = mState.source->getAttachmentSize(mState.imageIndex);
mState.samples = mState.source->getAttachmentSamples(mState.imageIndex);
return mImplementation->initialize(display); return mImplementation->initialize(display);
} }
......
...@@ -80,6 +80,10 @@ class ExternalImageSibling : public ImageSibling ...@@ -80,6 +80,10 @@ class ExternalImageSibling : public ImageSibling
const AttributeMap &attribs); const AttributeMap &attribs);
~ExternalImageSibling() override; ~ExternalImageSibling() override;
void onDestroy(const egl::Display *display);
Error initialize(const Display *display);
gl::Extents getAttachmentSize(const gl::ImageIndex &imageIndex) const override; gl::Extents getAttachmentSize(const gl::ImageIndex &imageIndex) const override;
gl::Format getAttachmentFormat(GLenum binding, const gl::ImageIndex &imageIndex) const override; gl::Format getAttachmentFormat(GLenum binding, const gl::ImageIndex &imageIndex) const override;
GLsizei getAttachmentSamples(const gl::ImageIndex &imageIndex) const override; GLsizei getAttachmentSamples(const gl::ImageIndex &imageIndex) const override;
......
...@@ -33,6 +33,9 @@ class ExternalImageSiblingImpl : public FramebufferAttachmentObjectImpl ...@@ -33,6 +33,9 @@ class ExternalImageSiblingImpl : public FramebufferAttachmentObjectImpl
public: public:
~ExternalImageSiblingImpl() override {} ~ExternalImageSiblingImpl() override {}
virtual egl::Error initialize(const egl::Display *display) = 0;
virtual void onDestroy(const egl::Display *display) {}
virtual gl::Format getFormat() const = 0; virtual gl::Format getFormat() const = 0;
virtual bool isRenderable(const gl::Context *context) const = 0; virtual bool isRenderable(const gl::Context *context) const = 0;
virtual bool isTexturable(const gl::Context *context) const = 0; virtual bool isTexturable(const gl::Context *context) const = 0;
......
...@@ -8,63 +8,30 @@ ...@@ -8,63 +8,30 @@
#include "libANGLE/renderer/gl/egl/android/NativeBufferImageSiblingAndroid.h" #include "libANGLE/renderer/gl/egl/android/NativeBufferImageSiblingAndroid.h"
#include "libANGLE/renderer/gl/egl/android/android_util.h" #include "common/android_util.h"
// Taken from cutils/native_handle.h:
// https://android.googlesource.com/platform/system/core/+/master/libcutils/include/cutils/native_handle.h
typedef struct native_handle
{
int version; /* sizeof(native_handle_t) */
int numFds; /* number of file-descriptors at &data[0] */
int numInts; /* number of ints at &data[numFds] */
int data[0]; /* numFds + numInts ints */
} native_handle_t;
// Taken from nativebase/nativebase.h
// https://android.googlesource.com/platform/frameworks/native/+/master/libs/nativebase/include/nativebase/nativebase.h
typedef const native_handle_t *buffer_handle_t;
typedef struct android_native_base_t
{
/* a magic value defined by the actual EGL native type */
int magic;
/* the sizeof() of the actual EGL native type */
int version;
void *reserved[4];
/* reference-counting interface */
void (*incRef)(struct android_native_base_t *base);
void (*decRef)(struct android_native_base_t *base);
} android_native_base_t;
typedef struct ANativeWindowBuffer
{
struct android_native_base_t common;
int width;
int height;
int stride;
int format;
int usage_deprecated;
uintptr_t layerCount;
void *reserved[1];
const native_handle_t *handle;
uint64_t usage;
// we needed extra space for storing the 64-bits usage flags
// the number of slots to use from reserved_proc depends on the
// architecture.
void *reserved_proc[8 - (sizeof(uint64_t) / sizeof(void *))];
} ANativeWindowBuffer_t;
namespace rx namespace rx
{ {
NativeBufferImageSiblingAndroid::NativeBufferImageSiblingAndroid(EGLClientBuffer buffer) NativeBufferImageSiblingAndroid::NativeBufferImageSiblingAndroid(EGLClientBuffer buffer)
: mBuffer(static_cast<struct ANativeWindowBuffer *>(buffer)) : mBuffer(buffer), mFormat(GL_NONE)
{} {}
NativeBufferImageSiblingAndroid::~NativeBufferImageSiblingAndroid() {} NativeBufferImageSiblingAndroid::~NativeBufferImageSiblingAndroid() {}
egl::Error NativeBufferImageSiblingAndroid::initialize(const egl::Display *display)
{
int pixelFormat = 0;
angle::android::GetANativeWindowBufferProperties(
angle::android::ClientBufferToANativeWindowBuffer(mBuffer), &mSize.width, &mSize.height,
&mSize.depth, &pixelFormat);
mFormat = gl::Format(angle::android::NativePixelFormatToGLInternalFormat(pixelFormat));
return egl::NoError();
}
gl::Format NativeBufferImageSiblingAndroid::getFormat() const gl::Format NativeBufferImageSiblingAndroid::getFormat() const
{ {
return gl::Format(android::NativePixelFormatToGLInternalFormat(mBuffer->format)); return mFormat;
} }
bool NativeBufferImageSiblingAndroid::isRenderable(const gl::Context *context) const bool NativeBufferImageSiblingAndroid::isRenderable(const gl::Context *context) const
...@@ -79,7 +46,7 @@ bool NativeBufferImageSiblingAndroid::isTexturable(const gl::Context *context) c ...@@ -79,7 +46,7 @@ bool NativeBufferImageSiblingAndroid::isTexturable(const gl::Context *context) c
gl::Extents NativeBufferImageSiblingAndroid::getSize() const gl::Extents NativeBufferImageSiblingAndroid::getSize() const
{ {
return gl::Extents(mBuffer->width, mBuffer->height, 1); return mSize;
} }
size_t NativeBufferImageSiblingAndroid::getSamples() const size_t NativeBufferImageSiblingAndroid::getSamples() const
...@@ -89,7 +56,7 @@ size_t NativeBufferImageSiblingAndroid::getSamples() const ...@@ -89,7 +56,7 @@ size_t NativeBufferImageSiblingAndroid::getSamples() const
EGLClientBuffer NativeBufferImageSiblingAndroid::getBuffer() const EGLClientBuffer NativeBufferImageSiblingAndroid::getBuffer() const
{ {
return static_cast<EGLClientBuffer>(mBuffer); return mBuffer;
} }
} // namespace rx } // namespace rx
...@@ -12,8 +12,6 @@ ...@@ -12,8 +12,6 @@
#include "libANGLE/renderer/gl/egl/ExternalImageSiblingEGL.h" #include "libANGLE/renderer/gl/egl/ExternalImageSiblingEGL.h"
struct ANativeWindowBuffer;
namespace rx namespace rx
{ {
...@@ -23,6 +21,8 @@ class NativeBufferImageSiblingAndroid : public ExternalImageSiblingEGL ...@@ -23,6 +21,8 @@ class NativeBufferImageSiblingAndroid : public ExternalImageSiblingEGL
NativeBufferImageSiblingAndroid(EGLClientBuffer buffer); NativeBufferImageSiblingAndroid(EGLClientBuffer buffer);
virtual ~NativeBufferImageSiblingAndroid(); virtual ~NativeBufferImageSiblingAndroid();
egl::Error initialize(const egl::Display *display) override;
// ExternalImageSiblingImpl interface // ExternalImageSiblingImpl interface
gl::Format getFormat() const override; gl::Format getFormat() const override;
bool isRenderable(const gl::Context *context) const override; bool isRenderable(const gl::Context *context) const override;
...@@ -34,7 +34,9 @@ class NativeBufferImageSiblingAndroid : public ExternalImageSiblingEGL ...@@ -34,7 +34,9 @@ class NativeBufferImageSiblingAndroid : public ExternalImageSiblingEGL
EGLClientBuffer getBuffer() const override; EGLClientBuffer getBuffer() const override;
private: private:
struct ANativeWindowBuffer *mBuffer; EGLClientBuffer mBuffer;
gl::Extents mSize;
gl::Format mFormat;
}; };
} // namespace rx } // 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.
//
// android_util.h: Utilities for the using the Android platform
#ifndef LIBANGLE_RENDERER_GL_EGL_ANDROID_ANDROID_UTIL_H_
#define LIBANGLE_RENDERER_GL_EGL_ANDROID_ANDROID_UTIL_H_
#include "angle_gl.h"
namespace rx
{
namespace android
{
GLenum NativePixelFormatToGLInternalFormat(int pixelFormat);
}
} // namespace rx
#endif // LIBANGLE_RENDERER_GL_EGL_ANDROID_ANDROID_UTIL_H_
\ No newline at end of file
...@@ -191,6 +191,7 @@ void DisplayVk::generateExtensions(egl::DisplayExtensions *outExtensions) const ...@@ -191,6 +191,7 @@ void DisplayVk::generateExtensions(egl::DisplayExtensions *outExtensions) const
outExtensions->glTextureCubemapImage = true; outExtensions->glTextureCubemapImage = true;
outExtensions->glTexture3DImage = false; outExtensions->glTexture3DImage = false;
outExtensions->glRenderbufferImage = true; outExtensions->glRenderbufferImage = true;
outExtensions->imageNativeBuffer = getRenderer()->getFeatures().supportsAndroidHardwareBuffer;
} }
void DisplayVk::generateCaps(egl::Caps *outCaps) const void DisplayVk::generateCaps(egl::Caps *outCaps) const
......
...@@ -62,17 +62,37 @@ egl::Error ImageVk::initialize(const egl::Display *display) ...@@ -62,17 +62,37 @@ egl::Error ImageVk::initialize(const egl::Display *display)
mImageLevel = mState.imageIndex.getLevelIndex(); mImageLevel = mState.imageIndex.getLevelIndex();
mImageLayer = mState.imageIndex.hasLayer() ? mState.imageIndex.getLayerIndex() : 0; mImageLayer = mState.imageIndex.hasLayer() ? mState.imageIndex.getLayerIndex() : 0;
} }
else if (egl::IsRenderbufferTarget(mState.target)) else
{ {
RenderbufferVk *renderbufferVk = if (egl::IsRenderbufferTarget(mState.target))
GetImplAs<RenderbufferVk>(GetAs<gl::Renderbuffer>(mState.source)); {
mImage = renderbufferVk->getImage(); RenderbufferVk *renderbufferVk =
GetImplAs<RenderbufferVk>(GetAs<gl::Renderbuffer>(mState.source));
mImage = renderbufferVk->getImage();
// Make sure a staging buffer is ready to use to upload data // Make sure a staging buffer is ready to use to upload data
ASSERT(mContext != nullptr); ASSERT(mContext != nullptr);
ContextVk *contextVk = vk::GetImpl(mContext); ContextVk *contextVk = vk::GetImpl(mContext);
RendererVk *renderer = contextVk->getRenderer(); RendererVk *renderer = contextVk->getRenderer();
mImage->initStagingBuffer(renderer); mImage->initStagingBuffer(renderer);
}
else if (egl::IsExternalImageTarget(mState.target))
{
const ExternalImageSiblingVk *externalImageSibling =
GetImplAs<ExternalImageSiblingVk>(GetAs<egl::ExternalImageSibling>(mState.source));
mImage = externalImageSibling->getImage();
// Make sure a staging buffer is ready to use to upload data
ASSERT(mContext == nullptr);
DisplayVk *displayVk = vk::GetImpl(display);
RendererVk *renderer = displayVk->getRenderer();
mImage->initStagingBuffer(renderer);
}
else
{
UNREACHABLE();
return egl::EglBadAccess();
}
mOwnsImage = false; mOwnsImage = false;
...@@ -80,11 +100,6 @@ egl::Error ImageVk::initialize(const egl::Display *display) ...@@ -80,11 +100,6 @@ egl::Error ImageVk::initialize(const egl::Display *display)
mImageLevel = 0; mImageLevel = 0;
mImageLayer = 0; mImageLayer = 0;
} }
else
{
UNREACHABLE();
return egl::EglBadAccess();
}
return egl::NoError(); return egl::NoError();
} }
......
...@@ -16,6 +16,15 @@ ...@@ -16,6 +16,15 @@
namespace rx namespace rx
{ {
class ExternalImageSiblingVk : public ExternalImageSiblingImpl
{
public:
ExternalImageSiblingVk() {}
~ExternalImageSiblingVk() override {}
virtual vk::ImageHelper *getImage() const = 0;
};
class ImageVk : public ImageImpl class ImageVk : public ImageImpl
{ {
public: public:
......
...@@ -139,6 +139,16 @@ angle::Result RenderbufferVk::setStorageEGLImageTarget(const gl::Context *contex ...@@ -139,6 +139,16 @@ angle::Result RenderbufferVk::setStorageEGLImageTarget(const gl::Context *contex
VkImageAspectFlags aspect = vk::GetFormatAspectFlags(textureFormat); VkImageAspectFlags aspect = vk::GetFormatAspectFlags(textureFormat);
// Transfer the image to this queue if needed
uint32_t rendererQueueFamilyIndex = contextVk->getRenderer()->getQueueFamilyIndex();
if (mImage->isQueueChangeNeccesary(rendererQueueFamilyIndex))
{
vk::CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(mImage->recordCommands(contextVk, &commandBuffer));
mImage->changeLayoutAndQueue(aspect, vk::ImageLayout::ColorAttachment,
rendererQueueFamilyIndex, commandBuffer);
}
ANGLE_TRY(mImage->initLayerImageView(contextVk, imageVk->getImageTextureType(), aspect, ANGLE_TRY(mImage->initLayerImageView(contextVk, imageVk->getImageTextureType(), aspect,
gl::SwizzleState(), &mImageView, imageVk->getImageLevel(), gl::SwizzleState(), &mImageView, imageVk->getImageLevel(),
1, imageVk->getImageLayer(), 1)); 1, imageVk->getImageLayer(), 1));
......
...@@ -923,6 +923,18 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF ...@@ -923,6 +923,18 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
enabledDeviceExtensions.push_back(VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME); enabledDeviceExtensions.push_back(VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME);
} }
#if defined(ANGLE_PLATFORM_ANDROID)
if (getFeatures().supportsAndroidHardwareBuffer)
{
enabledDeviceExtensions.push_back(VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME);
enabledDeviceExtensions.push_back(
VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME);
InitExternalMemoryHardwareBufferANDROIDFunctions(mInstance);
}
#else
ASSERT(!getFeatures().supportsAndroidHardwareBuffer);
#endif
std::sort(enabledDeviceExtensions.begin(), enabledDeviceExtensions.end(), StrLess); std::sort(enabledDeviceExtensions.begin(), enabledDeviceExtensions.end(), StrLess);
ANGLE_VK_TRY(displayVk, VerifyExtensionsPresent(deviceExtensionNames, enabledDeviceExtensions)); ANGLE_VK_TRY(displayVk, VerifyExtensionsPresent(deviceExtensionNames, enabledDeviceExtensions));
...@@ -1181,6 +1193,11 @@ void RendererVk::initFeatures(const ExtensionNameList &deviceExtensionNames) ...@@ -1181,6 +1193,11 @@ void RendererVk::initFeatures(const ExtensionNameList &deviceExtensionNames)
{ {
mFeatures.supportsIncrementalPresent = true; mFeatures.supportsIncrementalPresent = true;
} }
#if defined(ANGLE_PLATFORM_ANDROID)
mFeatures.supportsAndroidHardwareBuffer = ExtensionFound(
VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME, deviceExtensionNames);
#endif
} }
void RendererVk::initPipelineCacheVkKey() void RendererVk::initPipelineCacheVkKey()
......
...@@ -688,6 +688,17 @@ angle::Result TextureVk::setEGLImageTarget(const gl::Context *context, ...@@ -688,6 +688,17 @@ angle::Result TextureVk::setEGLImageTarget(const gl::Context *context,
const vk::Format &format = renderer->getFormat(image->getFormat().info->sizedInternalFormat); const vk::Format &format = renderer->getFormat(image->getFormat().info->sizedInternalFormat);
ANGLE_TRY(initImageViews(contextVk, format, 1)); ANGLE_TRY(initImageViews(contextVk, format, 1));
// Transfer the image to this queue if needed
uint32_t rendererQueueFamilyIndex = renderer->getQueueFamilyIndex();
if (mImage->isQueueChangeNeccesary(rendererQueueFamilyIndex))
{
vk::CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(mImage->recordCommands(contextVk, &commandBuffer));
mImage->changeLayoutAndQueue(VK_IMAGE_ASPECT_COLOR_BIT,
vk::ImageLayout::FragmentShaderReadOnly,
rendererQueueFamilyIndex, commandBuffer);
}
return angle::Result::Continue; return angle::Result::Continue;
} }
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
#include "libANGLE/renderer/vulkan/RendererVk.h" #include "libANGLE/renderer/vulkan/RendererVk.h"
#include "libANGLE/renderer/vulkan/android/HardwareBufferImageSiblingVkAndroid.h"
#include "libANGLE/renderer/vulkan/android/WindowSurfaceVkAndroid.h" #include "libANGLE/renderer/vulkan/android/WindowSurfaceVkAndroid.h"
#include "libANGLE/renderer/vulkan/vk_caps_utils.h" #include "libANGLE/renderer/vulkan/vk_caps_utils.h"
...@@ -58,6 +59,38 @@ bool DisplayVkAndroid::checkConfigSupport(egl::Config *config) ...@@ -58,6 +59,38 @@ bool DisplayVkAndroid::checkConfigSupport(egl::Config *config)
return true; return true;
} }
egl::Error DisplayVkAndroid::validateImageClientBuffer(const gl::Context *context,
EGLenum target,
EGLClientBuffer clientBuffer,
const egl::AttributeMap &attribs) const
{
switch (target)
{
case EGL_NATIVE_BUFFER_ANDROID:
return HardwareBufferImageSiblingVkAndroid::ValidateHardwareBuffer(mRenderer,
clientBuffer);
default:
return DisplayVk::validateImageClientBuffer(context, target, clientBuffer, attribs);
}
}
ExternalImageSiblingImpl *DisplayVkAndroid::createExternalImageSibling(
const gl::Context *context,
EGLenum target,
EGLClientBuffer buffer,
const egl::AttributeMap &attribs)
{
switch (target)
{
case EGL_NATIVE_BUFFER_ANDROID:
return new HardwareBufferImageSiblingVkAndroid(buffer);
default:
return DisplayVk::createExternalImageSibling(context, target, buffer, attribs);
}
}
const char *DisplayVkAndroid::getWSIExtension() const const char *DisplayVkAndroid::getWSIExtension() const
{ {
return VK_KHR_ANDROID_SURFACE_EXTENSION_NAME; return VK_KHR_ANDROID_SURFACE_EXTENSION_NAME;
......
...@@ -31,6 +31,16 @@ class DisplayVkAndroid : public DisplayVk ...@@ -31,6 +31,16 @@ class DisplayVkAndroid : public DisplayVk
egl::ConfigSet generateConfigs() override; egl::ConfigSet generateConfigs() override;
bool checkConfigSupport(egl::Config *config) override; bool checkConfigSupport(egl::Config *config) override;
egl::Error validateImageClientBuffer(const gl::Context *context,
EGLenum target,
EGLClientBuffer clientBuffer,
const egl::AttributeMap &attribs) const override;
ExternalImageSiblingImpl *createExternalImageSibling(const gl::Context *context,
EGLenum target,
EGLClientBuffer buffer,
const egl::AttributeMap &attribs) override;
const char *getWSIExtension() const override; const char *getWSIExtension() const override;
}; };
......
//
// 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.
//
// HardwareBufferImageSiblingVkAndroid.cpp: Implements HardwareBufferImageSiblingVkAndroid.
#include "libANGLE/renderer/vulkan/android/HardwareBufferImageSiblingVkAndroid.h"
#include "common/android_util.h"
#include "libANGLE/Display.h"
#include "libANGLE/renderer/vulkan/DisplayVk.h"
#include "libANGLE/renderer/vulkan/RendererVk.h"
namespace rx
{
HardwareBufferImageSiblingVkAndroid::HardwareBufferImageSiblingVkAndroid(EGLClientBuffer buffer)
: mBuffer(buffer),
mFormat(GL_NONE),
mRenderable(false),
mTextureable(false),
mSamples(0),
mImage(nullptr)
{}
HardwareBufferImageSiblingVkAndroid::~HardwareBufferImageSiblingVkAndroid() {}
// Static
egl::Error HardwareBufferImageSiblingVkAndroid::ValidateHardwareBuffer(RendererVk *renderer,
EGLClientBuffer buffer)
{
struct ANativeWindowBuffer *windowBuffer =
angle::android::ClientBufferToANativeWindowBuffer(buffer);
struct AHardwareBuffer *hardwareBuffer =
angle::android::ANativeWindowBufferToAHardwareBuffer(windowBuffer);
VkAndroidHardwareBufferFormatPropertiesANDROID bufferFormatProperties = {};
bufferFormatProperties.sType =
VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID;
bufferFormatProperties.pNext = nullptr;
VkAndroidHardwareBufferPropertiesANDROID bufferProperties = {};
bufferProperties.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID;
bufferProperties.pNext = &bufferFormatProperties;
VkDevice device = renderer->getDevice();
VkResult result =
vkGetAndroidHardwareBufferPropertiesANDROID(device, hardwareBuffer, &bufferProperties);
if (result != VK_SUCCESS)
{
return egl::EglBadParameter() << "Failed to query AHardwareBuffer properties";
}
if (!HasFullTextureFormatSupport(renderer, bufferFormatProperties.format))
{
return egl::EglBadParameter()
<< "AHardwareBuffer format does not support enough features to use as a texture.";
}
return egl::NoError();
}
egl::Error HardwareBufferImageSiblingVkAndroid::initialize(const egl::Display *display)
{
DisplayVk *displayVk = vk::GetImpl(display);
return angle::ToEGL(initImpl(displayVk), displayVk, EGL_BAD_PARAMETER);
}
angle::Result HardwareBufferImageSiblingVkAndroid::initImpl(DisplayVk *displayVk)
{
RendererVk *renderer = displayVk->getRenderer();
struct ANativeWindowBuffer *windowBuffer =
angle::android::ClientBufferToANativeWindowBuffer(mBuffer);
int pixelFormat = 0;
angle::android::GetANativeWindowBufferProperties(windowBuffer, &mSize.width, &mSize.height,
&mSize.depth, &pixelFormat);
GLenum internalFormat = angle::android::NativePixelFormatToGLInternalFormat(pixelFormat);
mFormat = gl::Format(internalFormat);
struct AHardwareBuffer *hardwareBuffer =
angle::android::ANativeWindowBufferToAHardwareBuffer(windowBuffer);
VkAndroidHardwareBufferFormatPropertiesANDROID bufferFormatProperties;
bufferFormatProperties.sType =
VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID;
bufferFormatProperties.pNext = nullptr;
VkAndroidHardwareBufferPropertiesANDROID bufferProperties = {};
bufferProperties.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID;
bufferProperties.pNext = &bufferFormatProperties;
VkDevice device = renderer->getDevice();
ANGLE_VK_TRY(displayVk, vkGetAndroidHardwareBufferPropertiesANDROID(device, hardwareBuffer,
&bufferProperties));
const vk::Format &vkFormat = renderer->getFormat(internalFormat);
const angle::Format &textureFormat = vkFormat.textureFormat();
bool isDepthOrStencilFormat = textureFormat.depthBits > 0 || textureFormat.stencilBits > 0;
const VkImageUsageFlags usage =
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
VK_IMAGE_USAGE_SAMPLED_BIT |
(textureFormat.redBits > 0 ? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT : 0) |
(isDepthOrStencilFormat ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : 0);
VkExternalFormatANDROID externalFormat = {};
externalFormat.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID;
externalFormat.externalFormat = 0;
if (bufferFormatProperties.format == VK_FORMAT_UNDEFINED)
{
externalFormat.externalFormat = bufferFormatProperties.externalFormat;
}
VkExternalMemoryImageCreateInfo externalMemoryImageCreateInfo = {};
externalMemoryImageCreateInfo.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO;
externalMemoryImageCreateInfo.pNext = &externalFormat;
externalMemoryImageCreateInfo.handleTypes =
VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
mImage = new vk::ImageHelper();
ANGLE_TRY(mImage->initExternal(displayVk, gl::TextureType::_2D, mSize, vkFormat, 1, usage,
vk::ImageLayout::ExternalPreInitialized,
&externalMemoryImageCreateInfo, 1, 1));
VkImportAndroidHardwareBufferInfoANDROID importHardwareBufferInfo = {};
importHardwareBufferInfo.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID;
importHardwareBufferInfo.buffer = hardwareBuffer;
VkMemoryDedicatedAllocateInfo dedicatedAllocInfo = {};
dedicatedAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
dedicatedAllocInfo.pNext = &importHardwareBufferInfo;
dedicatedAllocInfo.image = mImage->getImage().getHandle();
dedicatedAllocInfo.buffer = VK_NULL_HANDLE;
VkMemoryRequirements externalMemoryRequirements = {};
externalMemoryRequirements.size = bufferProperties.allocationSize;
externalMemoryRequirements.alignment = 0;
externalMemoryRequirements.memoryTypeBits = bufferProperties.memoryTypeBits;
VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
ANGLE_TRY(mImage->initExternalMemory(displayVk, renderer->getMemoryProperties(),
externalMemoryRequirements, &dedicatedAllocInfo,
VK_QUEUE_FAMILY_FOREIGN_EXT, flags));
constexpr uint32_t kColorRenderableRequiredBits = VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
constexpr uint32_t kDepthStencilRenderableRequiredBits = VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
mRenderable = renderer->hasTextureFormatFeatureBits(vkFormat.vkTextureFormat,
kColorRenderableRequiredBits) ||
renderer->hasTextureFormatFeatureBits(vkFormat.vkTextureFormat,
kDepthStencilRenderableRequiredBits);
constexpr uint32_t kTextureableRequiredBits =
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
mTextureable =
renderer->hasTextureFormatFeatureBits(vkFormat.vkTextureFormat, kTextureableRequiredBits);
return angle::Result::Continue;
}
void HardwareBufferImageSiblingVkAndroid::onDestroy(const egl::Display *display)
{
DisplayVk *displayVk = vk::GetImpl(display);
RendererVk *renderer = displayVk->getRenderer();
if (mImage != nullptr)
{
mImage->releaseImage(renderer);
mImage->releaseStagingBuffer(renderer);
SafeDelete(mImage);
}
}
gl::Format HardwareBufferImageSiblingVkAndroid::getFormat() const
{
return mFormat;
}
bool HardwareBufferImageSiblingVkAndroid::isRenderable(const gl::Context *context) const
{
return mRenderable;
}
bool HardwareBufferImageSiblingVkAndroid::isTexturable(const gl::Context *context) const
{
return mTextureable;
}
gl::Extents HardwareBufferImageSiblingVkAndroid::getSize() const
{
return mSize;
}
size_t HardwareBufferImageSiblingVkAndroid::getSamples() const
{
return mSamples;
}
// ExternalImageSiblingVk interface
vk::ImageHelper *HardwareBufferImageSiblingVkAndroid::getImage() const
{
return mImage;
}
} // 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.
//
// HardwareBufferImageSiblingVkAndroid.h: Defines the HardwareBufferImageSiblingVkAndroid to wrap
// EGL images created from AHardwareBuffer objects
#ifndef LIBANGLE_RENDERER_VULKAN_ANDROID_HARDWAREBUFFERIMAGESIBLINGVKANDROID_H_
#define LIBANGLE_RENDERER_VULKAN_ANDROID_HARDWAREBUFFERIMAGESIBLINGVKANDROID_H_
#include "libANGLE/renderer/vulkan/ImageVk.h"
namespace rx
{
class HardwareBufferImageSiblingVkAndroid : public ExternalImageSiblingVk
{
public:
HardwareBufferImageSiblingVkAndroid(EGLClientBuffer buffer);
~HardwareBufferImageSiblingVkAndroid() override;
static egl::Error ValidateHardwareBuffer(RendererVk *renderer, EGLClientBuffer buffer);
egl::Error initialize(const egl::Display *display) override;
void onDestroy(const egl::Display *display) override;
// ExternalImageSiblingImpl interface
gl::Format getFormat() const override;
bool isRenderable(const gl::Context *context) const override;
bool isTexturable(const gl::Context *context) const override;
gl::Extents getSize() const override;
size_t getSamples() const override;
// ExternalImageSiblingVk interface
vk::ImageHelper *getImage() const override;
private:
angle::Result initImpl(DisplayVk *displayVk);
EGLClientBuffer mBuffer;
gl::Extents mSize;
gl::Format mFormat;
bool mRenderable;
bool mTextureable;
size_t mSamples;
vk::ImageHelper *mImage;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_ANDROID_HARDWAREBUFFERIMAGESIBLINGVKANDROID_H_
...@@ -65,17 +65,6 @@ void FillTextureFormatCaps(RendererVk *renderer, VkFormat format, gl::TextureCap ...@@ -65,17 +65,6 @@ void FillTextureFormatCaps(RendererVk *renderer, VkFormat format, gl::TextureCap
} }
} }
bool HasFullTextureFormatSupport(RendererVk *renderer, VkFormat vkFormat)
{
constexpr uint32_t kBitsColor = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT |
VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
constexpr uint32_t kBitsDepth = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
return renderer->hasTextureFormatFeatureBits(vkFormat, kBitsColor) ||
renderer->hasTextureFormatFeatureBits(vkFormat, kBitsDepth);
}
bool HasFullBufferFormatSupport(RendererVk *renderer, VkFormat vkFormat) bool HasFullBufferFormatSupport(RendererVk *renderer, VkFormat vkFormat)
{ {
return renderer->hasBufferFormatFeatureBits(vkFormat, VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT); return renderer->hasBufferFormatFeatureBits(vkFormat, VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT);
...@@ -203,6 +192,17 @@ void FormatTable::initialize(RendererVk *renderer, ...@@ -203,6 +192,17 @@ void FormatTable::initialize(RendererVk *renderer,
} }
} // namespace vk } // namespace vk
bool HasFullTextureFormatSupport(RendererVk *renderer, VkFormat vkFormat)
{
constexpr uint32_t kBitsColor = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT |
VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
constexpr uint32_t kBitsDepth = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
return renderer->hasTextureFormatFeatureBits(vkFormat, kBitsColor) ||
renderer->hasTextureFormatFeatureBits(vkFormat, kBitsDepth);
}
size_t GetVertexInputAlignment(const vk::Format &format) size_t GetVertexInputAlignment(const vk::Format &format)
{ {
const angle::Format &bufferFormat = format.bufferFormat(); const angle::Format &bufferFormat = format.bufferFormat();
......
...@@ -121,6 +121,9 @@ const VkFormatProperties &GetMandatoryFormatSupport(VkFormat vkFormat); ...@@ -121,6 +121,9 @@ const VkFormatProperties &GetMandatoryFormatSupport(VkFormat vkFormat);
} // namespace vk } // namespace vk
// Checks if a vkFormat supports all the features needed to use it as a GL texture format
bool HasFullTextureFormatSupport(RendererVk *renderer, VkFormat vkFormat);
// Returns the alignment for a buffer to be used with the vertex input stage in Vulkan. This // Returns the alignment for a buffer to be used with the vertex input stage in Vulkan. This
// calculation is listed in the Vulkan spec at the end of the section 'Vertex Input Description'. // calculation is listed in the Vulkan spec at the end of the section 'Vertex Input Description'.
size_t GetVertexInputAlignment(const vk::Format &format); size_t GetVertexInputAlignment(const vk::Format &format);
......
...@@ -68,15 +68,15 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory ...@@ -68,15 +68,15 @@ constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemory
}, },
}, },
{ {
ImageLayout::PreInitialized, ImageLayout::ExternalPreInitialized,
{ {
VK_IMAGE_LAYOUT_PREINITIALIZED, VK_IMAGE_LAYOUT_PREINITIALIZED,
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_HOST_BIT | VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
// Transition to: we don't expect to transition into PreInitialized. // Transition to: we don't expect to transition into PreInitialized.
0, 0,
// Transition from: all writes must finish before barrier. // Transition from: all writes must finish before barrier.
VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_MEMORY_WRITE_BIT,
false, false,
}, },
}, },
...@@ -1068,8 +1068,8 @@ angle::Result BufferHelper::init(Context *context, ...@@ -1068,8 +1068,8 @@ angle::Result BufferHelper::init(Context *context,
{ {
mSize = createInfo.size; mSize = createInfo.size;
ANGLE_VK_TRY(context, mBuffer.init(context->getDevice(), createInfo)); ANGLE_VK_TRY(context, mBuffer.init(context->getDevice(), createInfo));
return vk::AllocateBufferMemory(context, memoryPropertyFlags, &mMemoryPropertyFlags, &mBuffer, return vk::AllocateBufferMemory(context, memoryPropertyFlags, &mMemoryPropertyFlags, nullptr,
&mDeviceMemory); &mBuffer, &mDeviceMemory);
} }
void BufferHelper::destroy(VkDevice device) void BufferHelper::destroy(VkDevice device)
...@@ -1219,6 +1219,7 @@ ImageHelper::ImageHelper() ...@@ -1219,6 +1219,7 @@ ImageHelper::ImageHelper()
mFormat(nullptr), mFormat(nullptr),
mSamples(0), mSamples(0),
mCurrentLayout(ImageLayout::Undefined), mCurrentLayout(ImageLayout::Undefined),
mCurrentQueueFamilyIndex(std::numeric_limits<uint32_t>::max()),
mLayerCount(0), mLayerCount(0),
mLevelCount(0), mLevelCount(0),
mStagingBuffer(kStagingBufferFlags, kStagingBufferSize, true) mStagingBuffer(kStagingBufferFlags, kStagingBufferSize, true)
...@@ -1232,6 +1233,7 @@ ImageHelper::ImageHelper(ImageHelper &&other) ...@@ -1232,6 +1233,7 @@ ImageHelper::ImageHelper(ImageHelper &&other)
mFormat(other.mFormat), mFormat(other.mFormat),
mSamples(other.mSamples), mSamples(other.mSamples),
mCurrentLayout(other.mCurrentLayout), mCurrentLayout(other.mCurrentLayout),
mCurrentQueueFamilyIndex(other.mCurrentQueueFamilyIndex),
mLayerCount(other.mLayerCount), mLayerCount(other.mLayerCount),
mLevelCount(other.mLevelCount), mLevelCount(other.mLevelCount),
mStagingBuffer(std::move(other.mStagingBuffer)), mStagingBuffer(std::move(other.mStagingBuffer)),
...@@ -1263,6 +1265,21 @@ angle::Result ImageHelper::init(Context *context, ...@@ -1263,6 +1265,21 @@ angle::Result ImageHelper::init(Context *context,
uint32_t mipLevels, uint32_t mipLevels,
uint32_t layerCount) uint32_t layerCount)
{ {
return initExternal(context, textureType, extents, format, samples, usage,
ImageLayout::Undefined, nullptr, mipLevels, layerCount);
}
angle::Result ImageHelper::initExternal(Context *context,
gl::TextureType textureType,
const gl::Extents &extents,
const Format &format,
GLint samples,
VkImageUsageFlags usage,
ImageLayout initialLayout,
const void *externalImageCreateInfo,
uint32_t mipLevels,
uint32_t layerCount)
{
ASSERT(!valid()); ASSERT(!valid());
// Validate that the input layerCount is compatible with the texture type // Validate that the input layerCount is compatible with the texture type
...@@ -1279,6 +1296,7 @@ angle::Result ImageHelper::init(Context *context, ...@@ -1279,6 +1296,7 @@ angle::Result ImageHelper::init(Context *context,
VkImageCreateInfo imageInfo = {}; VkImageCreateInfo imageInfo = {};
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageInfo.pNext = externalImageCreateInfo;
imageInfo.flags = GetImageCreateFlags(textureType); imageInfo.flags = GetImageCreateFlags(textureType);
imageInfo.imageType = gl_vk::GetImageType(textureType); imageInfo.imageType = gl_vk::GetImageType(textureType);
imageInfo.format = format.vkTextureFormat; imageInfo.format = format.vkTextureFormat;
...@@ -1293,9 +1311,9 @@ angle::Result ImageHelper::init(Context *context, ...@@ -1293,9 +1311,9 @@ angle::Result ImageHelper::init(Context *context,
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
imageInfo.queueFamilyIndexCount = 0; imageInfo.queueFamilyIndexCount = 0;
imageInfo.pQueueFamilyIndices = nullptr; imageInfo.pQueueFamilyIndices = nullptr;
imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; imageInfo.initialLayout = kImageMemoryBarrierData[initialLayout].layout;
mCurrentLayout = ImageLayout::Undefined; mCurrentLayout = initialLayout;
ANGLE_VK_TRY(context, mImage.init(context->getDevice(), imageInfo)); ANGLE_VK_TRY(context, mImage.init(context->getDevice(), imageInfo));
...@@ -1329,7 +1347,23 @@ angle::Result ImageHelper::initMemory(Context *context, ...@@ -1329,7 +1347,23 @@ angle::Result ImageHelper::initMemory(Context *context,
VkMemoryPropertyFlags flags) VkMemoryPropertyFlags flags)
{ {
// TODO(jmadill): Memory sub-allocation. http://anglebug.com/2162 // TODO(jmadill): Memory sub-allocation. http://anglebug.com/2162
ANGLE_TRY(AllocateImageMemory(context, flags, &mImage, &mDeviceMemory)); ANGLE_TRY(AllocateImageMemory(context, flags, nullptr, &mImage, &mDeviceMemory));
mCurrentQueueFamilyIndex = context->getRenderer()->getQueueFamilyIndex();
return angle::Result::Continue;
}
angle::Result ImageHelper::initExternalMemory(Context *context,
const MemoryProperties &memoryProperties,
const VkMemoryRequirements &memoryRequirements,
const void *extraAllocationInfo,
uint32_t currentQueueFamilyIndex,
VkMemoryPropertyFlags flags)
{
// TODO(jmadill): Memory sub-allocation. http://anglebug.com/2162
ANGLE_TRY(AllocateImageMemoryWithRequirements(context, flags, memoryRequirements,
extraAllocationInfo, &mImage, &mDeviceMemory));
mCurrentQueueFamilyIndex = currentQueueFamilyIndex;
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -1496,7 +1530,7 @@ VkImageLayout ImageHelper::getCurrentLayout() const ...@@ -1496,7 +1530,7 @@ VkImageLayout ImageHelper::getCurrentLayout() const
return kImageMemoryBarrierData[mCurrentLayout].layout; return kImageMemoryBarrierData[mCurrentLayout].layout;
} }
bool ImageHelper::isLayoutChangeNecessary(ImageLayout newLayout) bool ImageHelper::isLayoutChangeNecessary(ImageLayout newLayout) const
{ {
const ImageMemoryBarrierData &layoutData = kImageMemoryBarrierData[mCurrentLayout]; const ImageMemoryBarrierData &layoutData = kImageMemoryBarrierData[mCurrentLayout];
...@@ -1515,6 +1549,24 @@ void ImageHelper::changeLayout(VkImageAspectFlags aspectMask, ...@@ -1515,6 +1549,24 @@ void ImageHelper::changeLayout(VkImageAspectFlags aspectMask,
return; return;
} }
forceChangeLayoutAndQueue(aspectMask, newLayout, mCurrentQueueFamilyIndex, commandBuffer);
}
void ImageHelper::changeLayoutAndQueue(VkImageAspectFlags aspectMask,
ImageLayout newLayout,
uint32_t newQueueFamilyIndex,
CommandBuffer *commandBuffer)
{
ASSERT(isQueueChangeNeccesary(newQueueFamilyIndex));
forceChangeLayoutAndQueue(aspectMask, newLayout, newQueueFamilyIndex, commandBuffer);
}
void ImageHelper::forceChangeLayoutAndQueue(VkImageAspectFlags aspectMask,
ImageLayout newLayout,
uint32_t newQueueFamilyIndex,
CommandBuffer *commandBuffer)
{
const ImageMemoryBarrierData &transitionFrom = kImageMemoryBarrierData[mCurrentLayout]; const ImageMemoryBarrierData &transitionFrom = kImageMemoryBarrierData[mCurrentLayout];
const ImageMemoryBarrierData &transitionTo = kImageMemoryBarrierData[newLayout]; const ImageMemoryBarrierData &transitionTo = kImageMemoryBarrierData[newLayout];
...@@ -1524,8 +1576,8 @@ void ImageHelper::changeLayout(VkImageAspectFlags aspectMask, ...@@ -1524,8 +1576,8 @@ void ImageHelper::changeLayout(VkImageAspectFlags aspectMask,
imageMemoryBarrier.dstAccessMask = transitionTo.dstAccessMask; imageMemoryBarrier.dstAccessMask = transitionTo.dstAccessMask;
imageMemoryBarrier.oldLayout = transitionFrom.layout; imageMemoryBarrier.oldLayout = transitionFrom.layout;
imageMemoryBarrier.newLayout = transitionTo.layout; imageMemoryBarrier.newLayout = transitionTo.layout;
imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; imageMemoryBarrier.srcQueueFamilyIndex = mCurrentQueueFamilyIndex;
imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; imageMemoryBarrier.dstQueueFamilyIndex = newQueueFamilyIndex;
imageMemoryBarrier.image = mImage.getHandle(); imageMemoryBarrier.image = mImage.getHandle();
// TODO(jmadill): Is this needed for mipped/layer images? // TODO(jmadill): Is this needed for mipped/layer images?
...@@ -1539,6 +1591,7 @@ void ImageHelper::changeLayout(VkImageAspectFlags aspectMask, ...@@ -1539,6 +1591,7 @@ void ImageHelper::changeLayout(VkImageAspectFlags aspectMask,
nullptr, 0, nullptr, 1, &imageMemoryBarrier); nullptr, 0, nullptr, 1, &imageMemoryBarrier);
mCurrentLayout = newLayout; mCurrentLayout = newLayout;
mCurrentQueueFamilyIndex = newQueueFamilyIndex;
} }
void ImageHelper::clearColor(const VkClearColorValue &color, void ImageHelper::clearColor(const VkClearColorValue &color,
......
...@@ -504,7 +504,7 @@ class BufferHelper final : public CommandGraphResource ...@@ -504,7 +504,7 @@ class BufferHelper final : public CommandGraphResource
enum class ImageLayout enum class ImageLayout
{ {
Undefined = 0, Undefined = 0,
PreInitialized = 1, ExternalPreInitialized = 1,
TransferSrc = 2, TransferSrc = 2,
TransferDst = 3, TransferDst = 3,
ComputeShaderReadOnly = 4, ComputeShaderReadOnly = 4,
...@@ -535,9 +535,25 @@ class ImageHelper final : public CommandGraphResource ...@@ -535,9 +535,25 @@ class ImageHelper final : public CommandGraphResource
VkImageUsageFlags usage, VkImageUsageFlags usage,
uint32_t mipLevels, uint32_t mipLevels,
uint32_t layerCount); uint32_t layerCount);
angle::Result initExternal(Context *context,
gl::TextureType textureType,
const gl::Extents &extents,
const Format &format,
GLint samples,
VkImageUsageFlags usage,
ImageLayout initialLayout,
const void *externalImageCreateInfo,
uint32_t mipLevels,
uint32_t layerCount);
angle::Result initMemory(Context *context, angle::Result initMemory(Context *context,
const MemoryProperties &memoryProperties, const MemoryProperties &memoryProperties,
VkMemoryPropertyFlags flags); VkMemoryPropertyFlags flags);
angle::Result initExternalMemory(Context *context,
const MemoryProperties &memoryProperties,
const VkMemoryRequirements &memoryRequirements,
const void *extraAllocationInfo,
uint32_t currentQueueFamilyIndex,
VkMemoryPropertyFlags flags);
angle::Result initLayerImageView(Context *context, angle::Result initLayerImageView(Context *context,
gl::TextureType textureType, gl::TextureType textureType,
VkImageAspectFlags aspectMask, VkImageAspectFlags aspectMask,
...@@ -671,13 +687,28 @@ class ImageHelper final : public CommandGraphResource ...@@ -671,13 +687,28 @@ class ImageHelper final : public CommandGraphResource
// changeLayout automatically skips the layout change if it's unnecessary. This function can be // changeLayout automatically skips the layout change if it's unnecessary. This function can be
// used to prevent creating a command graph node and subsequently a command buffer for the sole // used to prevent creating a command graph node and subsequently a command buffer for the sole
// purpose of performing a transition (which may then not be issued). // purpose of performing a transition (which may then not be issued).
bool isLayoutChangeNecessary(ImageLayout newLayout); bool isLayoutChangeNecessary(ImageLayout newLayout) const;
void changeLayout(VkImageAspectFlags aspectMask, void changeLayout(VkImageAspectFlags aspectMask,
ImageLayout newLayout, ImageLayout newLayout,
CommandBuffer *commandBuffer); CommandBuffer *commandBuffer);
bool isQueueChangeNeccesary(uint32_t newQueueFamilyIndex) const
{
return mCurrentQueueFamilyIndex != newQueueFamilyIndex;
}
void changeLayoutAndQueue(VkImageAspectFlags aspectMask,
ImageLayout newLayout,
uint32_t newQueueFamilyIndex,
CommandBuffer *commandBuffer);
private: private:
void forceChangeLayoutAndQueue(VkImageAspectFlags aspectMask,
ImageLayout newLayout,
uint32_t newQueueFamilyIndex,
CommandBuffer *commandBuffer);
struct SubresourceUpdate struct SubresourceUpdate
{ {
SubresourceUpdate(); SubresourceUpdate();
...@@ -729,6 +760,7 @@ class ImageHelper final : public CommandGraphResource ...@@ -729,6 +760,7 @@ class ImageHelper final : public CommandGraphResource
// Current state. // Current state.
ImageLayout mCurrentLayout; ImageLayout mCurrentLayout;
uint32_t mCurrentQueueFamilyIndex;
// Cached properties. // Cached properties.
uint32_t mLayerCount; uint32_t mLayerCount;
......
...@@ -100,6 +100,7 @@ angle::Result FindAndAllocateCompatibleMemory(vk::Context *context, ...@@ -100,6 +100,7 @@ angle::Result FindAndAllocateCompatibleMemory(vk::Context *context,
VkMemoryPropertyFlags requestedMemoryPropertyFlags, VkMemoryPropertyFlags requestedMemoryPropertyFlags,
VkMemoryPropertyFlags *memoryPropertyFlagsOut, VkMemoryPropertyFlags *memoryPropertyFlagsOut,
const VkMemoryRequirements &memoryRequirements, const VkMemoryRequirements &memoryRequirements,
const void *extraAllocationInfo,
vk::DeviceMemory *deviceMemoryOut) vk::DeviceMemory *deviceMemoryOut)
{ {
uint32_t memoryTypeIndex = 0; uint32_t memoryTypeIndex = 0;
...@@ -109,6 +110,7 @@ angle::Result FindAndAllocateCompatibleMemory(vk::Context *context, ...@@ -109,6 +110,7 @@ angle::Result FindAndAllocateCompatibleMemory(vk::Context *context,
VkMemoryAllocateInfo allocInfo = {}; VkMemoryAllocateInfo allocInfo = {};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.pNext = extraAllocationInfo;
allocInfo.memoryTypeIndex = memoryTypeIndex; allocInfo.memoryTypeIndex = memoryTypeIndex;
allocInfo.allocationSize = memoryRequirements.size; allocInfo.allocationSize = memoryRequirements.size;
...@@ -117,22 +119,39 @@ angle::Result FindAndAllocateCompatibleMemory(vk::Context *context, ...@@ -117,22 +119,39 @@ angle::Result FindAndAllocateCompatibleMemory(vk::Context *context,
} }
template <typename T> template <typename T>
angle::Result AllocateAndBindBufferOrImageMemory(vk::Context *context,
VkMemoryPropertyFlags requestedMemoryPropertyFlags,
VkMemoryPropertyFlags *memoryPropertyFlagsOut,
const VkMemoryRequirements &memoryRequirements,
const void *extraAllocationInfo,
T *bufferOrImage,
vk::DeviceMemory *deviceMemoryOut)
{
const vk::MemoryProperties &memoryProperties = context->getRenderer()->getMemoryProperties();
ANGLE_TRY(FindAndAllocateCompatibleMemory(
context, memoryProperties, requestedMemoryPropertyFlags, memoryPropertyFlagsOut,
memoryRequirements, extraAllocationInfo, deviceMemoryOut));
ANGLE_VK_TRY(context, bufferOrImage->bindMemory(context->getDevice(), *deviceMemoryOut));
return angle::Result::Continue;
}
template <typename T>
angle::Result AllocateBufferOrImageMemory(vk::Context *context, angle::Result AllocateBufferOrImageMemory(vk::Context *context,
VkMemoryPropertyFlags requestedMemoryPropertyFlags, VkMemoryPropertyFlags requestedMemoryPropertyFlags,
VkMemoryPropertyFlags *memoryPropertyFlagsOut, VkMemoryPropertyFlags *memoryPropertyFlagsOut,
const void *extraAllocationInfo,
T *bufferOrImage, T *bufferOrImage,
vk::DeviceMemory *deviceMemoryOut) vk::DeviceMemory *deviceMemoryOut)
{ {
const vk::MemoryProperties &memoryProperties = context->getRenderer()->getMemoryProperties();
// Call driver to determine memory requirements. // Call driver to determine memory requirements.
VkMemoryRequirements memoryRequirements; VkMemoryRequirements memoryRequirements;
bufferOrImage->getMemoryRequirements(context->getDevice(), &memoryRequirements); bufferOrImage->getMemoryRequirements(context->getDevice(), &memoryRequirements);
ANGLE_TRY(FindAndAllocateCompatibleMemory(context, memoryProperties, ANGLE_TRY(AllocateAndBindBufferOrImageMemory(
requestedMemoryPropertyFlags, memoryPropertyFlagsOut, context, requestedMemoryPropertyFlags, memoryPropertyFlagsOut, memoryRequirements,
memoryRequirements, deviceMemoryOut)); extraAllocationInfo, bufferOrImage, deviceMemoryOut));
ANGLE_VK_TRY(context, bufferOrImage->bindMemory(context->getDevice(), *deviceMemoryOut));
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -335,7 +354,7 @@ angle::Result StagingBuffer::init(Context *context, VkDeviceSize size, StagingUs ...@@ -335,7 +354,7 @@ angle::Result StagingBuffer::init(Context *context, VkDeviceSize size, StagingUs
ANGLE_VK_TRY(context, mBuffer.init(context->getDevice(), createInfo)); ANGLE_VK_TRY(context, mBuffer.init(context->getDevice(), createInfo));
VkMemoryPropertyFlags flagsOut = 0; VkMemoryPropertyFlags flagsOut = 0;
ANGLE_TRY(AllocateBufferMemory(context, flags, &flagsOut, &mBuffer, &mDeviceMemory)); ANGLE_TRY(AllocateBufferMemory(context, flags, &flagsOut, nullptr, &mBuffer, &mDeviceMemory));
mSize = static_cast<size_t>(size); mSize = static_cast<size_t>(size);
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -349,21 +368,37 @@ void StagingBuffer::dumpResources(Serial serial, std::vector<vk::GarbageObject> ...@@ -349,21 +368,37 @@ void StagingBuffer::dumpResources(Serial serial, std::vector<vk::GarbageObject>
angle::Result AllocateBufferMemory(vk::Context *context, angle::Result AllocateBufferMemory(vk::Context *context,
VkMemoryPropertyFlags requestedMemoryPropertyFlags, VkMemoryPropertyFlags requestedMemoryPropertyFlags,
VkMemoryPropertyFlags *memoryPropertyFlagsOut, VkMemoryPropertyFlags *memoryPropertyFlagsOut,
const void *extraAllocationInfo,
Buffer *buffer, Buffer *buffer,
DeviceMemory *deviceMemoryOut) DeviceMemory *deviceMemoryOut)
{ {
return AllocateBufferOrImageMemory(context, requestedMemoryPropertyFlags, return AllocateBufferOrImageMemory(context, requestedMemoryPropertyFlags,
memoryPropertyFlagsOut, buffer, deviceMemoryOut); memoryPropertyFlagsOut, extraAllocationInfo, buffer,
deviceMemoryOut);
} }
angle::Result AllocateImageMemory(vk::Context *context, angle::Result AllocateImageMemory(vk::Context *context,
VkMemoryPropertyFlags memoryPropertyFlags, VkMemoryPropertyFlags memoryPropertyFlags,
const void *extraAllocationInfo,
Image *image, Image *image,
DeviceMemory *deviceMemoryOut) DeviceMemory *deviceMemoryOut)
{ {
VkMemoryPropertyFlags memoryPropertyFlagsOut = 0; VkMemoryPropertyFlags memoryPropertyFlagsOut = 0;
return AllocateBufferOrImageMemory(context, memoryPropertyFlags, &memoryPropertyFlagsOut, image, return AllocateBufferOrImageMemory(context, memoryPropertyFlags, &memoryPropertyFlagsOut,
deviceMemoryOut); extraAllocationInfo, image, deviceMemoryOut);
}
angle::Result AllocateImageMemoryWithRequirements(vk::Context *context,
VkMemoryPropertyFlags memoryPropertyFlags,
const VkMemoryRequirements &memoryRequirements,
const void *extraAllocationInfo,
Image *image,
DeviceMemory *deviceMemoryOut)
{
VkMemoryPropertyFlags memoryPropertyFlagsOut = 0;
return AllocateAndBindBufferOrImageMemory(context, memoryPropertyFlags, &memoryPropertyFlagsOut,
memoryRequirements, extraAllocationInfo, image,
deviceMemoryOut);
} }
angle::Result InitShaderAndSerial(Context *context, angle::Result InitShaderAndSerial(Context *context,
...@@ -519,6 +554,17 @@ void InitImagePipeSurfaceFUCHSIAFunctions(VkInstance instance) ...@@ -519,6 +554,17 @@ void InitImagePipeSurfaceFUCHSIAFunctions(VkInstance instance)
} }
#endif #endif
#if defined(ANGLE_PLATFORM_ANDROID)
PFN_vkGetAndroidHardwareBufferPropertiesANDROID vkGetAndroidHardwareBufferPropertiesANDROID =
nullptr;
PFN_vkGetMemoryAndroidHardwareBufferANDROID vkGetMemoryAndroidHardwareBufferANDROID = nullptr;
void InitExternalMemoryHardwareBufferANDROIDFunctions(VkInstance instance)
{
GET_FUNC(vkGetAndroidHardwareBufferPropertiesANDROID);
GET_FUNC(vkGetMemoryAndroidHardwareBufferANDROID);
}
#endif
#undef GET_FUNC #undef GET_FUNC
namespace gl_vk namespace gl_vk
......
...@@ -259,13 +259,21 @@ class ObjectAndSerial final : angle::NonCopyable ...@@ -259,13 +259,21 @@ class ObjectAndSerial final : angle::NonCopyable
angle::Result AllocateBufferMemory(vk::Context *context, angle::Result AllocateBufferMemory(vk::Context *context,
VkMemoryPropertyFlags requestedMemoryPropertyFlags, VkMemoryPropertyFlags requestedMemoryPropertyFlags,
VkMemoryPropertyFlags *memoryPropertyFlagsOut, VkMemoryPropertyFlags *memoryPropertyFlagsOut,
const void *extraAllocationInfo,
Buffer *buffer, Buffer *buffer,
DeviceMemory *deviceMemoryOut); DeviceMemory *deviceMemoryOut);
angle::Result AllocateImageMemory(vk::Context *context, angle::Result AllocateImageMemory(vk::Context *context,
VkMemoryPropertyFlags memoryPropertyFlags, VkMemoryPropertyFlags memoryPropertyFlags,
const void *extraAllocationInfo,
Image *image, Image *image,
DeviceMemory *deviceMemoryOut); DeviceMemory *deviceMemoryOut);
angle::Result AllocateImageMemoryWithRequirements(vk::Context *context,
VkMemoryPropertyFlags memoryPropertyFlags,
const VkMemoryRequirements &memoryRequirements,
const void *extraAllocationInfo,
Image *image,
DeviceMemory *deviceMemoryOut);
using ShaderAndSerial = ObjectAndSerial<ShaderModule>; using ShaderAndSerial = ObjectAndSerial<ShaderModule>;
...@@ -401,6 +409,13 @@ extern PFN_vkCreateImagePipeSurfaceFUCHSIA vkCreateImagePipeSurfaceFUCHSIA; ...@@ -401,6 +409,13 @@ extern PFN_vkCreateImagePipeSurfaceFUCHSIA vkCreateImagePipeSurfaceFUCHSIA;
void InitImagePipeSurfaceFUCHSIAFunctions(VkInstance instance); void InitImagePipeSurfaceFUCHSIAFunctions(VkInstance instance);
#endif #endif
#if defined(ANGLE_PLATFORM_ANDROID)
// VK_ANDROID_external_memory_android_hardware_buffer
extern PFN_vkGetAndroidHardwareBufferPropertiesANDROID vkGetAndroidHardwareBufferPropertiesANDROID;
extern PFN_vkGetMemoryAndroidHardwareBufferANDROID vkGetMemoryAndroidHardwareBufferANDROID;
void InitExternalMemoryHardwareBufferANDROIDFunctions(VkInstance instance);
#endif
namespace gl_vk namespace gl_vk
{ {
VkRect2D GetRect(const gl::Rectangle &source); VkRect2D GetRect(const gl::Rectangle &source);
......
...@@ -84,6 +84,13 @@ if (is_win) { ...@@ -84,6 +84,13 @@ if (is_win) {
angle_system_utils_sources += [ "src/common/system_utils_win.cpp" ] angle_system_utils_sources += [ "src/common/system_utils_win.cpp" ]
} }
if (is_android) {
angle_system_utils_sources += [
"src/common/android_util.cpp",
"src/common/android_util.h",
]
}
libangle_image_util_sources = [ libangle_image_util_sources = [
"src/image_util/copyimage.cpp", "src/image_util/copyimage.cpp",
"src/image_util/copyimage.h", "src/image_util/copyimage.h",
...@@ -727,8 +734,6 @@ libangle_gl_ozone_sources = [ ...@@ -727,8 +734,6 @@ libangle_gl_ozone_sources = [
] ]
libangle_gl_egl_android_sources = [ libangle_gl_egl_android_sources = [
"src/libANGLE/renderer/gl/egl/android/android_util.cpp",
"src/libANGLE/renderer/gl/egl/android/android_util.h",
"src/libANGLE/renderer/gl/egl/android/DisplayAndroid.cpp", "src/libANGLE/renderer/gl/egl/android/DisplayAndroid.cpp",
"src/libANGLE/renderer/gl/egl/android/DisplayAndroid.h", "src/libANGLE/renderer/gl/egl/android/DisplayAndroid.h",
"src/libANGLE/renderer/gl/egl/android/NativeBufferImageSiblingAndroid.cpp", "src/libANGLE/renderer/gl/egl/android/NativeBufferImageSiblingAndroid.cpp",
...@@ -817,6 +822,8 @@ libangle_vulkan_sources = [ ...@@ -817,6 +822,8 @@ libangle_vulkan_sources = [
libangle_vulkan_android_sources = [ libangle_vulkan_android_sources = [
"src/libANGLE/renderer/vulkan/android/DisplayVkAndroid.cpp", "src/libANGLE/renderer/vulkan/android/DisplayVkAndroid.cpp",
"src/libANGLE/renderer/vulkan/android/DisplayVkAndroid.h", "src/libANGLE/renderer/vulkan/android/DisplayVkAndroid.h",
"src/libANGLE/renderer/vulkan/android/HardwareBufferImageSiblingVkAndroid.cpp",
"src/libANGLE/renderer/vulkan/android/HardwareBufferImageSiblingVkAndroid.h",
"src/libANGLE/renderer/vulkan/android/WindowSurfaceVkAndroid.cpp", "src/libANGLE/renderer/vulkan/android/WindowSurfaceVkAndroid.cpp",
"src/libANGLE/renderer/vulkan/android/WindowSurfaceVkAndroid.h", "src/libANGLE/renderer/vulkan/android/WindowSurfaceVkAndroid.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