зеркало из https://github.com/AvaloniaUI/angle.git
Vulkan: Support Linux dma-bufs
This change adds support for EGL_EXT_image_dma_buf_import and EGL_EXT_image_dma_buf_import_modifiers on top of Vulkan's VK_EXT_external_memory_dma_buf and VK_EXT_image_drm_format_modifier. Bug: angleproject:6248 Change-Id: I581987f88e9ddcf351dc721f499f63912dca05f9 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3145610 Reviewed-by: Jamie Madill <jmadill@chromium.org> Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
This commit is contained in:
Родитель
c85d9a19ff
Коммит
458389f249
|
@ -301,6 +301,15 @@ struct FeaturesVk : FeatureSetBase
|
|||
"VkDevice supports the VK_EXT_swapchain_colorspace extension", &members,
|
||||
"http://anglebug.com/2514"};
|
||||
|
||||
// Whether the VkDevice supports the VK_EXT_external_memory_dma_buf and
|
||||
// VK_EXT_image_drm_format_modifier extensions. These extensions are always used together to
|
||||
// implement EGL_EXT_image_dma_buf_import and EGL_EXT_image_dma_buf_import_modifiers.
|
||||
Feature supportsExternalMemoryDmaBufAndModifiers = {
|
||||
"supportsExternalMemoryDmaBufAndModifiers", FeatureCategory::VulkanFeatures,
|
||||
"VkDevice supports the VK_EXT_external_memory_dma_buf and VK_EXT_image_drm_format_modifier "
|
||||
"extensions",
|
||||
&members, "http://anglebug.com/6248"};
|
||||
|
||||
// Whether the VkDevice supports the VK_EXT_external_memory_host extension, on which the
|
||||
// ANGLE_iosurface_client_buffer extension can be layered.
|
||||
Feature supportsExternalMemoryHost = {
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
# 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.
|
||||
|
||||
import("../../../gni/angle.gni")
|
||||
|
||||
angle_source_set("angle_dma_buf") {
|
||||
sources = [
|
||||
"dma_buf_utils.cpp",
|
||||
"dma_buf_utils.h",
|
||||
]
|
||||
|
||||
deps = [ "$angle_root:angle_common" ]
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
// dma_buf_utils.cpp: Utilities to interact with Linux dma bufs.
|
||||
|
||||
#include "dma_buf_utils.h"
|
||||
|
||||
#include "common/debug.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <array>
|
||||
|
||||
// Refer to:
|
||||
// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/drm/drm_fourcc.h
|
||||
// https://source.chromium.org/chromium/chromium/src/+/main:ui/gl/gl_image_native_pixmap.cc;l=24
|
||||
#define FOURCC(a, b, c, d) \
|
||||
((static_cast<uint32_t>(a)) | (static_cast<uint32_t>(b) << 8) | \
|
||||
(static_cast<uint32_t>(c) << 16) | (static_cast<uint32_t>(d) << 24))
|
||||
|
||||
#define DRM_FORMAT_R8 FOURCC('R', '8', ' ', ' ')
|
||||
#define DRM_FORMAT_R16 FOURCC('R', '1', '6', ' ')
|
||||
#define DRM_FORMAT_GR88 FOURCC('G', 'R', '8', '8')
|
||||
#define DRM_FORMAT_RGB565 FOURCC('R', 'G', '1', '6')
|
||||
#define DRM_FORMAT_ARGB8888 FOURCC('A', 'R', '2', '4')
|
||||
#define DRM_FORMAT_ABGR8888 FOURCC('A', 'B', '2', '4')
|
||||
#define DRM_FORMAT_XRGB8888 FOURCC('X', 'R', '2', '4')
|
||||
#define DRM_FORMAT_XBGR8888 FOURCC('X', 'B', '2', '4')
|
||||
#define DRM_FORMAT_ABGR2101010 FOURCC('A', 'B', '3', '0')
|
||||
#define DRM_FORMAT_ARGB2101010 FOURCC('A', 'R', '3', '0')
|
||||
#define DRM_FORMAT_YVU420 FOURCC('Y', 'V', '1', '2')
|
||||
#define DRM_FORMAT_NV12 FOURCC('N', 'V', '1', '2')
|
||||
#define DRM_FORMAT_P010 FOURCC('P', '0', '1', '0')
|
||||
|
||||
namespace angle
|
||||
{
|
||||
GLenum DrmFourCCFormatToGLInternalFormat(int fourccFormat, bool *isYUV)
|
||||
{
|
||||
*isYUV = false;
|
||||
|
||||
switch (fourccFormat)
|
||||
{
|
||||
case DRM_FORMAT_R8:
|
||||
return GL_R8;
|
||||
case DRM_FORMAT_R16:
|
||||
return GL_R16_EXT;
|
||||
case DRM_FORMAT_GR88:
|
||||
return GL_RG8_EXT;
|
||||
case DRM_FORMAT_ABGR8888:
|
||||
return GL_RGBA8;
|
||||
case DRM_FORMAT_XBGR8888:
|
||||
return GL_RGB8;
|
||||
case DRM_FORMAT_ARGB8888:
|
||||
return GL_BGRA8_EXT;
|
||||
case DRM_FORMAT_XRGB8888:
|
||||
return GL_RGB8;
|
||||
case DRM_FORMAT_ABGR2101010:
|
||||
case DRM_FORMAT_ARGB2101010:
|
||||
return GL_RGB10_A2_EXT;
|
||||
case DRM_FORMAT_RGB565:
|
||||
return GL_RGB565;
|
||||
case DRM_FORMAT_NV12:
|
||||
case DRM_FORMAT_YVU420:
|
||||
case DRM_FORMAT_P010:
|
||||
*isYUV = true;
|
||||
return GL_RGB8;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
WARN() << "Unknown dma_buf format " << fourccFormat
|
||||
<< " used to initialize an EGL image.";
|
||||
return GL_RGB8;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace angle
|
|
@ -0,0 +1,19 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
// dma_buf_utils.h: Utilities to interact with Linux dma bufs.
|
||||
|
||||
#ifndef COMMON_LINUX_DMA_BUF_UTILS_H_
|
||||
#define COMMON_LINUX_DMA_BUF_UTILS_H_
|
||||
|
||||
#include <angle_gl.h>
|
||||
|
||||
namespace angle
|
||||
{
|
||||
GLenum DrmFourCCFormatToGLInternalFormat(int format, bool *isYUV);
|
||||
} // namespace angle
|
||||
|
||||
#endif // COMMON_LINUX_DMA_BUF_UTILS_H_
|
|
@ -369,7 +369,7 @@ CheckedUnsignedAbs(T value)
|
|||
typename std::enable_if<std::numeric_limits<T>::is_iec559, T>::type Checked##NAME( \
|
||||
T, T, RangeConstraint *) \
|
||||
{ \
|
||||
NOTREACHED(); \
|
||||
UNREACHABLE(); \
|
||||
return static_cast<T>(0); \
|
||||
}
|
||||
|
||||
|
@ -496,7 +496,7 @@ class CheckedNumericState<T, NUMERIC_FLOATING>
|
|||
break;
|
||||
|
||||
default:
|
||||
NOTREACHED();
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -264,6 +264,9 @@ angle_source_set("angle_gl_backend") {
|
|||
"Xext",
|
||||
]
|
||||
}
|
||||
if (is_android || is_linux || is_chromeos) {
|
||||
deps += [ "$angle_root/src/common/linux:angle_dma_buf" ]
|
||||
}
|
||||
if (is_apple) {
|
||||
frameworks = [
|
||||
"IOSurface.framework",
|
||||
|
|
|
@ -9,67 +9,7 @@
|
|||
|
||||
#include "libANGLE/renderer/gl/egl/DmaBufImageSiblingEGL.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// Refer to the following link
|
||||
// https://source.chromium.org/chromium/chromium/src/+/main:ui/gl/gl_image_native_pixmap.cc;l=24
|
||||
#define FOURCC(a, b, c, d) \
|
||||
((static_cast<uint32_t>(a)) | (static_cast<uint32_t>(b) << 8) | \
|
||||
(static_cast<uint32_t>(c) << 16) | (static_cast<uint32_t>(d) << 24))
|
||||
|
||||
#define DRM_FORMAT_R8 FOURCC('R', '8', ' ', ' ')
|
||||
#define DRM_FORMAT_R16 FOURCC('R', '1', '6', ' ')
|
||||
#define DRM_FORMAT_GR88 FOURCC('G', 'R', '8', '8')
|
||||
#define DRM_FORMAT_RGB565 FOURCC('R', 'G', '1', '6')
|
||||
#define DRM_FORMAT_ARGB8888 FOURCC('A', 'R', '2', '4')
|
||||
#define DRM_FORMAT_ABGR8888 FOURCC('A', 'B', '2', '4')
|
||||
#define DRM_FORMAT_XRGB8888 FOURCC('X', 'R', '2', '4')
|
||||
#define DRM_FORMAT_XBGR8888 FOURCC('X', 'B', '2', '4')
|
||||
#define DRM_FORMAT_ABGR2101010 FOURCC('A', 'B', '3', '0')
|
||||
#define DRM_FORMAT_ARGB2101010 FOURCC('A', 'R', '3', '0')
|
||||
#define DRM_FORMAT_YVU420 FOURCC('Y', 'V', '1', '2')
|
||||
#define DRM_FORMAT_NV12 FOURCC('N', 'V', '1', '2')
|
||||
#define DRM_FORMAT_P010 FOURCC('P', '0', '1', '0')
|
||||
|
||||
GLenum FourCCFormatToGLInternalFormat(int format, bool *isYUV)
|
||||
{
|
||||
*isYUV = false;
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case DRM_FORMAT_R8:
|
||||
return GL_R8;
|
||||
case DRM_FORMAT_R16:
|
||||
return GL_R16_EXT;
|
||||
case DRM_FORMAT_GR88:
|
||||
return GL_RG8_EXT;
|
||||
case DRM_FORMAT_ABGR8888:
|
||||
return GL_RGBA8;
|
||||
case DRM_FORMAT_XBGR8888:
|
||||
return GL_RGB8;
|
||||
case DRM_FORMAT_ARGB8888:
|
||||
return GL_BGRA8_EXT;
|
||||
case DRM_FORMAT_XRGB8888:
|
||||
return GL_RGB8;
|
||||
case DRM_FORMAT_ABGR2101010:
|
||||
case DRM_FORMAT_ARGB2101010:
|
||||
return GL_RGB10_A2_EXT;
|
||||
case DRM_FORMAT_RGB565:
|
||||
return GL_RGB565;
|
||||
case DRM_FORMAT_NV12:
|
||||
case DRM_FORMAT_YVU420:
|
||||
case DRM_FORMAT_P010:
|
||||
*isYUV = true;
|
||||
return GL_RGB8;
|
||||
default:
|
||||
NOTREACHED();
|
||||
WARN() << "Unknown dma_buf format " << format << " used to initialize an EGL image.";
|
||||
return GL_RGB8;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
#include "common/linux/dma_buf_utils.h"
|
||||
|
||||
namespace rx
|
||||
{
|
||||
|
@ -84,7 +24,7 @@ DmaBufImageSiblingEGL::DmaBufImageSiblingEGL(const egl::AttributeMap &attribs)
|
|||
mHasProtectedContent = false;
|
||||
|
||||
int fourCCFormat = mAttribs.getAsInt(EGL_LINUX_DRM_FOURCC_EXT);
|
||||
mFormat = gl::Format(FourCCFormatToGLInternalFormat(fourCCFormat, &mYUV));
|
||||
mFormat = gl::Format(angle::DrmFourCCFormatToGLInternalFormat(fourCCFormat, &mYUV));
|
||||
}
|
||||
|
||||
DmaBufImageSiblingEGL::~DmaBufImageSiblingEGL() {}
|
||||
|
|
|
@ -138,14 +138,18 @@ if (angle_use_vulkan_null_display) {
|
|||
|
||||
if (is_linux) {
|
||||
_vulkan_backend_sources += [
|
||||
"display/DisplayVkSimple.cpp",
|
||||
"display/DisplayVkSimple.h",
|
||||
"display/WindowSurfaceVkSimple.cpp",
|
||||
"display/WindowSurfaceVkSimple.h",
|
||||
"headless/DisplayVkHeadless.cpp",
|
||||
"headless/DisplayVkHeadless.h",
|
||||
"headless/WindowSurfaceVkHeadless.cpp",
|
||||
"headless/WindowSurfaceVkHeadless.h",
|
||||
"linux/DisplayVkLinux.cpp",
|
||||
"linux/DisplayVkLinux.h",
|
||||
"linux/DmaBufImageSiblingVkLinux.cpp",
|
||||
"linux/DmaBufImageSiblingVkLinux.h",
|
||||
"linux/display/DisplayVkSimple.cpp",
|
||||
"linux/display/DisplayVkSimple.h",
|
||||
"linux/display/WindowSurfaceVkSimple.cpp",
|
||||
"linux/display/WindowSurfaceVkSimple.h",
|
||||
"linux/headless/DisplayVkHeadless.cpp",
|
||||
"linux/headless/DisplayVkHeadless.h",
|
||||
"linux/headless/WindowSurfaceVkHeadless.cpp",
|
||||
"linux/headless/WindowSurfaceVkHeadless.h",
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -173,10 +177,10 @@ if (is_win) {
|
|||
|
||||
if (angle_use_x11) {
|
||||
_vulkan_backend_sources += [
|
||||
"xcb/DisplayVkXcb.cpp",
|
||||
"xcb/DisplayVkXcb.h",
|
||||
"xcb/WindowSurfaceVkXcb.cpp",
|
||||
"xcb/WindowSurfaceVkXcb.h",
|
||||
"linux/xcb/DisplayVkXcb.cpp",
|
||||
"linux/xcb/DisplayVkXcb.h",
|
||||
"linux/xcb/WindowSurfaceVkXcb.cpp",
|
||||
"linux/xcb/WindowSurfaceVkXcb.h",
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -277,6 +281,10 @@ angle_source_set("angle_vulkan_backend") {
|
|||
data_deps += [ "$angle_root/src/common/vulkan:vulkan_validation_layers" ]
|
||||
}
|
||||
|
||||
if (is_linux) {
|
||||
deps += [ "$angle_root/src/common/linux:angle_dma_buf" ]
|
||||
}
|
||||
|
||||
if (is_fuchsia) {
|
||||
public_deps += [ "$angle_root/src/common/fuchsia_egl:backend" ]
|
||||
}
|
||||
|
|
|
@ -230,6 +230,14 @@ void DisplayVk::generateExtensions(egl::DisplayExtensions *outExtensions) const
|
|||
outExtensions->framebufferTargetANDROID = true;
|
||||
#endif // defined(ANGLE_PLATFORM_ANDROID)
|
||||
|
||||
// EGL_EXT_image_dma_buf_import is only exposed if EGL_EXT_image_dma_buf_import_modifiers can
|
||||
// also be exposed. The Vulkan extensions that support these EGL extensions are not split in
|
||||
// the same way; both Vulkan extensions are needed for EGL_EXT_image_dma_buf_import, and with
|
||||
// both Vulkan extensions, EGL_EXT_image_dma_buf_import_modifiers is also supportable.
|
||||
outExtensions->imageDmaBufImportEXT =
|
||||
getRenderer()->getFeatures().supportsExternalMemoryDmaBufAndModifiers.enabled;
|
||||
outExtensions->imageDmaBufImportModifiersEXT = outExtensions->imageDmaBufImportEXT;
|
||||
|
||||
// Disable context priority when non-zero memory init is enabled. This enforces a queue order.
|
||||
outExtensions->contextPriority = !getRenderer()->getFeatures().allocateNonZeroMemory.enabled;
|
||||
outExtensions->noConfigContext = true;
|
||||
|
|
|
@ -221,7 +221,7 @@ angle::Result MemoryObjectVk::createImage(ContextVk *contextVk,
|
|||
VkMemoryRequirements externalMemoryRequirements;
|
||||
image->getImage().getMemoryRequirements(renderer->getDevice(), &externalMemoryRequirements);
|
||||
|
||||
void *importMemoryInfo = nullptr;
|
||||
const void *importMemoryInfo = nullptr;
|
||||
VkMemoryDedicatedAllocateInfo memoryDedicatedAllocateInfo = {};
|
||||
if (mDedicatedMemory)
|
||||
{
|
||||
|
@ -262,7 +262,7 @@ angle::Result MemoryObjectVk::createImage(ContextVk *contextVk,
|
|||
|
||||
VkMemoryPropertyFlags flags = hasProtectedContent ? VK_MEMORY_PROPERTY_PROTECTED_BIT : 0;
|
||||
ANGLE_TRY(image->initExternalMemory(contextVk, renderer->getMemoryProperties(),
|
||||
externalMemoryRequirements, nullptr, importMemoryInfo,
|
||||
externalMemoryRequirements, nullptr, 1, &importMemoryInfo,
|
||||
renderer->getQueueFamilyIndex(), flags));
|
||||
|
||||
return angle::Result::Continue;
|
||||
|
|
|
@ -1819,6 +1819,12 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
|
|||
}
|
||||
}
|
||||
|
||||
if (getFeatures().supportsExternalMemoryDmaBufAndModifiers.enabled)
|
||||
{
|
||||
enabledDeviceExtensions.push_back(VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME);
|
||||
enabledDeviceExtensions.push_back(VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
if (getFeatures().supportsExternalMemoryHost.enabled)
|
||||
{
|
||||
enabledDeviceExtensions.push_back(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME);
|
||||
|
@ -2428,6 +2434,11 @@ void RendererVk::initFeatures(DisplayVk *displayVk,
|
|||
ANGLE_FEATURE_CONDITION(&mFeatures, logMemoryReportCallbacks, false);
|
||||
ANGLE_FEATURE_CONDITION(&mFeatures, logMemoryReportStats, false);
|
||||
|
||||
ANGLE_FEATURE_CONDITION(
|
||||
&mFeatures, supportsExternalMemoryDmaBufAndModifiers,
|
||||
ExtensionFound(VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME, deviceExtensionNames) &&
|
||||
ExtensionFound(VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME, deviceExtensionNames));
|
||||
|
||||
ANGLE_FEATURE_CONDITION(
|
||||
&mFeatures, supportsExternalMemoryHost,
|
||||
ExtensionFound(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME, deviceExtensionNames));
|
||||
|
|
|
@ -235,7 +235,8 @@ angle::Result OffscreenSurfaceVk::AttachmentImage::initializeWithExternalMemory(
|
|||
importMemoryHostPointerInfo.pNext = nullptr;
|
||||
importMemoryHostPointerInfo.handleType =
|
||||
VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT;
|
||||
importMemoryHostPointerInfo.pHostPointer = buffer;
|
||||
importMemoryHostPointerInfo.pHostPointer = buffer;
|
||||
const void *importMemoryHostPointerInfoPtr = &importMemoryHostPointerInfo;
|
||||
|
||||
VkMemoryRequirements externalMemoryRequirements;
|
||||
image.getImage().getMemoryRequirements(renderer->getDevice(), &externalMemoryRequirements);
|
||||
|
@ -246,8 +247,8 @@ angle::Result OffscreenSurfaceVk::AttachmentImage::initializeWithExternalMemory(
|
|||
flags |= VK_MEMORY_PROPERTY_PROTECTED_BIT;
|
||||
}
|
||||
ANGLE_TRY(image.initExternalMemory(
|
||||
displayVk, renderer->getMemoryProperties(), externalMemoryRequirements, nullptr,
|
||||
&importMemoryHostPointerInfo, VK_QUEUE_FAMILY_EXTERNAL, flags));
|
||||
displayVk, renderer->getMemoryProperties(), externalMemoryRequirements, nullptr, 1,
|
||||
&importMemoryHostPointerInfoPtr, VK_QUEUE_FAMILY_EXTERNAL, flags));
|
||||
|
||||
imageViews.init(renderer);
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ VkImageTiling AhbDescUsageToVkImageTiling(const AHardwareBuffer_Desc &ahbDescrip
|
|||
//
|
||||
// Also, as an aside, in terms of what's generally expected from the Vulkan
|
||||
// ICD in Android when determining AHB compatibility, if the vendor wants
|
||||
// to declare a particular combinatino of format/tiling/usage/etc as not
|
||||
// to declare a particular combination of format/tiling/usage/etc as not
|
||||
// supported AHB-wise, it's up to the ICD vendor to zero out bits in
|
||||
// supportedHandleTypes in the vkGetPhysicalDeviceImageFormatProperties2
|
||||
// query:
|
||||
|
@ -72,6 +72,38 @@ VkImageTiling AhbDescUsageToVkImageTiling(const AHardwareBuffer_Desc &ahbDescrip
|
|||
|
||||
return VK_IMAGE_TILING_OPTIMAL;
|
||||
}
|
||||
|
||||
// Map AHB usage flags to VkImageUsageFlags using this table from the Vulkan spec
|
||||
// https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/chap10.html#memory-external-android-hardware-buffer-usage
|
||||
VkImageUsageFlags AhbDescUsageToVkImageUsage(const AHardwareBuffer_Desc &ahbDescription,
|
||||
bool isDepthOrStencilFormat)
|
||||
{
|
||||
VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||
|
||||
if ((ahbDescription.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE) != 0)
|
||||
{
|
||||
usage |= VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
|
||||
}
|
||||
|
||||
if ((ahbDescription.usage & AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER) != 0)
|
||||
{
|
||||
if (isDepthOrStencilFormat)
|
||||
{
|
||||
usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ahbDescription.usage & AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP) != 0)
|
||||
{
|
||||
usage |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
|
||||
}
|
||||
|
||||
return usage;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
HardwareBufferImageSiblingVkAndroid::HardwareBufferImageSiblingVkAndroid(EGLClientBuffer buffer)
|
||||
|
@ -161,43 +193,6 @@ egl::Error HardwareBufferImageSiblingVkAndroid::initialize(const egl::Display *d
|
|||
return angle::ToEGL(initImpl(displayVk), displayVk, EGL_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
// Map AHB usage flags to VkImageUsageFlags using this table from the Vulkan spec
|
||||
// https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/chap10.html#memory-external-android-hardware-buffer-usage
|
||||
VkImageUsageFlags AhbDescUsageToVkImageUsage(const AHardwareBuffer_Desc &ahbDescription,
|
||||
bool isDepthOrStencilFormat)
|
||||
{
|
||||
VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||
|
||||
if ((ahbDescription.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE) != 0)
|
||||
{
|
||||
usage |= VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
|
||||
}
|
||||
|
||||
if ((ahbDescription.usage & AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER) != 0)
|
||||
{
|
||||
if (isDepthOrStencilFormat)
|
||||
{
|
||||
usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ahbDescription.usage & AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP) != 0)
|
||||
{
|
||||
usage |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
|
||||
}
|
||||
|
||||
if ((ahbDescription.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT) != 0)
|
||||
{
|
||||
usage |= VK_IMAGE_CREATE_PROTECTED_BIT;
|
||||
}
|
||||
|
||||
return usage;
|
||||
}
|
||||
|
||||
angle::Result HardwareBufferImageSiblingVkAndroid::initImpl(DisplayVk *displayVk)
|
||||
{
|
||||
const AHBFunctions &functions = static_cast<DisplayVkAndroid *>(displayVk)->getAHBFunctions();
|
||||
|
@ -296,18 +291,23 @@ angle::Result HardwareBufferImageSiblingVkAndroid::initImpl(DisplayVk *displayVk
|
|||
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;
|
||||
dedicatedAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
|
||||
dedicatedAllocInfo.pNext = &importHardwareBufferInfo;
|
||||
dedicatedAllocInfo.image = mImage->getImage().getHandle();
|
||||
dedicatedAllocInfo.buffer = VK_NULL_HANDLE;
|
||||
const void *dedicatedAllocInfoPtr = &dedicatedAllocInfo;
|
||||
|
||||
VkMemoryRequirements externalMemoryRequirements = {};
|
||||
externalMemoryRequirements.size = bufferProperties.allocationSize;
|
||||
externalMemoryRequirements.alignment = 0;
|
||||
externalMemoryRequirements.memoryTypeBits = bufferProperties.memoryTypeBits;
|
||||
|
||||
VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
|
||||
(hasProtectedContent() ? VK_MEMORY_PROPERTY_PROTECTED_BIT : 0);
|
||||
const VkMemoryPropertyFlags flags =
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
|
||||
(hasProtectedContent() ? VK_MEMORY_PROPERTY_PROTECTED_BIT : 0);
|
||||
|
||||
VkSamplerYcbcrConversionCreateInfo yuvConversionInfo = {};
|
||||
VkSamplerYcbcrConversionCreateInfo *yuvConversionInfoPtr = nullptr;
|
||||
if (bufferFormatProperties.format == VK_FORMAT_UNDEFINED)
|
||||
{
|
||||
// Note from Vulkan spec: Since GL_OES_EGL_image_external does not require the same sampling
|
||||
|
@ -316,7 +316,7 @@ angle::Result HardwareBufferImageSiblingVkAndroid::initImpl(DisplayVk *displayVk
|
|||
ANGLE_VK_CHECK(displayVk, renderer->getFeatures().supportsYUVSamplerConversion.enabled,
|
||||
VK_ERROR_FEATURE_NOT_PRESENT);
|
||||
ASSERT(externalFormat.pNext == nullptr);
|
||||
VkSamplerYcbcrConversionCreateInfo yuvConversionInfo = {};
|
||||
|
||||
yuvConversionInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO;
|
||||
yuvConversionInfo.pNext = &externalFormat;
|
||||
yuvConversionInfo.format = VK_FORMAT_UNDEFINED;
|
||||
|
@ -327,18 +327,14 @@ angle::Result HardwareBufferImageSiblingVkAndroid::initImpl(DisplayVk *displayVk
|
|||
yuvConversionInfo.chromaFilter = VK_FILTER_NEAREST;
|
||||
yuvConversionInfo.components = bufferFormatProperties.samplerYcbcrConversionComponents;
|
||||
|
||||
ANGLE_TRY(mImage->initExternalMemory(
|
||||
displayVk, renderer->getMemoryProperties(), externalMemoryRequirements,
|
||||
&yuvConversionInfo, &dedicatedAllocInfo, VK_QUEUE_FAMILY_FOREIGN_EXT, flags));
|
||||
yuvConversionInfoPtr = &yuvConversionInfo;
|
||||
|
||||
mYUV = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ANGLE_TRY(mImage->initExternalMemory(
|
||||
displayVk, renderer->getMemoryProperties(), externalMemoryRequirements, nullptr,
|
||||
&dedicatedAllocInfo, VK_QUEUE_FAMILY_FOREIGN_EXT, flags));
|
||||
}
|
||||
|
||||
ANGLE_TRY(mImage->initExternalMemory(
|
||||
displayVk, renderer->getMemoryProperties(), externalMemoryRequirements,
|
||||
yuvConversionInfoPtr, 1, &dedicatedAllocInfoPtr, 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;
|
||||
|
@ -411,8 +407,8 @@ void HardwareBufferImageSiblingVkAndroid::release(RendererVk *renderer)
|
|||
{
|
||||
if (mImage != nullptr)
|
||||
{
|
||||
// TODO: We need to handle the case that EGLImage used in two context that aren't shared.
|
||||
// https://issuetracker.google.com/169868803
|
||||
// TODO: Handle the case where the EGLImage is used in two contexts not in the same share
|
||||
// group. https://issuetracker.google.com/169868803
|
||||
mImage->releaseImage(renderer);
|
||||
mImage->releaseStagingBuffer(renderer);
|
||||
SafeDelete(mImage);
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
// DisplayVkLinux.cpp:
|
||||
// Implements the class methods for DisplayVkLinux.
|
||||
//
|
||||
|
||||
#include "libANGLE/renderer/vulkan/linux/DisplayVkLinux.h"
|
||||
|
||||
#include "libANGLE/renderer/vulkan/RendererVk.h"
|
||||
#include "libANGLE/renderer/vulkan/linux/DmaBufImageSiblingVkLinux.h"
|
||||
|
||||
namespace rx
|
||||
{
|
||||
|
||||
DisplayVkLinux::DisplayVkLinux(const egl::DisplayState &state) : DisplayVk(state) {}
|
||||
|
||||
ExternalImageSiblingImpl *DisplayVkLinux::createExternalImageSibling(
|
||||
const gl::Context *context,
|
||||
EGLenum target,
|
||||
EGLClientBuffer buffer,
|
||||
const egl::AttributeMap &attribs)
|
||||
{
|
||||
switch (target)
|
||||
{
|
||||
case EGL_LINUX_DMA_BUF_EXT:
|
||||
ASSERT(context == nullptr);
|
||||
ASSERT(buffer == nullptr);
|
||||
return new DmaBufImageSiblingVkLinux(attribs);
|
||||
|
||||
default:
|
||||
return DisplayVk::createExternalImageSibling(context, target, buffer, attribs);
|
||||
}
|
||||
}
|
||||
} // namespace rx
|
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
// DisplayVkLinux.h:
|
||||
// Defines the class interface for DisplayVkLinux, which is the base of DisplayVkSimple,
|
||||
// DisplayVkHeadless and DisplayVkXcb. This base class implements the common functionality of
|
||||
// handling Linux dma-bufs.
|
||||
//
|
||||
|
||||
#ifndef LIBANGLE_RENDERER_VULKAN_DISPLAY_DISPLAYVKLINUX_H_
|
||||
#define LIBANGLE_RENDERER_VULKAN_DISPLAY_DISPLAYVKLINUX_H_
|
||||
|
||||
#include "libANGLE/renderer/vulkan/DisplayVk.h"
|
||||
|
||||
namespace rx
|
||||
{
|
||||
class DisplayVkLinux : public DisplayVk
|
||||
{
|
||||
public:
|
||||
DisplayVkLinux(const egl::DisplayState &state);
|
||||
|
||||
ExternalImageSiblingImpl *createExternalImageSibling(const gl::Context *context,
|
||||
EGLenum target,
|
||||
EGLClientBuffer buffer,
|
||||
const egl::AttributeMap &attribs) override;
|
||||
};
|
||||
|
||||
} // namespace rx
|
||||
|
||||
#endif // LIBANGLE_RENDERER_VULKAN_DISPLAY_DISPLAYVKLINUX_H_
|
|
@ -0,0 +1,558 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
// DmaBufImageSiblingVkLinux.cpp: Implements DmaBufImageSiblingVkLinux.
|
||||
|
||||
#include "libANGLE/renderer/vulkan/linux/DmaBufImageSiblingVkLinux.h"
|
||||
|
||||
#include "common/linux/dma_buf_utils.h"
|
||||
#include "libANGLE/Display.h"
|
||||
#include "libANGLE/renderer/vulkan/DisplayVk.h"
|
||||
#include "libANGLE/renderer/vulkan/RendererVk.h"
|
||||
|
||||
namespace rx
|
||||
{
|
||||
namespace
|
||||
{
|
||||
constexpr uint32_t kMaxPlaneCount = 4;
|
||||
template <typename T>
|
||||
using PerPlane = std::array<T, kMaxPlaneCount>;
|
||||
|
||||
constexpr PerPlane<EGLenum> kFds = {EGL_DMA_BUF_PLANE0_FD_EXT, EGL_DMA_BUF_PLANE1_FD_EXT,
|
||||
EGL_DMA_BUF_PLANE2_FD_EXT, EGL_DMA_BUF_PLANE3_FD_EXT};
|
||||
|
||||
constexpr PerPlane<EGLenum> kOffsets = {
|
||||
EGL_DMA_BUF_PLANE0_OFFSET_EXT, EGL_DMA_BUF_PLANE1_OFFSET_EXT, EGL_DMA_BUF_PLANE2_OFFSET_EXT,
|
||||
EGL_DMA_BUF_PLANE3_OFFSET_EXT};
|
||||
|
||||
constexpr PerPlane<EGLenum> kPitches = {EGL_DMA_BUF_PLANE0_PITCH_EXT, EGL_DMA_BUF_PLANE1_PITCH_EXT,
|
||||
EGL_DMA_BUF_PLANE2_PITCH_EXT, EGL_DMA_BUF_PLANE3_PITCH_EXT};
|
||||
|
||||
constexpr PerPlane<EGLenum> kModifiersLo = {
|
||||
EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT, EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT,
|
||||
EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT, EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT};
|
||||
|
||||
constexpr PerPlane<EGLenum> kModifiersHi = {
|
||||
EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT,
|
||||
EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT, EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT};
|
||||
|
||||
constexpr VkImageUsageFlags kTransferUsage =
|
||||
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||
constexpr VkImageUsageFlags kTextureUsage =
|
||||
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
|
||||
constexpr VkImageUsageFlags kRenderUsage =
|
||||
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
|
||||
struct AllocateInfo
|
||||
{
|
||||
PerPlane<VkMemoryDedicatedAllocateInfo> allocateInfo = {};
|
||||
PerPlane<VkImportMemoryFdInfoKHR> importFdInfo = {};
|
||||
|
||||
PerPlane<const void *> allocateInfoPtr = {};
|
||||
};
|
||||
|
||||
// Look at provided fds and count the number of planes based on that.
|
||||
uint32_t GetPlaneCount(const egl::AttributeMap &attribs)
|
||||
{
|
||||
// There should always be at least one plane.
|
||||
ASSERT(attribs.contains(kFds[0]));
|
||||
ASSERT(attribs.contains(kOffsets[0]));
|
||||
ASSERT(attribs.contains(kPitches[0]));
|
||||
|
||||
for (uint32_t plane = 1; plane < kMaxPlaneCount; ++plane)
|
||||
{
|
||||
if (!attribs.contains(kFds[plane]))
|
||||
{
|
||||
return plane;
|
||||
}
|
||||
|
||||
ASSERT(attribs.contains(kOffsets[plane]));
|
||||
ASSERT(attribs.contains(kPitches[plane]));
|
||||
}
|
||||
|
||||
return kMaxPlaneCount;
|
||||
}
|
||||
|
||||
uint64_t GetModifier(const egl::AttributeMap &attribs, EGLenum lo, EGLenum hi)
|
||||
{
|
||||
if (!attribs.contains(lo))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
ASSERT(attribs.contains(hi));
|
||||
|
||||
uint64_t modifier = attribs.getAsInt(hi);
|
||||
modifier = modifier << 32 | attribs.getAsInt(lo);
|
||||
|
||||
return modifier;
|
||||
}
|
||||
|
||||
void GetModifiers(const egl::AttributeMap &attribs,
|
||||
uint32_t planeCount,
|
||||
PerPlane<uint64_t> *drmModifiersOut)
|
||||
{
|
||||
for (uint32_t plane = 0; plane < planeCount; ++plane)
|
||||
{
|
||||
(*drmModifiersOut)[plane] = GetModifier(attribs, kModifiersLo[plane], kModifiersHi[plane]);
|
||||
}
|
||||
}
|
||||
|
||||
angle::Result GetFormatModifierProperties(DisplayVk *displayVk,
|
||||
VkFormat vkFormat,
|
||||
uint64_t drmModifier,
|
||||
VkDrmFormatModifierPropertiesEXT *modifierPropertiesOut)
|
||||
{
|
||||
RendererVk *renderer = displayVk->getRenderer();
|
||||
|
||||
// Query list of drm format modifiers compatible with VkFormat.
|
||||
VkDrmFormatModifierPropertiesListEXT formatModifierPropertiesList = {};
|
||||
formatModifierPropertiesList.sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT;
|
||||
formatModifierPropertiesList.drmFormatModifierCount = 0;
|
||||
|
||||
VkFormatProperties2 formatProperties = {};
|
||||
formatProperties.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2;
|
||||
formatProperties.pNext = &formatModifierPropertiesList;
|
||||
|
||||
vkGetPhysicalDeviceFormatProperties2(renderer->getPhysicalDevice(), vkFormat,
|
||||
&formatProperties);
|
||||
|
||||
std::vector<VkDrmFormatModifierPropertiesEXT> formatModifierProperties(
|
||||
formatModifierPropertiesList.drmFormatModifierCount);
|
||||
formatModifierPropertiesList.pDrmFormatModifierProperties = formatModifierProperties.data();
|
||||
|
||||
vkGetPhysicalDeviceFormatProperties2(renderer->getPhysicalDevice(), vkFormat,
|
||||
&formatProperties);
|
||||
|
||||
// Find the requested DRM modifiers.
|
||||
uint32_t propertiesIndex = formatModifierPropertiesList.drmFormatModifierCount;
|
||||
for (uint32_t index = 0; index < formatModifierPropertiesList.drmFormatModifierCount; ++index)
|
||||
{
|
||||
if (formatModifierPropertiesList.pDrmFormatModifierProperties[index].drmFormatModifier ==
|
||||
drmModifier)
|
||||
{
|
||||
propertiesIndex = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the properties if found.
|
||||
ANGLE_VK_CHECK(displayVk, propertiesIndex < formatModifierPropertiesList.drmFormatModifierCount,
|
||||
VK_ERROR_FORMAT_NOT_SUPPORTED);
|
||||
|
||||
*modifierPropertiesOut =
|
||||
formatModifierPropertiesList.pDrmFormatModifierProperties[propertiesIndex];
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
VkImageUsageFlags GetUsageFlags(RendererVk *renderer,
|
||||
const angle::Format &format,
|
||||
const VkDrmFormatModifierPropertiesEXT &properties,
|
||||
bool *texturableOut,
|
||||
bool *renderableOut)
|
||||
{
|
||||
const bool isDepthStencilFormat = format.depthBits > 0 || format.stencilBits > 0;
|
||||
|
||||
// Check what format features are exposed for this modifier.
|
||||
constexpr uint32_t kTextureableRequiredBits =
|
||||
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
|
||||
constexpr uint32_t kColorRenderableRequiredBits = VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
|
||||
constexpr uint32_t kDepthStencilRenderableRequiredBits =
|
||||
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||
|
||||
*texturableOut =
|
||||
IsMaskFlagSet(properties.drmFormatModifierTilingFeatures, kTextureableRequiredBits);
|
||||
*renderableOut = IsMaskFlagSet(
|
||||
properties.drmFormatModifierTilingFeatures,
|
||||
isDepthStencilFormat ? kDepthStencilRenderableRequiredBits : kColorRenderableRequiredBits);
|
||||
|
||||
VkImageUsageFlags usage = kTransferUsage;
|
||||
if (*texturableOut)
|
||||
{
|
||||
usage |= kTextureUsage;
|
||||
}
|
||||
if (*renderableOut)
|
||||
{
|
||||
usage |= isDepthStencilFormat ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
|
||||
: VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
}
|
||||
|
||||
return usage;
|
||||
}
|
||||
|
||||
bool IsFormatSupported(RendererVk *renderer,
|
||||
VkFormat vkFormat,
|
||||
uint64_t drmModifier,
|
||||
VkImageUsageFlags usageFlags,
|
||||
VkImageCreateFlags createFlags,
|
||||
VkImageFormatProperties2 *imageFormatPropertiesOut)
|
||||
{
|
||||
VkExternalMemoryImageCreateInfo externalMemoryImageCreateInfo = {};
|
||||
externalMemoryImageCreateInfo.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO;
|
||||
externalMemoryImageCreateInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
|
||||
|
||||
VkPhysicalDeviceImageFormatInfo2 imageFormatInfo = {};
|
||||
imageFormatInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2;
|
||||
imageFormatInfo.pNext = &externalMemoryImageCreateInfo;
|
||||
imageFormatInfo.format = vkFormat;
|
||||
imageFormatInfo.type = VK_IMAGE_TYPE_2D;
|
||||
imageFormatInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
imageFormatInfo.usage = usageFlags;
|
||||
imageFormatInfo.flags = createFlags;
|
||||
|
||||
VkPhysicalDeviceImageDrmFormatModifierInfoEXT drmFormatModifierInfo = {};
|
||||
drmFormatModifierInfo.sType =
|
||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT;
|
||||
drmFormatModifierInfo.pNext = &externalMemoryImageCreateInfo;
|
||||
drmFormatModifierInfo.drmFormatModifier = drmModifier;
|
||||
drmFormatModifierInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
if (drmModifier != 0)
|
||||
{
|
||||
imageFormatInfo.pNext = &drmFormatModifierInfo;
|
||||
imageFormatInfo.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
|
||||
}
|
||||
|
||||
return vkGetPhysicalDeviceImageFormatProperties2(renderer->getPhysicalDevice(),
|
||||
&imageFormatInfo, imageFormatPropertiesOut) !=
|
||||
VK_ERROR_FORMAT_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
VkChromaLocation GetChromaLocation(const egl::AttributeMap &attribs, EGLenum hint)
|
||||
{
|
||||
return attribs.getAsInt(hint, EGL_YUV_CHROMA_SITING_0_EXT) == EGL_YUV_CHROMA_SITING_0_EXT
|
||||
? VK_CHROMA_LOCATION_COSITED_EVEN
|
||||
: VK_CHROMA_LOCATION_MIDPOINT;
|
||||
}
|
||||
|
||||
VkSamplerYcbcrModelConversion GetYcbcrModel(const egl::AttributeMap &attribs)
|
||||
{
|
||||
switch (attribs.getAsInt(EGL_YUV_COLOR_SPACE_HINT_EXT, EGL_ITU_REC601_EXT))
|
||||
{
|
||||
case EGL_ITU_REC601_EXT:
|
||||
return VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601;
|
||||
case EGL_ITU_REC709_EXT:
|
||||
return VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709;
|
||||
case EGL_ITU_REC2020_EXT:
|
||||
return VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601;
|
||||
}
|
||||
}
|
||||
|
||||
VkSamplerYcbcrRange GetYcbcrRange(const egl::AttributeMap &attribs)
|
||||
{
|
||||
return attribs.getAsInt(EGL_SAMPLE_RANGE_HINT_EXT, EGL_YUV_FULL_RANGE_EXT) ==
|
||||
EGL_YUV_FULL_RANGE_EXT
|
||||
? VK_SAMPLER_YCBCR_RANGE_ITU_FULL
|
||||
: VK_SAMPLER_YCBCR_RANGE_ITU_NARROW;
|
||||
}
|
||||
|
||||
uint32_t GetAllocateInfo(const egl::AttributeMap &attribs,
|
||||
VkImage image,
|
||||
uint32_t planeCount,
|
||||
const VkDrmFormatModifierPropertiesEXT &properties,
|
||||
AllocateInfo *infoOut)
|
||||
{
|
||||
// There are a number of situations:
|
||||
//
|
||||
// - If the format tilingFeatures does not have the DISJOINT bit, then allocation and bind is
|
||||
// done as usual; the fd is used to create the allocation and vkBindImageMemory is called
|
||||
// without any extra bind info (which would need vkBindImageMemory2).
|
||||
// - If the format tilingFeatures does have the DISJOINT bit, but all fds are identical, it's
|
||||
// handled similarly to the non-disjoint case.
|
||||
// - Otherwise if there are N planes, there must be N allocations and N binds (one per fd).
|
||||
// When binding, VkBindImagePlaneMemoryInfo is used to identify which plane is being bound.
|
||||
//
|
||||
constexpr uint32_t kDisjointBit = VK_FORMAT_FEATURE_DISJOINT_BIT;
|
||||
bool isDisjoint =
|
||||
planeCount > 1 && IsMaskFlagSet(properties.drmFormatModifierTilingFeatures, kDisjointBit);
|
||||
if (isDisjoint)
|
||||
{
|
||||
bool areFdsIdentical = true;
|
||||
for (uint32_t plane = 1; plane < planeCount; ++plane)
|
||||
{
|
||||
if (attribs.getAsInt(kFds[plane]) != attribs.getAsInt(kFds[0]))
|
||||
{
|
||||
areFdsIdentical = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Treat DISJOINT-but-identical-fds as non-disjoint.
|
||||
if (areFdsIdentical)
|
||||
{
|
||||
isDisjoint = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill in allocateInfo, importFdInfo, bindInfo and bindPlaneInfo first.
|
||||
const uint32_t planesToAllocate = isDisjoint ? planeCount : 1;
|
||||
for (uint32_t plane = 0; plane < planesToAllocate; ++plane)
|
||||
{
|
||||
infoOut->allocateInfo[plane].sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
|
||||
infoOut->allocateInfo[plane].pNext = &infoOut->importFdInfo[plane];
|
||||
infoOut->allocateInfo[plane].image = image;
|
||||
|
||||
infoOut->importFdInfo[plane].sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR;
|
||||
infoOut->importFdInfo[plane].handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
|
||||
infoOut->importFdInfo[plane].fd = attribs.getAsInt(kFds[plane]);
|
||||
|
||||
infoOut->allocateInfoPtr[plane] = &infoOut->allocateInfo[plane];
|
||||
}
|
||||
|
||||
return planesToAllocate;
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
DmaBufImageSiblingVkLinux::DmaBufImageSiblingVkLinux(const egl::AttributeMap &attribs)
|
||||
: mAttribs(attribs),
|
||||
mFormat(GL_NONE),
|
||||
mRenderable(false),
|
||||
mTextureable(false),
|
||||
mYUV(false),
|
||||
mSamples(0),
|
||||
mImage(nullptr)
|
||||
{
|
||||
ASSERT(mAttribs.contains(EGL_WIDTH));
|
||||
ASSERT(mAttribs.contains(EGL_HEIGHT));
|
||||
mSize.width = mAttribs.getAsInt(EGL_WIDTH);
|
||||
mSize.height = mAttribs.getAsInt(EGL_HEIGHT);
|
||||
mSize.depth = 1;
|
||||
|
||||
int fourCCFormat = mAttribs.getAsInt(EGL_LINUX_DRM_FOURCC_EXT);
|
||||
mFormat = gl::Format(angle::DrmFourCCFormatToGLInternalFormat(fourCCFormat, &mYUV));
|
||||
|
||||
mHasProtectedContent = mAttribs.getAsInt(EGL_PROTECTED_CONTENT_EXT, false);
|
||||
}
|
||||
|
||||
DmaBufImageSiblingVkLinux::~DmaBufImageSiblingVkLinux() {}
|
||||
|
||||
egl::Error DmaBufImageSiblingVkLinux::initialize(const egl::Display *display)
|
||||
{
|
||||
DisplayVk *displayVk = vk::GetImpl(display);
|
||||
return angle::ToEGL(initImpl(displayVk), displayVk, EGL_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
angle::Result DmaBufImageSiblingVkLinux::initImpl(DisplayVk *displayVk)
|
||||
{
|
||||
RendererVk *renderer = displayVk->getRenderer();
|
||||
|
||||
const vk::Format &vkFormat = renderer->getFormat(mFormat.info->sizedInternalFormat);
|
||||
const angle::Format &format = vkFormat.getActualImageFormat(rx::vk::ImageAccess::SampleOnly);
|
||||
const VkFormat vulkanFormat = vkFormat.getActualImageVkFormat(rx::vk::ImageAccess::SampleOnly);
|
||||
const angle::FormatID intendedFormatID = vkFormat.getIntendedFormatID();
|
||||
const angle::FormatID actualImageFormatID =
|
||||
vkFormat.getActualImageFormatID(rx::vk::ImageAccess::SampleOnly);
|
||||
|
||||
const uint32_t planeCount = GetPlaneCount(mAttribs);
|
||||
|
||||
PerPlane<uint64_t> planeModifiers = {};
|
||||
GetModifiers(mAttribs, planeCount, &planeModifiers);
|
||||
|
||||
// The EGL extension allows for each plane to have a different DRM modifier. This is not
|
||||
// allowed in Vulkan, and all hardware past and current require the planes to have the same DRM
|
||||
// modifier. If an application provides different modifiers for the planes, fail.
|
||||
const uint64_t plane0Modifier = planeModifiers[0];
|
||||
for (uint32_t plane = 0; plane < planeCount; ++plane)
|
||||
{
|
||||
ANGLE_VK_CHECK(displayVk, planeModifiers[plane] == plane0Modifier,
|
||||
VK_ERROR_INCOMPATIBLE_DRIVER);
|
||||
}
|
||||
|
||||
// First, check the possible features for the format and determine usage and create flags.
|
||||
VkDrmFormatModifierPropertiesEXT modifierProperties = {};
|
||||
ANGLE_TRY(
|
||||
GetFormatModifierProperties(displayVk, vulkanFormat, plane0Modifier, &modifierProperties));
|
||||
|
||||
VkImageUsageFlags usageFlags =
|
||||
GetUsageFlags(renderer, format, modifierProperties, &mTextureable, &mRenderable);
|
||||
|
||||
const VkImageCreateFlags createFlags =
|
||||
vk::kVkImageCreateFlagsNone | (hasProtectedContent() ? VK_IMAGE_CREATE_PROTECTED_BIT : 0);
|
||||
|
||||
// The Vulkan and EGL plane counts are expected to match.
|
||||
ANGLE_VK_CHECK(displayVk, modifierProperties.drmFormatModifierPlaneCount == planeCount,
|
||||
VK_ERROR_INCOMPATIBLE_DRIVER);
|
||||
|
||||
// Verify that such a usage is compatible with the provided modifiers, if any. If not, try to
|
||||
// remove features until it is.
|
||||
VkExternalImageFormatProperties externalFormatProperties = {};
|
||||
externalFormatProperties.sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES;
|
||||
|
||||
VkImageFormatProperties2 imageFormatProperties = {};
|
||||
imageFormatProperties.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
|
||||
imageFormatProperties.pNext = &externalFormatProperties;
|
||||
|
||||
if (!IsFormatSupported(renderer, vulkanFormat, plane0Modifier, usageFlags, createFlags,
|
||||
&imageFormatProperties))
|
||||
{
|
||||
mRenderable = false;
|
||||
usageFlags &= ~kRenderUsage;
|
||||
if (!IsFormatSupported(renderer, vulkanFormat, plane0Modifier, usageFlags, createFlags,
|
||||
&imageFormatProperties))
|
||||
{
|
||||
mTextureable = false;
|
||||
usageFlags &= ~kTextureUsage;
|
||||
|
||||
if (!IsFormatSupported(renderer, vulkanFormat, plane0Modifier, usageFlags, createFlags,
|
||||
&imageFormatProperties))
|
||||
{
|
||||
// The image is completely unusable.
|
||||
ANGLE_VK_CHECK(displayVk, false, VK_ERROR_FORMAT_NOT_SUPPORTED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure image width/height/samples are within allowed range and the image is importable.
|
||||
const bool isWidthValid = static_cast<uint32_t>(mSize.width) <=
|
||||
imageFormatProperties.imageFormatProperties.maxExtent.width;
|
||||
const bool isHeightValid = static_cast<uint32_t>(mSize.height) <=
|
||||
imageFormatProperties.imageFormatProperties.maxExtent.height;
|
||||
const bool isSampleCountValid =
|
||||
(imageFormatProperties.imageFormatProperties.sampleCounts & VK_SAMPLE_COUNT_1_BIT) != 0;
|
||||
const bool isMemoryImportable =
|
||||
(externalFormatProperties.externalMemoryProperties.externalMemoryFeatures &
|
||||
VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) == 0;
|
||||
ANGLE_VK_CHECK(displayVk,
|
||||
isWidthValid && isHeightValid && isSampleCountValid && isMemoryImportable,
|
||||
VK_ERROR_INCOMPATIBLE_DRIVER);
|
||||
|
||||
std::vector<VkSubresourceLayout> planes(planeCount, VkSubresourceLayout{});
|
||||
for (uint32_t plane = 0; plane < planeCount; ++plane)
|
||||
{
|
||||
planes[plane].offset = mAttribs.getAsInt(kOffsets[plane]);
|
||||
planes[plane].rowPitch = mAttribs.getAsInt(kPitches[plane]);
|
||||
}
|
||||
|
||||
VkImageDrmFormatModifierExplicitCreateInfoEXT imageDrmModifierCreateInfo = {};
|
||||
imageDrmModifierCreateInfo.sType =
|
||||
VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT;
|
||||
imageDrmModifierCreateInfo.drmFormatModifier = plane0Modifier;
|
||||
imageDrmModifierCreateInfo.drmFormatModifierPlaneCount = planeCount;
|
||||
imageDrmModifierCreateInfo.pPlaneLayouts = planes.data();
|
||||
|
||||
VkExternalMemoryImageCreateInfo externalMemoryImageCreateInfo = {};
|
||||
externalMemoryImageCreateInfo.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO;
|
||||
externalMemoryImageCreateInfo.pNext = &imageDrmModifierCreateInfo;
|
||||
externalMemoryImageCreateInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
|
||||
|
||||
// Create the image
|
||||
mImage = new vk::ImageHelper();
|
||||
|
||||
VkExtent3D vkExtents;
|
||||
gl_vk::GetExtent(mSize, &vkExtents);
|
||||
|
||||
constexpr bool kIsRobustInitEnabled = false;
|
||||
|
||||
ANGLE_TRY(mImage->initExternal(displayVk, gl::TextureType::_2D, vkExtents, intendedFormatID,
|
||||
actualImageFormatID, 1, usageFlags, createFlags,
|
||||
vk::ImageLayout::ExternalPreInitialized,
|
||||
&externalMemoryImageCreateInfo, gl::LevelIndex(0), 1, 1,
|
||||
kIsRobustInitEnabled, nullptr, hasProtectedContent()));
|
||||
|
||||
VkMemoryRequirements externalMemoryRequirements;
|
||||
mImage->getImage().getMemoryRequirements(renderer->getDevice(), &externalMemoryRequirements);
|
||||
|
||||
const VkMemoryPropertyFlags flags =
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
|
||||
(hasProtectedContent() ? VK_MEMORY_PROPERTY_PROTECTED_BIT : 0);
|
||||
|
||||
VkSamplerYcbcrConversionCreateInfo yuvConversionInfo = {};
|
||||
VkSamplerYcbcrConversionCreateInfo *yuvConversionInfoPtr = nullptr;
|
||||
if (mYUV)
|
||||
{
|
||||
const VkChromaLocation xChromaOffset =
|
||||
GetChromaLocation(mAttribs, EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT);
|
||||
const VkChromaLocation yChromaOffset =
|
||||
GetChromaLocation(mAttribs, EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT);
|
||||
const VkSamplerYcbcrModelConversion model = GetYcbcrModel(mAttribs);
|
||||
const VkSamplerYcbcrRange range = GetYcbcrRange(mAttribs);
|
||||
|
||||
ANGLE_VK_CHECK(displayVk, renderer->getFeatures().supportsYUVSamplerConversion.enabled,
|
||||
VK_ERROR_FEATURE_NOT_PRESENT);
|
||||
|
||||
yuvConversionInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO;
|
||||
yuvConversionInfo.format = vulkanFormat;
|
||||
yuvConversionInfo.xChromaOffset = xChromaOffset;
|
||||
yuvConversionInfo.yChromaOffset = yChromaOffset;
|
||||
yuvConversionInfo.ycbcrModel = model;
|
||||
yuvConversionInfo.ycbcrRange = range;
|
||||
yuvConversionInfo.chromaFilter = VK_FILTER_NEAREST;
|
||||
// yuvConversionInfo.components = {}; // TODO: swizzle?
|
||||
|
||||
yuvConversionInfoPtr = &yuvConversionInfo;
|
||||
}
|
||||
|
||||
AllocateInfo allocateInfo;
|
||||
const uint32_t allocateInfoCount = GetAllocateInfo(
|
||||
mAttribs, mImage->getImage().getHandle(), planeCount, modifierProperties, &allocateInfo);
|
||||
|
||||
return mImage->initExternalMemory(displayVk, renderer->getMemoryProperties(),
|
||||
externalMemoryRequirements, yuvConversionInfoPtr,
|
||||
allocateInfoCount, allocateInfo.allocateInfoPtr.data(),
|
||||
VK_QUEUE_FAMILY_FOREIGN_EXT, flags);
|
||||
}
|
||||
|
||||
void DmaBufImageSiblingVkLinux::onDestroy(const egl::Display *display)
|
||||
{
|
||||
ASSERT(mImage == nullptr);
|
||||
}
|
||||
|
||||
gl::Format DmaBufImageSiblingVkLinux::getFormat() const
|
||||
{
|
||||
return mFormat;
|
||||
}
|
||||
|
||||
bool DmaBufImageSiblingVkLinux::isRenderable(const gl::Context *context) const
|
||||
{
|
||||
return mRenderable;
|
||||
}
|
||||
|
||||
bool DmaBufImageSiblingVkLinux::isTexturable(const gl::Context *context) const
|
||||
{
|
||||
return mTextureable;
|
||||
}
|
||||
|
||||
bool DmaBufImageSiblingVkLinux::isYUV() const
|
||||
{
|
||||
return mYUV;
|
||||
}
|
||||
|
||||
bool DmaBufImageSiblingVkLinux::hasProtectedContent() const
|
||||
{
|
||||
return mHasProtectedContent;
|
||||
}
|
||||
|
||||
gl::Extents DmaBufImageSiblingVkLinux::getSize() const
|
||||
{
|
||||
return mSize;
|
||||
}
|
||||
|
||||
size_t DmaBufImageSiblingVkLinux::getSamples() const
|
||||
{
|
||||
return mSamples;
|
||||
}
|
||||
|
||||
// ExternalImageSiblingVk interface
|
||||
vk::ImageHelper *DmaBufImageSiblingVkLinux::getImage() const
|
||||
{
|
||||
return mImage;
|
||||
}
|
||||
|
||||
void DmaBufImageSiblingVkLinux::release(RendererVk *renderer)
|
||||
{
|
||||
if (mImage != nullptr)
|
||||
{
|
||||
// TODO: Handle the case where the EGLImage is used in two contexts not in the same share
|
||||
// group. https://issuetracker.google.com/169868803
|
||||
mImage->releaseImage(renderer);
|
||||
mImage->releaseStagingBuffer(renderer);
|
||||
SafeDelete(mImage);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace rx
|
|
@ -0,0 +1,59 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
// DmaBufImageSiblingVkLinux.h: Defines the DmaBufImageSiblingVkLinux to wrap
|
||||
// EGL images created from Linux dma-buf objects
|
||||
|
||||
#ifndef LIBANGLE_RENDERER_VULKAN_LINUX_DMABUFIMAGESIBLINGVKLINUX_H_
|
||||
#define LIBANGLE_RENDERER_VULKAN_LINUX_DMABUFIMAGESIBLINGVKLINUX_H_
|
||||
|
||||
#include "libANGLE/renderer/vulkan/ImageVk.h"
|
||||
|
||||
namespace rx
|
||||
{
|
||||
|
||||
class DmaBufImageSiblingVkLinux : public ExternalImageSiblingVk
|
||||
{
|
||||
public:
|
||||
DmaBufImageSiblingVkLinux(const egl::AttributeMap &attribs);
|
||||
~DmaBufImageSiblingVkLinux() override;
|
||||
|
||||
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;
|
||||
bool isYUV() const override;
|
||||
bool hasProtectedContent() const override;
|
||||
gl::Extents getSize() const override;
|
||||
size_t getSamples() const override;
|
||||
|
||||
// ExternalImageSiblingVk interface
|
||||
vk::ImageHelper *getImage() const override;
|
||||
|
||||
void release(RendererVk *renderer) override;
|
||||
|
||||
private:
|
||||
angle::Result initImpl(DisplayVk *displayVk);
|
||||
|
||||
egl::AttributeMap mAttribs;
|
||||
gl::Extents mSize;
|
||||
gl::Format mFormat;
|
||||
|
||||
bool mRenderable;
|
||||
bool mTextureable;
|
||||
bool mYUV;
|
||||
bool mHasProtectedContent;
|
||||
size_t mSamples;
|
||||
|
||||
vk::ImageHelper *mImage;
|
||||
};
|
||||
|
||||
} // namespace rx
|
||||
|
||||
#endif // LIBANGLE_RENDERER_VULKAN_LINUX_DMABUFIMAGESIBLINGVKLINUX_H_
|
|
@ -17,7 +17,7 @@
|
|||
namespace rx
|
||||
{
|
||||
|
||||
DisplayVkSimple::DisplayVkSimple(const egl::DisplayState &state) : DisplayVk(state) {}
|
||||
DisplayVkSimple::DisplayVkSimple(const egl::DisplayState &state) : DisplayVkLinux(state) {}
|
||||
|
||||
void DisplayVkSimple::terminate()
|
||||
{
|
|
@ -11,12 +11,12 @@
|
|||
#ifndef LIBANGLE_RENDERER_VULKAN_DISPLAY_DISPLAYVKSIMPLE_H_
|
||||
#define LIBANGLE_RENDERER_VULKAN_DISPLAY_DISPLAYVKSIMPLE_H_
|
||||
|
||||
#include "libANGLE/renderer/vulkan/DisplayVk.h"
|
||||
#include "libANGLE/renderer/vulkan/linux/DisplayVkLinux.h"
|
||||
|
||||
namespace rx
|
||||
{
|
||||
|
||||
class DisplayVkSimple : public DisplayVk
|
||||
class DisplayVkSimple : public DisplayVkLinux
|
||||
{
|
||||
public:
|
||||
DisplayVkSimple(const egl::DisplayState &state);
|
|
@ -17,7 +17,7 @@
|
|||
namespace rx
|
||||
{
|
||||
|
||||
DisplayVkHeadless::DisplayVkHeadless(const egl::DisplayState &state) : DisplayVk(state) {}
|
||||
DisplayVkHeadless::DisplayVkHeadless(const egl::DisplayState &state) : DisplayVkLinux(state) {}
|
||||
|
||||
void DisplayVkHeadless::terminate()
|
||||
{
|
|
@ -11,12 +11,12 @@
|
|||
#ifndef LIBANGLE_RENDERER_VULKAN_DISPLAY_DISPLAYVKHEADLESS_H_
|
||||
#define LIBANGLE_RENDERER_VULKAN_DISPLAY_DISPLAYVKHEADLESS_H_
|
||||
|
||||
#include "libANGLE/renderer/vulkan/DisplayVk.h"
|
||||
#include "libANGLE/renderer/vulkan/linux/DisplayVkLinux.h"
|
||||
|
||||
namespace rx
|
||||
{
|
||||
|
||||
class DisplayVkHeadless : public DisplayVk
|
||||
class DisplayVkHeadless : public DisplayVkLinux
|
||||
{
|
||||
public:
|
||||
DisplayVkHeadless(const egl::DisplayState &state);
|
|
@ -7,15 +7,15 @@
|
|||
// Implements the class methods for DisplayVkXcb.
|
||||
//
|
||||
|
||||
#include "libANGLE/renderer/vulkan/xcb/DisplayVkXcb.h"
|
||||
#include "libANGLE/renderer/vulkan/linux/xcb/DisplayVkXcb.h"
|
||||
|
||||
#include <X11/Xutil.h>
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
#include "common/system_utils.h"
|
||||
#include "libANGLE/Display.h"
|
||||
#include "libANGLE/renderer/vulkan/linux/xcb/WindowSurfaceVkXcb.h"
|
||||
#include "libANGLE/renderer/vulkan/vk_caps_utils.h"
|
||||
#include "libANGLE/renderer/vulkan/xcb/WindowSurfaceVkXcb.h"
|
||||
|
||||
namespace rx
|
||||
{
|
||||
|
@ -43,7 +43,7 @@ EGLint GetXcbVisualType(xcb_screen_t *screen)
|
|||
} // namespace
|
||||
|
||||
DisplayVkXcb::DisplayVkXcb(const egl::DisplayState &state)
|
||||
: DisplayVk(state), mXcbConnection(nullptr), mHasXDisplay(false)
|
||||
: DisplayVkLinux(state), mXcbConnection(nullptr), mHasXDisplay(false)
|
||||
{}
|
||||
|
||||
egl::Error DisplayVkXcb::initialize(egl::Display *display)
|
|
@ -10,14 +10,14 @@
|
|||
#ifndef LIBANGLE_RENDERER_VULKAN_XCB_DISPLAYVKXCB_H_
|
||||
#define LIBANGLE_RENDERER_VULKAN_XCB_DISPLAYVKXCB_H_
|
||||
|
||||
#include "libANGLE/renderer/vulkan/DisplayVk.h"
|
||||
#include "libANGLE/renderer/vulkan/linux/DisplayVkLinux.h"
|
||||
|
||||
struct xcb_connection_t;
|
||||
|
||||
namespace rx
|
||||
{
|
||||
|
||||
class DisplayVkXcb : public DisplayVk
|
||||
class DisplayVkXcb : public DisplayVkLinux
|
||||
{
|
||||
public:
|
||||
DisplayVkXcb(const egl::DisplayState &state);
|
|
@ -7,7 +7,7 @@
|
|||
// Implements the class methods for WindowSurfaceVkXcb.
|
||||
//
|
||||
|
||||
#include "libANGLE/renderer/vulkan/xcb/WindowSurfaceVkXcb.h"
|
||||
#include "libANGLE/renderer/vulkan/linux/xcb/WindowSurfaceVkXcb.h"
|
||||
|
||||
#include "libANGLE/renderer/vulkan/RendererVk.h"
|
||||
|
|
@ -4362,13 +4362,35 @@ angle::Result ImageHelper::initExternalMemory(
|
|||
const MemoryProperties &memoryProperties,
|
||||
const VkMemoryRequirements &memoryRequirements,
|
||||
const VkSamplerYcbcrConversionCreateInfo *samplerYcbcrConversionCreateInfo,
|
||||
const void *extraAllocationInfo,
|
||||
uint32_t extraAllocationInfoCount,
|
||||
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));
|
||||
// Vulkan allows up to 4 memory planes.
|
||||
constexpr size_t kMaxMemoryPlanes = 4;
|
||||
constexpr VkImageAspectFlagBits kMemoryPlaneAspects[kMaxMemoryPlanes] = {
|
||||
VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT,
|
||||
VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT,
|
||||
VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT,
|
||||
VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT,
|
||||
};
|
||||
ASSERT(extraAllocationInfoCount <= kMaxMemoryPlanes);
|
||||
|
||||
VkBindImagePlaneMemoryInfoKHR bindImagePlaneMemoryInfo = {};
|
||||
bindImagePlaneMemoryInfo.sType = VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO;
|
||||
|
||||
const VkBindImagePlaneMemoryInfoKHR *bindImagePlaneMemoryInfoPtr =
|
||||
extraAllocationInfoCount == 1 ? nullptr : &bindImagePlaneMemoryInfo;
|
||||
|
||||
for (uint32_t memoryPlane = 0; memoryPlane < extraAllocationInfoCount; ++memoryPlane)
|
||||
{
|
||||
bindImagePlaneMemoryInfo.planeAspect = kMemoryPlaneAspects[memoryPlane];
|
||||
|
||||
ANGLE_TRY(AllocateImageMemoryWithRequirements(
|
||||
context, flags, memoryRequirements, extraAllocationInfo[memoryPlane],
|
||||
bindImagePlaneMemoryInfoPtr, &mImage, &mDeviceMemory));
|
||||
}
|
||||
mCurrentQueueFamilyIndex = currentQueueFamilyIndex;
|
||||
|
||||
#ifdef VK_USE_PLATFORM_ANDROID_KHR
|
||||
|
|
|
@ -1480,7 +1480,8 @@ class ImageHelper final : public Resource, public angle::Subject
|
|||
const MemoryProperties &memoryProperties,
|
||||
const VkMemoryRequirements &memoryRequirements,
|
||||
const VkSamplerYcbcrConversionCreateInfo *samplerYcbcrConversionCreateInfo,
|
||||
const void *extraAllocationInfo,
|
||||
uint32_t extraAllocationInfoCount,
|
||||
const void **extraAllocationInfo,
|
||||
uint32_t currentQueueFamilyIndex,
|
||||
VkMemoryPropertyFlags flags);
|
||||
angle::Result initLayerImageView(Context *context,
|
||||
|
|
|
@ -124,7 +124,18 @@ angle::Result AllocateAndBindBufferOrImageMemory(vk::Context *context,
|
|||
VkMemoryPropertyFlags *memoryPropertyFlagsOut,
|
||||
const VkMemoryRequirements &memoryRequirements,
|
||||
const void *extraAllocationInfo,
|
||||
const VkBindImagePlaneMemoryInfoKHR *extraBindInfo,
|
||||
T *bufferOrImage,
|
||||
vk::DeviceMemory *deviceMemoryOut);
|
||||
|
||||
template <>
|
||||
angle::Result AllocateAndBindBufferOrImageMemory(vk::Context *context,
|
||||
VkMemoryPropertyFlags requestedMemoryPropertyFlags,
|
||||
VkMemoryPropertyFlags *memoryPropertyFlagsOut,
|
||||
const VkMemoryRequirements &memoryRequirements,
|
||||
const void *extraAllocationInfo,
|
||||
const VkBindImagePlaneMemoryInfoKHR *extraBindInfo,
|
||||
vk::Image *image,
|
||||
vk::DeviceMemory *deviceMemoryOut)
|
||||
{
|
||||
const vk::MemoryProperties &memoryProperties = context->getRenderer()->getMemoryProperties();
|
||||
|
@ -132,7 +143,44 @@ angle::Result AllocateAndBindBufferOrImageMemory(vk::Context *context,
|
|||
ANGLE_TRY(FindAndAllocateCompatibleMemory(
|
||||
context, memoryProperties, requestedMemoryPropertyFlags, memoryPropertyFlagsOut,
|
||||
memoryRequirements, extraAllocationInfo, deviceMemoryOut));
|
||||
ANGLE_VK_TRY(context, bufferOrImage->bindMemory(context->getDevice(), *deviceMemoryOut));
|
||||
|
||||
if (extraBindInfo)
|
||||
{
|
||||
VkBindImageMemoryInfoKHR bindInfo = {};
|
||||
bindInfo.sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO;
|
||||
bindInfo.pNext = extraBindInfo;
|
||||
bindInfo.image = image->getHandle();
|
||||
bindInfo.memory = deviceMemoryOut->getHandle();
|
||||
bindInfo.memoryOffset = 0;
|
||||
|
||||
ANGLE_VK_TRY(context, image->bindMemory2(context->getDevice(), bindInfo));
|
||||
}
|
||||
else
|
||||
{
|
||||
ANGLE_VK_TRY(context, image->bindMemory(context->getDevice(), *deviceMemoryOut));
|
||||
}
|
||||
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
template <>
|
||||
angle::Result AllocateAndBindBufferOrImageMemory(vk::Context *context,
|
||||
VkMemoryPropertyFlags requestedMemoryPropertyFlags,
|
||||
VkMemoryPropertyFlags *memoryPropertyFlagsOut,
|
||||
const VkMemoryRequirements &memoryRequirements,
|
||||
const void *extraAllocationInfo,
|
||||
const VkBindImagePlaneMemoryInfoKHR *extraBindInfo,
|
||||
vk::Buffer *buffer,
|
||||
vk::DeviceMemory *deviceMemoryOut)
|
||||
{
|
||||
ASSERT(extraBindInfo == nullptr);
|
||||
|
||||
const vk::MemoryProperties &memoryProperties = context->getRenderer()->getMemoryProperties();
|
||||
|
||||
ANGLE_TRY(FindAndAllocateCompatibleMemory(
|
||||
context, memoryProperties, requestedMemoryPropertyFlags, memoryPropertyFlagsOut,
|
||||
memoryRequirements, extraAllocationInfo, deviceMemoryOut));
|
||||
ANGLE_VK_TRY(context, buffer->bindMemory(context->getDevice(), *deviceMemoryOut));
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
|
@ -151,7 +199,7 @@ angle::Result AllocateBufferOrImageMemory(vk::Context *context,
|
|||
|
||||
ANGLE_TRY(AllocateAndBindBufferOrImageMemory(
|
||||
context, requestedMemoryPropertyFlags, memoryPropertyFlagsOut, memoryRequirements,
|
||||
extraAllocationInfo, bufferOrImage, deviceMemoryOut));
|
||||
extraAllocationInfo, nullptr, bufferOrImage, deviceMemoryOut));
|
||||
|
||||
*sizeOut = memoryRequirements.size;
|
||||
|
||||
|
@ -565,17 +613,19 @@ angle::Result AllocateImageMemory(Context *context,
|
|||
extraAllocationInfo, image, deviceMemoryOut, sizeOut);
|
||||
}
|
||||
|
||||
angle::Result AllocateImageMemoryWithRequirements(Context *context,
|
||||
VkMemoryPropertyFlags memoryPropertyFlags,
|
||||
const VkMemoryRequirements &memoryRequirements,
|
||||
const void *extraAllocationInfo,
|
||||
Image *image,
|
||||
DeviceMemory *deviceMemoryOut)
|
||||
angle::Result AllocateImageMemoryWithRequirements(
|
||||
Context *context,
|
||||
VkMemoryPropertyFlags memoryPropertyFlags,
|
||||
const VkMemoryRequirements &memoryRequirements,
|
||||
const void *extraAllocationInfo,
|
||||
const VkBindImagePlaneMemoryInfoKHR *extraBindInfo,
|
||||
Image *image,
|
||||
DeviceMemory *deviceMemoryOut)
|
||||
{
|
||||
VkMemoryPropertyFlags memoryPropertyFlagsOut = 0;
|
||||
return AllocateAndBindBufferOrImageMemory(context, memoryPropertyFlags, &memoryPropertyFlagsOut,
|
||||
memoryRequirements, extraAllocationInfo, image,
|
||||
deviceMemoryOut);
|
||||
memoryRequirements, extraAllocationInfo,
|
||||
extraBindInfo, image, deviceMemoryOut);
|
||||
}
|
||||
|
||||
angle::Result AllocateBufferMemoryWithRequirements(Context *context,
|
||||
|
@ -587,8 +637,8 @@ angle::Result AllocateBufferMemoryWithRequirements(Context *context,
|
|||
DeviceMemory *deviceMemoryOut)
|
||||
{
|
||||
return AllocateAndBindBufferOrImageMemory(context, memoryPropertyFlags, memoryPropertyFlagsOut,
|
||||
memoryRequirements, extraAllocationInfo, buffer,
|
||||
deviceMemoryOut);
|
||||
memoryRequirements, extraAllocationInfo, nullptr,
|
||||
buffer, deviceMemoryOut);
|
||||
}
|
||||
|
||||
angle::Result InitShaderAndSerial(Context *context,
|
||||
|
|
|
@ -404,12 +404,14 @@ angle::Result AllocateImageMemory(Context *context,
|
|||
DeviceMemory *deviceMemoryOut,
|
||||
VkDeviceSize *sizeOut);
|
||||
|
||||
angle::Result AllocateImageMemoryWithRequirements(Context *context,
|
||||
VkMemoryPropertyFlags memoryPropertyFlags,
|
||||
const VkMemoryRequirements &memoryRequirements,
|
||||
const void *extraAllocationInfo,
|
||||
Image *image,
|
||||
DeviceMemory *deviceMemoryOut);
|
||||
angle::Result AllocateImageMemoryWithRequirements(
|
||||
Context *context,
|
||||
VkMemoryPropertyFlags memoryPropertyFlags,
|
||||
const VkMemoryRequirements &memoryRequirements,
|
||||
const void *extraAllocationInfo,
|
||||
const VkBindImagePlaneMemoryInfoKHR *extraBindInfo,
|
||||
Image *image,
|
||||
DeviceMemory *deviceMemoryOut);
|
||||
|
||||
angle::Result AllocateBufferMemoryWithRequirements(Context *context,
|
||||
VkMemoryPropertyFlags memoryPropertyFlags,
|
||||
|
|
|
@ -411,6 +411,7 @@ class Image final : public WrappedObject<Image, VkImage>
|
|||
|
||||
void getMemoryRequirements(VkDevice device, VkMemoryRequirements *requirementsOut) const;
|
||||
VkResult bindMemory(VkDevice device, const DeviceMemory &deviceMemory);
|
||||
VkResult bindMemory2(VkDevice device, const VkBindImageMemoryInfoKHR &bindInfo);
|
||||
|
||||
void getSubresourceLayout(VkDevice device,
|
||||
VkImageAspectFlagBits aspectMask,
|
||||
|
@ -1300,6 +1301,12 @@ ANGLE_INLINE VkResult Image::bindMemory(VkDevice device, const vk::DeviceMemory
|
|||
return vkBindImageMemory(device, mHandle, deviceMemory.getHandle(), 0);
|
||||
}
|
||||
|
||||
ANGLE_INLINE VkResult Image::bindMemory2(VkDevice device, const VkBindImageMemoryInfoKHR &bindInfo)
|
||||
{
|
||||
ASSERT(valid());
|
||||
return vkBindImageMemory2KHR(device, 1, &bindInfo);
|
||||
}
|
||||
|
||||
ANGLE_INLINE void Image::getSubresourceLayout(VkDevice device,
|
||||
VkImageAspectFlagBits aspectMask,
|
||||
uint32_t mipLevel,
|
||||
|
|
Загрузка…
Ссылка в новой задаче