Commit c4197713 by Michael Spang Committed by Commit Bot

Implement glImportMemoryZirconHandle & glImportSemaphoreZirconHandle

Implement import of fuchsia external objects passed by zircon handle. This works exactly the same as with file descriptors. Bug: angleproject:3492 Change-Id: I4d46917dfc5902f00c94550158a9f8073097f0a4 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1642334 Commit-Queue: Michael Spang <spang@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 5b78b389
......@@ -114,12 +114,24 @@ struct FeaturesVk : FeatureSetBase
"supports_external_memory_fd", FeatureCategory::VulkanFeatures,
"VkDevice supports the VK_KHR_external_memory_fd extension", &members};
// Whether the VkDevice supports the VK_FUCHSIA_external_memory
// extension, on which the GL_ANGLE_memory_object_fuchsia extension can be layered.
angle::Feature supportsExternalMemoryFuchsia = {
"supports_external_memory_fuchsia", FeatureCategory::VulkanFeatures,
"VkDevice supports the VK_FUCHSIA_external_memory extension", &members};
// Whether the VkDevice supports the VK_KHR_external_semaphore_fd extension, on which the
// GL_EXT_semaphore_fd extension can be layered.
Feature supportsExternalSemaphoreFd = {
"supports_external_semaphore_fd", FeatureCategory::VulkanFeatures,
"VkDevice supports the VK_KHR_external_semaphore_fd extension", &members};
// Whether the VkDevice supports the VK_FUCHSIA_external_semaphore
// extension, on which the GL_ANGLE_semaphore_fuchsia extension can be layered.
angle::Feature supportsExternalSemaphoreFuchsia = {
"supports_external_semaphore_fuchsia", FeatureCategory::VulkanFeatures,
"VkDevice supports the VK_FUCHSIA_external_semaphore extension", &members};
// Whether the VkDevice supports the VK_EXT_shader_stencil_export extension, which is used to
// perform multisampled resolve of stencil buffer. A multi-step workaround is used instead if
// this extension is not available.
......
//
// 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.
//
// vulkan_fuchsia_ext:
// Defines Fuchsia-specific Vulkan extensions that haven't been
// upstreamed to the official Vulkan headers.
//
#ifndef COMMON_VULKAN_FUCHSIA_EXT_H_
#define COMMON_VULKAN_FUCHSIA_EXT_H_
#if !defined(VK_NO_PROTOTYPES)
# define VK_NO_PROTOTYPES
#endif
#include <vulkan/vulkan.h>
#if defined(ANGLE_PLATFORM_FUCHSIA)
# include <zircon/types.h>
#else
typedef uint32_t zx_handle_t;
# define ZX_HANDLE_INVALID ((zx_handle_t)0)
#endif
#ifdef __cplusplus
extern "C" {
#endif
const VkStructureType VK_STRUCTURE_TYPE_TEMP_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA =
static_cast<VkStructureType>(1001005000);
const VkStructureType VK_STRUCTURE_TYPE_TEMP_MEMORY_ZIRCON_HANDLE_PROPERTIES_FUCHSIA =
static_cast<VkStructureType>(1001005001);
const VkStructureType VK_STRUCTURE_TYPE_TEMP_MEMORY_GET_ZIRCON_HANDLE_INFO_FUCHSIA =
static_cast<VkStructureType>(1001005002);
const VkStructureType VK_STRUCTURE_TYPE_TEMP_IMPORT_SEMAPHORE_ZIRCON_HANDLE_INFO_FUCHSIA =
static_cast<VkStructureType>(1001006000);
const VkStructureType VK_STRUCTURE_TYPE_TEMP_SEMAPHORE_GET_ZIRCON_HANDLE_INFO_FUCHSIA =
static_cast<VkStructureType>(1001006001);
const VkExternalMemoryHandleTypeFlagBits
VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA =
static_cast<VkExternalMemoryHandleTypeFlagBits>(0x00100000);
const VkExternalSemaphoreHandleTypeFlagBits
VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TEMP_ZIRCON_EVENT_BIT_FUCHSIA =
static_cast<VkExternalSemaphoreHandleTypeFlagBits>(0x00100000);
#define VK_FUCHSIA_external_memory 1
#define VK_FUCHSIA_EXTERNAL_MEMORY_SPEC_VERSION 1
#define VK_FUCHSIA_EXTERNAL_MEMORY_EXTENSION_NAME "VK_FUCHSIA_external_memory"
typedef struct VkImportMemoryZirconHandleInfoFUCHSIA
{
VkStructureType sType;
const void *pNext;
VkExternalMemoryHandleTypeFlagBits handleType;
zx_handle_t handle;
} VkImportMemoryZirconHandleInfoFUCHSIA;
typedef struct VkMemoryZirconHandlePropertiesFUCHSIA
{
VkStructureType sType;
void *pNext;
zx_handle_t memoryTypeBits;
} VkMemoryZirconHandlePropertiesFUCHSIA;
typedef struct VkMemoryGetZirconHandleInfoFUCHSIA
{
VkStructureType sType;
const void *pNext;
VkDeviceMemory memory;
VkExternalMemoryHandleTypeFlagBits handleType;
} VkMemoryGetZirconHandleInfoFUCHSIA;
typedef VkResult(VKAPI_PTR *PFN_vkGetMemoryZirconHandleFUCHSIA)(
VkDevice device,
const VkMemoryGetZirconHandleInfoFUCHSIA *pGetZirconHandleInfo,
zx_handle_t *pZirconHandle);
typedef VkResult(VKAPI_PTR *PFN_vkGetMemoryZirconHandlePropertiesFUCHSIA)(
VkDevice device,
VkExternalMemoryHandleTypeFlagBits handleType,
zx_handle_t ZirconHandle,
VkMemoryZirconHandlePropertiesFUCHSIA *pMemoryZirconHandleProperties);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL
vkGetMemoryZirconHandleFUCHSIA(VkDevice device,
const VkMemoryGetZirconHandleInfoFUCHSIA *pGetZirconHandleInfo,
zx_handle_t *pZirconHandle);
VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryZirconHandlePropertiesFUCHSIA(
VkDevice device,
VkExternalMemoryHandleTypeFlagBits handleType,
zx_handle_t ZirconHandle,
VkMemoryZirconHandlePropertiesFUCHSIA *pMemoryZirconHandleProperties);
#endif
#define VK_FUCHSIA_external_semaphore 1
#define VK_FUCHSIA_EXTERNAL_SEMAPHORE_SPEC_VERSION 1
#define VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME "VK_FUCHSIA_external_semaphore"
typedef struct VkImportSemaphoreZirconHandleInfoFUCHSIA
{
VkStructureType sType;
const void *pNext;
VkSemaphore semaphore;
VkSemaphoreImportFlags flags;
VkExternalSemaphoreHandleTypeFlagBits handleType;
zx_handle_t handle;
} VkImportSemaphoreZirconHandleInfoFUCHSIA;
typedef struct VkSemaphoreGetZirconHandleInfoFUCHSIA
{
VkStructureType sType;
const void *pNext;
VkSemaphore semaphore;
VkExternalSemaphoreHandleTypeFlagBits handleType;
} VkSemaphoreGetZirconHandleInfoFUCHSIA;
typedef VkResult(VKAPI_PTR *PFN_vkImportSemaphoreZirconHandleFUCHSIA)(
VkDevice device,
const VkImportSemaphoreZirconHandleInfoFUCHSIA *pImportSemaphoreZirconHandleInfo);
typedef VkResult(VKAPI_PTR *PFN_vkGetSemaphoreZirconHandleFUCHSIA)(
VkDevice device,
const VkSemaphoreGetZirconHandleInfoFUCHSIA *pGetZirconHandleInfo,
zx_handle_t *pZirconHandle);
#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkImportSemaphoreZirconHandleFUCHSIA(
VkDevice device,
const VkImportSemaphoreZirconHandleInfoFUCHSIA *pImportSemaphoreZirconHandleInfo);
VKAPI_ATTR VkResult VKAPI_CALL
vkGetSemaphoreZirconHandleFUCHSIA(VkDevice device,
const VkSemaphoreGetZirconHandleInfoFUCHSIA *pGetZirconHandleInfo,
zx_handle_t *pZirconHandle);
#endif
#ifdef __cplusplus
}
#endif
#endif // COMMON_VULKAN_FUCHSIA_EXT_H_
......@@ -8145,7 +8145,9 @@ void Context::importMemoryZirconHandle(MemoryObjectID memory,
HandleType handleType,
GLuint handle)
{
UNREACHABLE();
MemoryObject *memoryObject = getMemoryObject(memory);
ASSERT(memoryObject != nullptr);
ANGLE_CONTEXT_TRY(memoryObject->importZirconHandle(this, size, handleType, handle));
}
void Context::genSemaphores(GLsizei n, SemaphoreID *semaphores)
......@@ -8247,7 +8249,9 @@ void Context::importSemaphoreZirconHandle(SemaphoreID semaphore,
HandleType handleType,
GLuint handle)
{
UNREACHABLE();
Semaphore *semaphoreObject = getSemaphore(semaphore);
ASSERT(semaphoreObject != nullptr);
ANGLE_CONTEXT_TRY(semaphoreObject->importZirconHandle(this, handleType, handle));
}
void Context::eGLImageTargetTexture2D(TextureType target, GLeglImageOES image)
......
......@@ -33,4 +33,12 @@ angle::Result MemoryObject::importFd(Context *context,
return mImplementation->importFd(context, size, handleType, fd);
}
angle::Result MemoryObject::importZirconHandle(Context *context,
GLuint64 size,
HandleType handleType,
GLuint handle)
{
return mImplementation->importZirconHandle(context, size, handleType, handle);
}
} // namespace gl
......@@ -35,6 +35,10 @@ class MemoryObject final : public RefCountObject<MemoryObjectID>
rx::MemoryObjectImpl *getImplementation() const { return mImplementation.get(); }
angle::Result importFd(Context *context, GLuint64 size, HandleType handleType, GLint fd);
angle::Result importZirconHandle(Context *context,
GLuint64 size,
HandleType handleType,
GLuint handle);
private:
std::unique_ptr<rx::MemoryObjectImpl> mImplementation;
......
......@@ -30,6 +30,11 @@ angle::Result Semaphore::importFd(Context *context, HandleType handleType, GLint
return mImplementation->importFd(context, handleType, fd);
}
angle::Result Semaphore::importZirconHandle(Context *context, HandleType handleType, GLuint handle)
{
return mImplementation->importZirconHandle(context, handleType, handle);
}
angle::Result Semaphore::wait(Context *context,
const BufferBarrierVector &bufferBarriers,
const TextureBarrierVector &textureBarriers)
......
......@@ -38,6 +38,7 @@ class Semaphore final : public RefCountObject<SemaphoreID>
rx::SemaphoreImpl *getImplementation() const { return mImplementation.get(); }
angle::Result importFd(Context *context, HandleType handleType, GLint fd);
angle::Result importZirconHandle(Context *context, HandleType handleType, GLuint handle);
angle::Result wait(Context *context,
const BufferBarrierVector &bufferBarriers,
......
......@@ -32,7 +32,11 @@ class MemoryObjectImpl : angle::NonCopyable
virtual angle::Result importFd(gl::Context *context,
GLuint64 size,
gl::HandleType handleType,
GLint fd) = 0;
GLint fd) = 0;
virtual angle::Result importZirconHandle(gl::Context *context,
GLuint64 size,
gl::HandleType handleType,
GLuint handle) = 0;
};
} // namespace rx
......
......@@ -32,6 +32,10 @@ class SemaphoreImpl : angle::NonCopyable
virtual angle::Result importFd(gl::Context *context, gl::HandleType handleType, GLint fd) = 0;
virtual angle::Result importZirconHandle(gl::Context *context,
gl::HandleType handleType,
GLuint handle) = 0;
virtual angle::Result wait(gl::Context *context,
const gl::BufferBarrierVector &bufferBarriers,
const gl::TextureBarrierVector &textureBarriers) = 0;
......
......@@ -39,6 +39,15 @@ angle::Result MemoryObjectGL::importFd(gl::Context *context,
return angle::Result::Continue;
}
angle::Result MemoryObjectGL::importZirconHandle(gl::Context *context,
GLuint64 size,
gl::HandleType handleType,
GLuint handle)
{
UNREACHABLE();
return angle::Result::Stop;
}
GLuint MemoryObjectGL::getMemoryObjectID() const
{
return mMemoryObject;
......
......@@ -26,6 +26,11 @@ class MemoryObjectGL : public MemoryObjectImpl
gl::HandleType handleType,
GLint fd) override;
angle::Result importZirconHandle(gl::Context *context,
GLuint64 size,
gl::HandleType handleType,
GLuint handle) override;
GLuint getMemoryObjectID() const;
private:
......
......@@ -67,6 +67,14 @@ angle::Result SemaphoreGL::importFd(gl::Context *context, gl::HandleType handleT
return angle::Result::Continue;
}
angle::Result SemaphoreGL::importZirconHandle(gl::Context *context,
gl::HandleType handleType,
GLuint handle)
{
UNREACHABLE();
return angle::Result::Stop;
}
angle::Result SemaphoreGL::wait(gl::Context *context,
const gl::BufferBarrierVector &bufferBarriers,
const gl::TextureBarrierVector &textureBarriers)
......
......@@ -23,6 +23,10 @@ class SemaphoreGL : public SemaphoreImpl
angle::Result importFd(gl::Context *context, gl::HandleType handleType, GLint fd) override;
angle::Result importZirconHandle(gl::Context *context,
gl::HandleType handleType,
GLuint handle) override;
angle::Result wait(gl::Context *context,
const gl::BufferBarrierVector &bufferBarriers,
const gl::TextureBarrierVector &textureBarriers) override;
......
......@@ -7,12 +7,12 @@
#include "libANGLE/renderer/vulkan/MemoryObjectVk.h"
#include "volk.h"
#include "common/debug.h"
#include "libANGLE/Context.h"
#include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/RendererVk.h"
#include "volk.h"
#include "vulkan/vulkan_fuchsia_ext.h"
#if !defined(ANGLE_PLATFORM_WINDOWS)
# include <unistd.h>
......@@ -20,14 +20,17 @@
# include <io.h>
#endif
#if defined(ANGLE_PLATFORM_FUCHSIA)
# include <zircon/status.h>
# include <zircon/syscalls.h>
#endif
namespace rx
{
namespace
{
constexpr int kInvalidFd = -1;
#if defined(ANGLE_PLATFORM_WINDOWS)
int close(int fd)
{
......@@ -35,9 +38,45 @@ int close(int fd)
}
#endif
void CloseZirconVmo(zx_handle_t handle)
{
#if defined(ANGLE_PLATFORM_FUCHSIA)
zx_handle_close(handle);
#else
UNREACHABLE();
#endif
}
angle::Result DuplicateZirconVmo(ContextVk *contextVk, zx_handle_t handle, zx_handle_t *duplicate)
{
#if defined(ANGLE_PLATFORM_FUCHSIA)
zx_status_t status = zx_handle_duplicate(handle, ZX_RIGHT_SAME_RIGHTS, duplicate);
ANGLE_VK_CHECK(contextVk, status == ZX_OK, VK_ERROR_INVALID_EXTERNAL_HANDLE);
return angle::Result::Continue;
#else
UNREACHABLE();
return angle::Result::Stop;
#endif
}
VkExternalMemoryHandleTypeFlagBits ToVulkanHandleType(gl::HandleType handleType)
{
switch (handleType)
{
case gl::HandleType::OpaqueFd:
return VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
case gl::HandleType::ZirconVmo:
return VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA;
default:
// Not a memory handle type.
UNREACHABLE();
return VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM;
}
}
} // namespace
MemoryObjectVk::MemoryObjectVk() : mSize(0), mFd(kInvalidFd) {}
MemoryObjectVk::MemoryObjectVk() {}
MemoryObjectVk::~MemoryObjectVk() = default;
......@@ -48,6 +87,12 @@ void MemoryObjectVk::onDestroy(const gl::Context *context)
close(mFd);
mFd = kInvalidFd;
}
if (mZirconHandle != ZX_HANDLE_INVALID)
{
CloseZirconVmo(mZirconHandle);
mZirconHandle = ZX_HANDLE_INVALID;
}
}
angle::Result MemoryObjectVk::importFd(gl::Context *context,
......@@ -68,11 +113,43 @@ angle::Result MemoryObjectVk::importFd(gl::Context *context,
}
}
angle::Result MemoryObjectVk::importZirconHandle(gl::Context *context,
GLuint64 size,
gl::HandleType handleType,
GLuint handle)
{
ContextVk *contextVk = vk::GetImpl(context);
switch (handleType)
{
case gl::HandleType::ZirconVmo:
return importZirconVmo(contextVk, size, handle);
default:
UNREACHABLE();
return angle::Result::Stop;
}
}
angle::Result MemoryObjectVk::importOpaqueFd(ContextVk *contextVk, GLuint64 size, GLint fd)
{
ASSERT(mHandleType == gl::HandleType::InvalidEnum);
ASSERT(mFd == kInvalidFd);
mFd = fd;
mSize = size;
ASSERT(fd != kInvalidFd);
mHandleType = gl::HandleType::OpaqueFd;
mFd = fd;
mSize = size;
return angle::Result::Continue;
}
angle::Result MemoryObjectVk::importZirconVmo(ContextVk *contextVk, GLuint64 size, GLuint handle)
{
ASSERT(mHandleType == gl::HandleType::InvalidEnum);
ASSERT(mZirconHandle == ZX_HANDLE_INVALID);
ASSERT(handle != ZX_HANDLE_INVALID);
mHandleType = gl::HandleType::ZirconVmo;
mZirconHandle = handle;
mSize = size;
return angle::Result::Continue;
}
......@@ -95,7 +172,7 @@ angle::Result MemoryObjectVk::createImage(ContextVk *contextVk,
VkExternalMemoryImageCreateInfo externalMemoryImageCreateInfo = {};
externalMemoryImageCreateInfo.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO;
externalMemoryImageCreateInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
externalMemoryImageCreateInfo.handleTypes = ToVulkanHandleType(mHandleType);
VkExtent3D vkExtents;
uint32_t layerCount;
......@@ -109,11 +186,30 @@ angle::Result MemoryObjectVk::createImage(ContextVk *contextVk,
VkMemoryRequirements externalMemoryRequirements;
image->getImage().getMemoryRequirements(renderer->getDevice(), &externalMemoryRequirements);
ASSERT(mFd != -1);
VkImportMemoryFdInfoKHR importMemoryFdInfo = {};
importMemoryFdInfo.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR;
importMemoryFdInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
importMemoryFdInfo.fd = dup(mFd);
void *importMemoryInfo = nullptr;
VkImportMemoryFdInfoKHR importMemoryFdInfo = {};
VkImportMemoryZirconHandleInfoFUCHSIA importMemoryZirconHandleInfo = {};
switch (mHandleType)
{
case gl::HandleType::OpaqueFd:
ASSERT(mFd != kInvalidFd);
importMemoryFdInfo.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR;
importMemoryFdInfo.handleType = ToVulkanHandleType(mHandleType);
importMemoryFdInfo.fd = dup(mFd);
importMemoryInfo = &importMemoryFdInfo;
break;
case gl::HandleType::ZirconVmo:
ASSERT(mZirconHandle != ZX_HANDLE_INVALID);
importMemoryZirconHandleInfo.sType =
VK_STRUCTURE_TYPE_TEMP_IMPORT_MEMORY_ZIRCON_HANDLE_INFO_FUCHSIA;
importMemoryZirconHandleInfo.handleType = ToVulkanHandleType(mHandleType);
ANGLE_TRY(
DuplicateZirconVmo(contextVk, mZirconHandle, &importMemoryZirconHandleInfo.handle));
importMemoryInfo = &importMemoryZirconHandleInfo;
break;
default:
UNREACHABLE();
}
// TODO(jmadill, spang): Memory sub-allocation. http://anglebug.com/2162
ASSERT(offset == 0);
......@@ -121,7 +217,7 @@ angle::Result MemoryObjectVk::createImage(ContextVk *contextVk,
VkMemoryPropertyFlags flags = 0;
ANGLE_TRY(image->initExternalMemory(contextVk, renderer->getMemoryProperties(),
externalMemoryRequirements, &importMemoryFdInfo,
externalMemoryRequirements, importMemoryInfo,
VK_QUEUE_FAMILY_EXTERNAL, flags));
return angle::Result::Continue;
......
......@@ -28,7 +28,12 @@ class MemoryObjectVk : public MemoryObjectImpl
gl::HandleType handleType,
GLint fd) override;
angle::Result createImage(ContextVk *contextVk,
angle::Result importZirconHandle(gl::Context *context,
GLuint64 size,
gl::HandleType handleType,
GLuint handle) override;
angle::Result createImage(ContextVk *context,
gl::TextureType type,
size_t levels,
GLenum internalFormat,
......@@ -37,10 +42,15 @@ class MemoryObjectVk : public MemoryObjectImpl
vk::ImageHelper *image);
private:
static constexpr int kInvalidFd = -1;
angle::Result importOpaqueFd(ContextVk *contextVk, GLuint64 size, GLint fd);
angle::Result importZirconVmo(ContextVk *contextVk, GLuint64 size, GLuint handle);
GLuint64 mSize = 0;
gl::HandleType mHandleType = gl::HandleType::InvalidEnum;
int mFd = kInvalidFd;
GLuint64 mSize;
int mFd;
zx_handle_t mZirconHandle = ZX_HANDLE_INVALID;
};
} // namespace rx
......
......@@ -1128,12 +1128,6 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
enabledDeviceExtensions.push_back(VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME);
}
if (getFeatures().supportsAndroidHardwareBuffer.enabled ||
getFeatures().supportsExternalMemoryFd.enabled)
{
enabledDeviceExtensions.push_back(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME);
}
#if defined(ANGLE_PLATFORM_ANDROID)
if (getFeatures().supportsAndroidHardwareBuffer.enabled)
{
......@@ -1145,12 +1139,25 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
ASSERT(!getFeatures().supportsAndroidHardwareBuffer.enabled);
#endif
if (getFeatures().supportsAndroidHardwareBuffer.enabled ||
getFeatures().supportsExternalMemoryFd.enabled ||
getFeatures().supportsExternalMemoryFuchsia.enabled)
{
enabledDeviceExtensions.push_back(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME);
}
if (getFeatures().supportsExternalMemoryFd.enabled)
{
enabledDeviceExtensions.push_back(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME);
}
if (getFeatures().supportsExternalSemaphoreFd.enabled)
if (getFeatures().supportsExternalMemoryFuchsia.enabled)
{
enabledDeviceExtensions.push_back(VK_FUCHSIA_EXTERNAL_MEMORY_EXTENSION_NAME);
}
if (getFeatures().supportsExternalSemaphoreFd.enabled ||
getFeatures().supportsExternalSemaphoreFuchsia.enabled)
{
enabledDeviceExtensions.push_back(VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME);
}
......@@ -1160,6 +1167,11 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
enabledDeviceExtensions.push_back(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME);
}
if (getFeatures().supportsExternalSemaphoreFuchsia.enabled)
{
enabledDeviceExtensions.push_back(VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME);
}
if (getFeatures().supportsShaderStencilExport.enabled)
{
enabledDeviceExtensions.push_back(VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME);
......@@ -1573,10 +1585,18 @@ void RendererVk::initFeatures(DisplayVk *displayVk, const ExtensionNameList &dev
ExtensionFound(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, deviceExtensionNames));
ANGLE_FEATURE_CONDITION(
(&mFeatures), supportsExternalMemoryFuchsia,
ExtensionFound(VK_FUCHSIA_EXTERNAL_MEMORY_EXTENSION_NAME, deviceExtensionNames));
ANGLE_FEATURE_CONDITION(
(&mFeatures), supportsExternalSemaphoreFd,
ExtensionFound(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, deviceExtensionNames));
ANGLE_FEATURE_CONDITION(
(&mFeatures), supportsExternalSemaphoreFuchsia,
ExtensionFound(VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME, deviceExtensionNames));
ANGLE_FEATURE_CONDITION(
(&mFeatures), supportsShaderStencilExport,
ExtensionFound(VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME, deviceExtensionNames));
......
......@@ -78,6 +78,23 @@ angle::Result SemaphoreVk::importFd(gl::Context *context, gl::HandleType handleT
}
}
angle::Result SemaphoreVk::importZirconHandle(gl::Context *context,
gl::HandleType handleType,
GLuint handle)
{
ContextVk *contextVk = vk::GetImpl(context);
switch (handleType)
{
case gl::HandleType::ZirconEvent:
return importZirconEvent(contextVk, handle);
default:
ANGLE_VK_UNREACHABLE(contextVk);
return angle::Result::Stop;
}
}
angle::Result SemaphoreVk::wait(gl::Context *context,
const gl::BufferBarrierVector &bufferBarriers,
const gl::TextureBarrierVector &textureBarriers)
......@@ -216,4 +233,35 @@ angle::Result SemaphoreVk::importOpaqueFd(ContextVk *contextVk, GLint fd)
return angle::Result::Continue;
}
angle::Result SemaphoreVk::importZirconEvent(ContextVk *contextVk, GLuint handle)
{
RendererVk *renderer = contextVk->getRenderer();
if (!mSemaphore.valid())
{
mSemaphore.init(renderer->getDevice());
}
ASSERT(mSemaphore.valid());
VkImportSemaphoreZirconHandleInfoFUCHSIA importSemaphoreZirconHandleInfo = {};
importSemaphoreZirconHandleInfo.sType =
VK_STRUCTURE_TYPE_TEMP_IMPORT_SEMAPHORE_ZIRCON_HANDLE_INFO_FUCHSIA;
importSemaphoreZirconHandleInfo.semaphore = mSemaphore.getHandle();
importSemaphoreZirconHandleInfo.flags = 0;
importSemaphoreZirconHandleInfo.handleType =
VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TEMP_ZIRCON_EVENT_BIT_FUCHSIA;
importSemaphoreZirconHandleInfo.handle = handle;
// TODO(spang): Add vkImportSemaphoreZirconHandleFUCHSIA to volk.
static PFN_vkImportSemaphoreZirconHandleFUCHSIA vkImportSemaphoreZirconHandleFUCHSIA =
reinterpret_cast<PFN_vkImportSemaphoreZirconHandleFUCHSIA>(
vkGetInstanceProcAddr(renderer->getInstance(), "vkImportSemaphoreZirconHandleFUCHSIA"));
ANGLE_VK_TRY(contextVk, vkImportSemaphoreZirconHandleFUCHSIA(renderer->getDevice(),
&importSemaphoreZirconHandleInfo));
return angle::Result::Continue;
}
} // namespace rx
......@@ -25,6 +25,10 @@ class SemaphoreVk : public SemaphoreImpl
angle::Result importFd(gl::Context *context, gl::HandleType handleType, GLint fd) override;
angle::Result importZirconHandle(gl::Context *context,
gl::HandleType handleType,
GLuint handle) override;
angle::Result wait(gl::Context *context,
const gl::BufferBarrierVector &bufferBarriers,
const gl::TextureBarrierVector &textureBarriers) override;
......@@ -35,6 +39,7 @@ class SemaphoreVk : public SemaphoreImpl
private:
angle::Result importOpaqueFd(ContextVk *contextVk, GLint fd);
angle::Result importZirconEvent(ContextVk *contextVk, GLuint handle);
vk::Semaphore mSemaphore;
};
......
......@@ -94,9 +94,13 @@ void RendererVk::ensureCapsInitialized() const
mNativeExtensions.memoryObject = true;
mNativeExtensions.memoryObjectFd = getFeatures().supportsExternalMemoryFd.enabled;
mNativeExtensions.memoryObjectFuchsiaANGLE =
getFeatures().supportsExternalMemoryFuchsia.enabled;
mNativeExtensions.semaphore = true;
mNativeExtensions.semaphoreFd = getFeatures().supportsExternalSemaphoreFd.enabled;
mNativeExtensions.semaphoreFuchsiaANGLE =
getFeatures().supportsExternalSemaphoreFuchsia.enabled;
mNativeExtensions.vertexHalfFloatOES = true;
......
......@@ -23,6 +23,7 @@
#include "libANGLE/renderer/serial_utils.h"
#include "libANGLE/renderer/vulkan/SecondaryCommandBuffer.h"
#include "libANGLE/renderer/vulkan/vk_wrapper.h"
#include "vulkan/vulkan_fuchsia_ext.h"
#define ANGLE_GL_OBJECTS_X(PROC) \
PROC(Buffer) \
......
......@@ -3589,8 +3589,16 @@ bool ValidateImportMemoryZirconHandleANGLE(const Context *context,
return false;
}
UNIMPLEMENTED();
return false;
switch (handleType)
{
case HandleType::ZirconVmo:
break;
default:
context->validationError(GL_INVALID_ENUM, kInvalidHandleType);
return false;
}
return true;
}
bool ValidateDeleteSemaphoresEXT(const Context *context, GLsizei n, const SemaphoreID *semaphores)
......@@ -3733,7 +3741,7 @@ bool ValidateImportSemaphoreFdEXT(const Context *context,
bool ValidateImportSemaphoreZirconHandleANGLE(const Context *context,
SemaphoreID semaphore,
HandleType handleTypePacked,
HandleType handleType,
GLuint handle)
{
if (!context->getExtensions().semaphoreFuchsiaANGLE)
......@@ -3742,8 +3750,16 @@ bool ValidateImportSemaphoreZirconHandleANGLE(const Context *context,
return false;
}
UNIMPLEMENTED();
return false;
switch (handleType)
{
case HandleType::ZirconEvent:
break;
default:
context->validationError(GL_INVALID_ENUM, kInvalidHandleType);
return false;
}
return true;
}
bool ValidateMapBufferBase(const Context *context, BufferBinding target)
......
......@@ -175,6 +175,59 @@ TEST_P(VulkanExternalImageTest, ShouldClearOpaqueFdRGBA8)
vkFreeMemory(helper.getDevice(), deviceMemory, nullptr);
}
// Test creating and clearing a simple RGBA8 texture in a zircon vmo.
TEST_P(VulkanExternalImageTest, ShouldClearZirconVmoRGBA8)
{
// http://anglebug.com/4229
ANGLE_SKIP_TEST_IF(IsVulkan());
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
VulkanExternalHelper helper;
helper.initialize();
VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
ANGLE_SKIP_TEST_IF(
!helper.canCreateImageZirconVmo(format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL));
VkImage image = VK_NULL_HANDLE;
VkDeviceMemory deviceMemory = VK_NULL_HANDLE;
VkDeviceSize deviceMemorySize = 0;
VkExtent3D extent = {1, 1, 1};
VkResult result =
helper.createImage2DZirconVmo(format, extent, &image, &deviceMemory, &deviceMemorySize);
EXPECT_EQ(result, VK_SUCCESS);
zx_handle_t vmo = ZX_HANDLE_INVALID;
result = helper.exportMemoryZirconVmo(deviceMemory, &vmo);
EXPECT_EQ(result, VK_SUCCESS);
EXPECT_NE(vmo, ZX_HANDLE_INVALID);
{
GLMemoryObject memoryObject;
glImportMemoryZirconHandleANGLE(memoryObject, deviceMemorySize,
GL_HANDLE_TYPE_ZIRCON_VMO_ANGLE, vmo);
GLTexture texture;
glBindTexture(GL_TEXTURE_2D, texture);
glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1, memoryObject, 0);
GLFramebuffer framebuffer;
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
glClearColor(0.5f, 0.5f, 0.5f, 0.5f);
glClear(GL_COLOR_BUFFER_BIT);
EXPECT_PIXEL_NEAR(0, 0, 128, 128, 128, 128, 1.0);
}
EXPECT_GL_NO_ERROR();
vkDestroyImage(helper.getDevice(), image, nullptr);
vkFreeMemory(helper.getDevice(), deviceMemory, nullptr);
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against.
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(VulkanExternalImageTest);
......
......@@ -201,10 +201,9 @@ void VulkanExternalHelper::initialize()
EnumerateDeviceExtensionProperties(mPhysicalDevice, nullptr);
std::vector<const char *> requestedDeviceExtensions = {
VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME,
VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME,
VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,
VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME, VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME,
VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME, VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,
VK_FUCHSIA_EXTERNAL_MEMORY_EXTENSION_NAME, VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME,
};
std::vector<const char *> enabledDeviceExtensions;
......@@ -273,6 +272,10 @@ void VulkanExternalHelper::initialize()
HasExtension(enabledDeviceExtensions, VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME);
mHasExternalSemaphoreFd =
HasExtension(enabledDeviceExtensions, VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME);
mHasExternalMemoryFuchsia =
HasExtension(enabledDeviceExtensions, VK_FUCHSIA_EXTERNAL_MEMORY_EXTENSION_NAME);
mHasExternalSemaphoreFuchsia =
HasExtension(enabledDeviceExtensions, VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME);
vkGetPhysicalDeviceImageFormatProperties2 =
reinterpret_cast<PFN_vkGetPhysicalDeviceImageFormatProperties2>(
......@@ -284,21 +287,20 @@ void VulkanExternalHelper::initialize()
vkGetPhysicalDeviceExternalSemaphorePropertiesKHR =
reinterpret_cast<PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR>(
vkGetInstanceProcAddr(mInstance, "vkGetPhysicalDeviceExternalSemaphorePropertiesKHR"));
vkGetMemoryZirconHandleFUCHSIA = reinterpret_cast<PFN_vkGetMemoryZirconHandleFUCHSIA>(
vkGetInstanceProcAddr(mInstance, "vkGetMemoryZirconHandleFUCHSIA"));
}
bool VulkanExternalHelper::canCreateImageOpaqueFd(VkFormat format,
VkImageType type,
VkImageTiling tiling) const
bool VulkanExternalHelper::canCreateImageExternal(
VkFormat format,
VkImageType type,
VkImageTiling tiling,
VkExternalMemoryHandleTypeFlagBits handleType) const
{
if (!mHasExternalMemoryFd)
{
return false;
}
VkPhysicalDeviceExternalImageFormatInfo externalImageFormatInfo = {
/* .sType = */ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
/* .pNext = */ nullptr,
/* .handleType = */ VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,
/* .handleType = */ handleType,
};
VkPhysicalDeviceImageFormatInfo2 imageFormatInfo = {
......@@ -347,8 +349,9 @@ bool VulkanExternalHelper::canCreateImageOpaqueFd(VkFormat format,
return true;
}
VkResult VulkanExternalHelper::createImage2DOpaqueFd(VkFormat format,
VkResult VulkanExternalHelper::createImage2DExternal(VkFormat format,
VkExtent3D extent,
VkExternalMemoryHandleTypeFlags handleTypes,
VkImage *imageOut,
VkDeviceMemory *deviceMemoryOut,
VkDeviceSize *deviceMemorySizeOut)
......@@ -356,7 +359,7 @@ VkResult VulkanExternalHelper::createImage2DOpaqueFd(VkFormat format,
VkExternalMemoryImageCreateInfoKHR externalMemoryImageCreateInfo = {
/* .sType = */ VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
/* .pNext = */ nullptr,
/* .handleTypes = */ VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,
/* .handleTypes = */ handleTypes,
};
VkImageCreateInfo imageCreateInfo = {
......@@ -395,9 +398,8 @@ VkResult VulkanExternalHelper::createImage2DOpaqueFd(VkFormat format,
VkExportMemoryAllocateInfo exportMemoryAllocateInfo = {
/* .sType = */ VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
/* .pNext = */ nullptr,
/* .handleTypes = */ VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,
/* .handleTypes = */ handleTypes,
};
VkMemoryAllocateInfo memoryAllocateInfo = {
/* .sType = */ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
/* .pNext = */ &exportMemoryAllocateInfo,
......@@ -429,6 +431,29 @@ VkResult VulkanExternalHelper::createImage2DOpaqueFd(VkFormat format,
return VK_SUCCESS;
}
bool VulkanExternalHelper::canCreateImageOpaqueFd(VkFormat format,
VkImageType type,
VkImageTiling tiling) const
{
if (!mHasExternalMemoryFd)
{
return false;
}
return canCreateImageExternal(format, type, tiling,
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT);
}
VkResult VulkanExternalHelper::createImage2DOpaqueFd(VkFormat format,
VkExtent3D extent,
VkImage *imageOut,
VkDeviceMemory *deviceMemoryOut,
VkDeviceSize *deviceMemorySizeOut)
{
return createImage2DExternal(format, extent, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT,
imageOut, deviceMemoryOut, deviceMemorySizeOut);
}
VkResult VulkanExternalHelper::exportMemoryOpaqueFd(VkDeviceMemory deviceMemory, int *fd)
{
VkMemoryGetFdInfoKHR memoryGetFdInfo = {
......@@ -441,6 +466,42 @@ VkResult VulkanExternalHelper::exportMemoryOpaqueFd(VkDeviceMemory deviceMemory,
return vkGetMemoryFdKHR(mDevice, &memoryGetFdInfo, fd);
}
bool VulkanExternalHelper::canCreateImageZirconVmo(VkFormat format,
VkImageType type,
VkImageTiling tiling) const
{
if (!mHasExternalMemoryFuchsia)
{
return false;
}
return canCreateImageExternal(format, type, tiling,
VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA);
}
VkResult VulkanExternalHelper::createImage2DZirconVmo(VkFormat format,
VkExtent3D extent,
VkImage *imageOut,
VkDeviceMemory *deviceMemoryOut,
VkDeviceSize *deviceMemorySizeOut)
{
return createImage2DExternal(format, extent,
VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA,
imageOut, deviceMemoryOut, deviceMemorySizeOut);
}
VkResult VulkanExternalHelper::exportMemoryZirconVmo(VkDeviceMemory deviceMemory, zx_handle_t *vmo)
{
VkMemoryGetZirconHandleInfoFUCHSIA memoryGetZirconHandleInfo = {
/* .sType = */ VK_STRUCTURE_TYPE_TEMP_MEMORY_GET_ZIRCON_HANDLE_INFO_FUCHSIA,
/* .pNext = */ nullptr,
/* .memory = */ deviceMemory,
/* .handleType = */ VK_EXTERNAL_MEMORY_HANDLE_TYPE_TEMP_ZIRCON_VMO_BIT_FUCHSIA,
};
return vkGetMemoryZirconHandleFUCHSIA(mDevice, &memoryGetZirconHandleInfo, vmo);
}
bool VulkanExternalHelper::canCreateSemaphoreOpaqueFd() const
{
if (!mHasExternalSemaphoreFd || !vkGetPhysicalDeviceExternalSemaphorePropertiesKHR)
......
......@@ -9,6 +9,7 @@
#define ANGLE_TESTS_TESTUTILS_VULKANEXTERNALHELPER_H_
#include "volk.h"
#include "vulkan/vulkan_fuchsia_ext.h"
namespace angle
{
......@@ -26,6 +27,17 @@ class VulkanExternalHelper
VkDevice getDevice() const { return mDevice; }
VkQueue getGraphicsQueue() const { return mGraphicsQueue; }
bool canCreateImageExternal(VkFormat format,
VkImageType type,
VkImageTiling tiling,
VkExternalMemoryHandleTypeFlagBits handleType) const;
VkResult createImage2DExternal(VkFormat format,
VkExtent3D extent,
VkExternalMemoryHandleTypeFlags handleTypes,
VkImage *imageOut,
VkDeviceMemory *deviceMemoryOut,
VkDeviceSize *deviceMemorySizeOut);
// VK_KHR_external_memory_fd
bool canCreateImageOpaqueFd(VkFormat format, VkImageType type, VkImageTiling tiling) const;
VkResult createImage2DOpaqueFd(VkFormat format,
......@@ -35,11 +47,25 @@ class VulkanExternalHelper
VkDeviceSize *deviceMemorySizeOut);
VkResult exportMemoryOpaqueFd(VkDeviceMemory deviceMemory, int *fd);
// VK_FUCHSIA_external_memory
bool canCreateImageZirconVmo(VkFormat format, VkImageType type, VkImageTiling tiling) const;
VkResult createImage2DZirconVmo(VkFormat format,
VkExtent3D extent,
VkImage *imageOut,
VkDeviceMemory *deviceMemoryOut,
VkDeviceSize *deviceMemorySizeOut);
VkResult exportMemoryZirconVmo(VkDeviceMemory deviceMemory, zx_handle_t *vmo);
// VK_KHR_external_semaphore_fd
bool canCreateSemaphoreOpaqueFd() const;
VkResult createSemaphoreOpaqueFd(VkSemaphore *semaphore);
VkResult exportSemaphoreOpaqueFd(VkSemaphore semaphore, int *fd);
// VK_FUCHSIA_external_semaphore
bool canCreateSemaphoreZirconEvent() const;
VkResult createSemaphoreZirconEvent(VkSemaphore *semaphore);
VkResult exportSemaphoreZirconEvent(VkSemaphore semaphore, zx_handle_t *event);
private:
VkInstance mInstance = VK_NULL_HANDLE;
VkPhysicalDevice mPhysicalDevice = VK_NULL_HANDLE;
......@@ -50,14 +76,17 @@ class VulkanExternalHelper
uint32_t mGraphicsQueueFamilyIndex = UINT32_MAX;
bool mHasExternalMemoryFd = false;
bool mHasExternalSemaphoreFd = false;
bool mHasExternalMemoryFd = false;
bool mHasExternalMemoryFuchsia = false;
bool mHasExternalSemaphoreFd = false;
bool mHasExternalSemaphoreFuchsia = false;
PFN_vkGetPhysicalDeviceImageFormatProperties2 vkGetPhysicalDeviceImageFormatProperties2 =
nullptr;
PFN_vkGetMemoryFdKHR vkGetMemoryFdKHR = nullptr;
PFN_vkGetSemaphoreFdKHR vkGetSemaphoreFdKHR = nullptr;
PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR
vkGetPhysicalDeviceExternalSemaphorePropertiesKHR = nullptr;
vkGetPhysicalDeviceExternalSemaphorePropertiesKHR = nullptr;
PFN_vkGetMemoryZirconHandleFUCHSIA vkGetMemoryZirconHandleFUCHSIA = nullptr;
};
} // namespace angle
......
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