Commit 6bb193c8 by Michael Spang Committed by Commit Bot

Vulkan: Implement glImportSemaphoreFdEXT

Allow importing file descriptors into semaphores on linux. This can be used to synchronize ANGLE's GL renderer with respect to vulkan composition in chromium. Bug: angleproject:3289 Change-Id: I04ba3bbb2e343baa000ff89c21c03ca36163a713 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1623812 Commit-Queue: Michael Spang <spang@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent d9fa0744
...@@ -7265,7 +7265,9 @@ void Context::signalSemaphore(GLuint semaphore, ...@@ -7265,7 +7265,9 @@ void Context::signalSemaphore(GLuint semaphore,
void Context::importSemaphoreFd(GLuint semaphore, HandleType handleType, GLint fd) void Context::importSemaphoreFd(GLuint semaphore, HandleType handleType, GLint fd)
{ {
UNIMPLEMENTED(); Semaphore *semaphoreObject = getSemaphore(semaphore);
ASSERT(semaphoreObject != nullptr);
ANGLE_CONTEXT_TRY(semaphoreObject->importFd(this, handleType, fd));
} }
void Context::eGLImageTargetTexture2D(TextureType target, GLeglImageOES image) void Context::eGLImageTargetTexture2D(TextureType target, GLeglImageOES image)
......
...@@ -25,4 +25,9 @@ void Semaphore::onDestroy(const Context *context) ...@@ -25,4 +25,9 @@ void Semaphore::onDestroy(const Context *context)
mImplementation->onDestroy(context); mImplementation->onDestroy(context);
} }
angle::Result Semaphore::importFd(Context *context, HandleType handleType, GLint fd)
{
return mImplementation->importFd(context, handleType, fd);
}
} // namespace gl } // namespace gl
...@@ -11,7 +11,9 @@ ...@@ -11,7 +11,9 @@
#include <memory> #include <memory>
#include "angle_gl.h" #include "angle_gl.h"
#include "common/PackedEnums.h"
#include "common/angleutils.h" #include "common/angleutils.h"
#include "libANGLE/Error.h"
#include "libANGLE/RefCountObject.h" #include "libANGLE/RefCountObject.h"
namespace rx namespace rx
...@@ -34,6 +36,8 @@ class Semaphore final : public RefCountObject ...@@ -34,6 +36,8 @@ class Semaphore final : public RefCountObject
rx::SemaphoreImpl *getImplementation() const { return mImplementation.get(); } rx::SemaphoreImpl *getImplementation() const { return mImplementation.get(); }
angle::Result importFd(Context *context, HandleType handleType, GLint fd);
private: private:
std::unique_ptr<rx::SemaphoreImpl> mImplementation; std::unique_ptr<rx::SemaphoreImpl> mImplementation;
}; };
......
...@@ -28,6 +28,8 @@ class SemaphoreImpl : angle::NonCopyable ...@@ -28,6 +28,8 @@ class SemaphoreImpl : angle::NonCopyable
virtual ~SemaphoreImpl() {} virtual ~SemaphoreImpl() {}
virtual void onDestroy(const gl::Context *context) = 0; virtual void onDestroy(const gl::Context *context) = 0;
virtual angle::Result importFd(gl::Context *context, gl::HandleType handleType, GLint fd) = 0;
}; };
} // namespace rx } // namespace rx
......
...@@ -1012,6 +1012,7 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF ...@@ -1012,6 +1012,7 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
if (getFeatures().supportsExternalSemaphoreFd.enabled) if (getFeatures().supportsExternalSemaphoreFd.enabled)
{ {
enabledDeviceExtensions.push_back(VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME); enabledDeviceExtensions.push_back(VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME);
InitExternalSemaphoreFdFunctions(mInstance);
} }
if (getFeatures().supportsExternalSemaphoreFd.enabled) if (getFeatures().supportsExternalSemaphoreFd.enabled)
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#include "common/debug.h" #include "common/debug.h"
#include "libANGLE/Context.h" #include "libANGLE/Context.h"
#include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/RendererVk.h"
namespace rx namespace rx
{ {
...@@ -17,6 +19,50 @@ SemaphoreVk::SemaphoreVk() = default; ...@@ -17,6 +19,50 @@ SemaphoreVk::SemaphoreVk() = default;
SemaphoreVk::~SemaphoreVk() = default; SemaphoreVk::~SemaphoreVk() = default;
void SemaphoreVk::onDestroy(const gl::Context *context) {} void SemaphoreVk::onDestroy(const gl::Context *context)
{
ContextVk *contextVk = vk::GetImpl(context);
RendererVk *renderer = contextVk->getRenderer();
Serial currentSerial = renderer->getCurrentQueueSerial();
renderer->releaseObject(currentSerial, &mSemaphore);
}
angle::Result SemaphoreVk::importFd(gl::Context *context, gl::HandleType handleType, GLint fd)
{
switch (handleType)
{
case gl::HandleType::OpaqueFd:
return importOpaqueFd(context, fd);
default:
ANGLE_VK_UNREACHABLE(vk::GetImpl(context));
return angle::Result::Stop;
}
}
angle::Result SemaphoreVk::importOpaqueFd(gl::Context *context, GLint fd)
{
ContextVk *contextVk = vk::GetImpl(context);
RendererVk *renderer = contextVk->getRenderer();
if (!mSemaphore.valid())
{
mSemaphore.init(renderer->getDevice());
}
ASSERT(mSemaphore.valid());
VkImportSemaphoreFdInfoKHR importSemaphoreFdInfo = {};
importSemaphoreFdInfo.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR;
importSemaphoreFdInfo.semaphore = mSemaphore.getHandle();
importSemaphoreFdInfo.flags = 0;
importSemaphoreFdInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT;
importSemaphoreFdInfo.fd = fd;
ANGLE_VK_TRY(contextVk, vkImportSemaphoreFdKHR(renderer->getDevice(), &importSemaphoreFdInfo));
return angle::Result::Continue;
}
} // namespace rx } // namespace rx
...@@ -22,6 +22,13 @@ class SemaphoreVk : public SemaphoreImpl ...@@ -22,6 +22,13 @@ class SemaphoreVk : public SemaphoreImpl
~SemaphoreVk() override; ~SemaphoreVk() override;
void onDestroy(const gl::Context *context) override; void onDestroy(const gl::Context *context) override;
angle::Result importFd(gl::Context *context, gl::HandleType handleType, GLint fd) override;
private:
angle::Result importOpaqueFd(gl::Context *context, GLint fd);
vk::Semaphore mSemaphore;
}; };
} // namespace rx } // namespace rx
......
...@@ -522,6 +522,9 @@ PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT = nullptr; ...@@ -522,6 +522,9 @@ PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT = nullptr;
// VK_KHR_get_physical_device_properties2 // VK_KHR_get_physical_device_properties2
PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR = nullptr; PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR = nullptr;
// VK_KHR_external_semaphore_fd
PFN_vkImportSemaphoreFdKHR vkImportSemaphoreFdKHR = nullptr;
#if defined(ANGLE_PLATFORM_FUCHSIA) #if defined(ANGLE_PLATFORM_FUCHSIA)
// VK_FUCHSIA_imagepipe_surface // VK_FUCHSIA_imagepipe_surface
PFN_vkCreateImagePipeSurfaceFUCHSIA vkCreateImagePipeSurfaceFUCHSIA = nullptr; PFN_vkCreateImagePipeSurfaceFUCHSIA vkCreateImagePipeSurfaceFUCHSIA = nullptr;
...@@ -572,6 +575,11 @@ void InitExternalMemoryHardwareBufferANDROIDFunctions(VkInstance instance) ...@@ -572,6 +575,11 @@ void InitExternalMemoryHardwareBufferANDROIDFunctions(VkInstance instance)
} }
#endif #endif
void InitExternalSemaphoreFdFunctions(VkInstance instance)
{
GET_FUNC(vkImportSemaphoreFdKHR);
}
#undef GET_FUNC #undef GET_FUNC
namespace gl_vk namespace gl_vk
......
...@@ -494,6 +494,9 @@ extern PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT; ...@@ -494,6 +494,9 @@ extern PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT;
// VK_KHR_get_physical_device_properties2 // VK_KHR_get_physical_device_properties2
extern PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR; extern PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR;
// VK_KHR_external_semaphore_fd
extern PFN_vkImportSemaphoreFdKHR vkImportSemaphoreFdKHR;
// Lazily load entry points for each extension as necessary. // Lazily load entry points for each extension as necessary.
void InitDebugUtilsEXTFunctions(VkInstance instance); void InitDebugUtilsEXTFunctions(VkInstance instance);
void InitDebugReportEXTFunctions(VkInstance instance); void InitDebugReportEXTFunctions(VkInstance instance);
...@@ -512,6 +515,8 @@ extern PFN_vkGetMemoryAndroidHardwareBufferANDROID vkGetMemoryAndroidHardwareBuf ...@@ -512,6 +515,8 @@ extern PFN_vkGetMemoryAndroidHardwareBufferANDROID vkGetMemoryAndroidHardwareBuf
void InitExternalMemoryHardwareBufferANDROIDFunctions(VkInstance instance); void InitExternalMemoryHardwareBufferANDROIDFunctions(VkInstance instance);
#endif #endif
void InitExternalSemaphoreFdFunctions(VkInstance instance);
namespace gl_vk namespace gl_vk
{ {
VkRect2D GetRect(const gl::Rectangle &source); VkRect2D GetRect(const gl::Rectangle &source);
......
...@@ -3374,8 +3374,16 @@ bool ValidateImportSemaphoreFdEXT(Context *context, ...@@ -3374,8 +3374,16 @@ bool ValidateImportSemaphoreFdEXT(Context *context,
return false; return false;
} }
UNIMPLEMENTED(); switch (handleType)
return false; {
case HandleType::OpaqueFd:
break;
default:
context->validationError(GL_INVALID_ENUM, kInvalidHandleType);
return false;
}
return true;
} }
bool ValidateMapBufferBase(Context *context, BufferBinding target) bool ValidateMapBufferBase(Context *context, BufferBinding target)
......
...@@ -48,6 +48,21 @@ TEST_P(SemaphoreTest, SemaphoreShouldBeSemaphore) ...@@ -48,6 +48,21 @@ TEST_P(SemaphoreTest, SemaphoreShouldBeSemaphore)
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
} }
// glImportSemaphoreFdEXT must fail for handle types that are not file descriptors.
TEST_P(SemaphoreTest, ShouldFailValidationOnImportFdUnsupportedHandleType)
{
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
{
GLSemaphore semaphore;
int fd = -1;
glImportSemaphoreFdEXT(semaphore, GL_HANDLE_TYPE_OPAQUE_WIN32_EXT, fd);
EXPECT_GL_ERROR(GL_INVALID_ENUM);
}
EXPECT_GL_NO_ERROR();
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these // Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against. // tests should be run against.
ANGLE_INSTANTIATE_TEST(SemaphoreTest, ANGLE_INSTANTIATE_TEST(SemaphoreTest,
......
...@@ -55,7 +55,7 @@ class VulkanExternalImageTest : public ANGLETest ...@@ -55,7 +55,7 @@ class VulkanExternalImageTest : public ANGLETest
}; };
// glImportMemoryFdEXT must be able to import a valid opaque fd. // glImportMemoryFdEXT must be able to import a valid opaque fd.
TEST_P(VulkanExternalImageTest, ShouldImportOpaqueFd) TEST_P(VulkanExternalImageTest, ShouldImportMemoryOpaqueFd)
{ {
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd")); ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
...@@ -90,6 +90,35 @@ TEST_P(VulkanExternalImageTest, ShouldImportOpaqueFd) ...@@ -90,6 +90,35 @@ TEST_P(VulkanExternalImageTest, ShouldImportOpaqueFd)
vkFreeMemory(helper.getDevice(), deviceMemory, nullptr); vkFreeMemory(helper.getDevice(), deviceMemory, nullptr);
} }
// glImportSemaphoreFdEXT must be able to import a valid opaque fd.
TEST_P(VulkanExternalImageTest, ShouldImportSemaphoreOpaqueFd)
{
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
VulkanExternalHelper helper;
helper.initialize();
ANGLE_SKIP_TEST_IF(!helper.canCreateSemaphoreOpaqueFd());
VkSemaphore vkSemaphore = VK_NULL_HANDLE;
VkResult result = helper.createSemaphoreOpaqueFd(&vkSemaphore);
EXPECT_EQ(result, VK_SUCCESS);
int fd = kInvalidFd;
result = helper.exportSemaphoreOpaqueFd(vkSemaphore, &fd);
EXPECT_EQ(result, VK_SUCCESS);
EXPECT_NE(fd, kInvalidFd);
{
GLSemaphore glSemaphore;
glImportSemaphoreFdEXT(glSemaphore, GL_HANDLE_TYPE_OPAQUE_FD_EXT, fd);
}
EXPECT_GL_NO_ERROR();
vkDestroySemaphore(helper.getDevice(), vkSemaphore, nullptr);
}
// Test creating and clearing a simple RGBA8 texture in a opaque fd. // Test creating and clearing a simple RGBA8 texture in a opaque fd.
TEST_P(VulkanExternalImageTest, ShouldClearOpaqueFdRGBA8) TEST_P(VulkanExternalImageTest, ShouldClearOpaqueFdRGBA8)
{ {
......
...@@ -277,6 +277,11 @@ void VulkanExternalHelper::initialize() ...@@ -277,6 +277,11 @@ void VulkanExternalHelper::initialize()
vkGetInstanceProcAddr(mInstance, "vkGetPhysicalDeviceImageFormatProperties2")); vkGetInstanceProcAddr(mInstance, "vkGetPhysicalDeviceImageFormatProperties2"));
vkGetMemoryFdKHR = reinterpret_cast<PFN_vkGetMemoryFdKHR>( vkGetMemoryFdKHR = reinterpret_cast<PFN_vkGetMemoryFdKHR>(
vkGetInstanceProcAddr(mInstance, "vkGetMemoryFdKHR")); vkGetInstanceProcAddr(mInstance, "vkGetMemoryFdKHR"));
vkGetSemaphoreFdKHR = reinterpret_cast<PFN_vkGetSemaphoreFdKHR>(
vkGetInstanceProcAddr(mInstance, "vkGetSemaphoreFdKHR"));
vkGetPhysicalDeviceExternalSemaphorePropertiesKHR =
reinterpret_cast<PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR>(
vkGetInstanceProcAddr(mInstance, "vkGetPhysicalDeviceExternalSemaphorePropertiesKHR"));
} }
bool VulkanExternalHelper::canCreateImageOpaqueFd(VkFormat format, bool VulkanExternalHelper::canCreateImageOpaqueFd(VkFormat format,
...@@ -331,8 +336,8 @@ bool VulkanExternalHelper::canCreateImageOpaqueFd(VkFormat format, ...@@ -331,8 +336,8 @@ bool VulkanExternalHelper::canCreateImageOpaqueFd(VkFormat format,
{ {
return false; return false;
} }
if (!(externalImageFormatProperties.externalMemoryProperties.externalMemoryFeatures & if ((externalImageFormatProperties.externalMemoryProperties.externalMemoryFeatures &
kRequiredFeatures)) kRequiredFeatures) != kRequiredFeatures)
{ {
return false; return false;
} }
...@@ -434,4 +439,62 @@ VkResult VulkanExternalHelper::exportMemoryOpaqueFd(VkDeviceMemory deviceMemory, ...@@ -434,4 +439,62 @@ VkResult VulkanExternalHelper::exportMemoryOpaqueFd(VkDeviceMemory deviceMemory,
return vkGetMemoryFdKHR(mDevice, &memoryGetFdInfo, fd); return vkGetMemoryFdKHR(mDevice, &memoryGetFdInfo, fd);
} }
bool VulkanExternalHelper::canCreateSemaphoreOpaqueFd() const
{
if (!mHasExternalSemaphoreFd || !vkGetPhysicalDeviceExternalSemaphorePropertiesKHR)
{
return false;
}
VkPhysicalDeviceExternalSemaphoreInfo externalSemaphoreInfo = {
/* .sType = */ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
/* .pNext = */ nullptr,
/* .handleType = */ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT,
};
VkExternalSemaphoreProperties externalSemaphoreProperties = {};
vkGetPhysicalDeviceExternalSemaphorePropertiesKHR(mPhysicalDevice, &externalSemaphoreInfo,
&externalSemaphoreProperties);
constexpr VkExternalSemaphoreFeatureFlags kRequiredFeatures =
VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT | VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT;
if ((externalSemaphoreProperties.externalSemaphoreFeatures & kRequiredFeatures) !=
kRequiredFeatures)
{
return false;
}
return true;
}
VkResult VulkanExternalHelper::createSemaphoreOpaqueFd(VkSemaphore *semaphore)
{
VkExportSemaphoreCreateInfo exportSemaphoreCreateInfo = {
/* .sType = */ VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
/* .pNext = */ nullptr,
/* .handleTypes = */ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT,
};
VkSemaphoreCreateInfo semaphoreCreateInfo = {
/* .sType = */ VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
/* .pNext = */ &exportSemaphoreCreateInfo,
/* .flags = */ 0,
};
return vkCreateSemaphore(mDevice, &semaphoreCreateInfo, nullptr, semaphore);
}
VkResult VulkanExternalHelper::exportSemaphoreOpaqueFd(VkSemaphore semaphore, int *fd)
{
VkSemaphoreGetFdInfoKHR semaphoreGetFdInfo = {
/* .sType = */ VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR,
/* .pNext = */ nullptr,
/* .semaphore = */ semaphore,
/* .handleType = */ VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT,
};
return vkGetSemaphoreFdKHR(mDevice, &semaphoreGetFdInfo, fd);
}
} // namespace angle } // namespace angle
...@@ -35,6 +35,11 @@ class VulkanExternalHelper ...@@ -35,6 +35,11 @@ class VulkanExternalHelper
VkDeviceSize *deviceMemorySizeOut); VkDeviceSize *deviceMemorySizeOut);
VkResult exportMemoryOpaqueFd(VkDeviceMemory deviceMemory, int *fd); VkResult exportMemoryOpaqueFd(VkDeviceMemory deviceMemory, int *fd);
// VK_KHR_external_semaphore_fd
bool canCreateSemaphoreOpaqueFd() const;
VkResult createSemaphoreOpaqueFd(VkSemaphore *semaphore);
VkResult exportSemaphoreOpaqueFd(VkSemaphore semaphore, int *fd);
private: private:
VkInstance mInstance = VK_NULL_HANDLE; VkInstance mInstance = VK_NULL_HANDLE;
VkPhysicalDevice mPhysicalDevice = VK_NULL_HANDLE; VkPhysicalDevice mPhysicalDevice = VK_NULL_HANDLE;
...@@ -50,6 +55,9 @@ class VulkanExternalHelper ...@@ -50,6 +55,9 @@ class VulkanExternalHelper
PFN_vkGetPhysicalDeviceImageFormatProperties2 vkGetPhysicalDeviceImageFormatProperties2 = PFN_vkGetPhysicalDeviceImageFormatProperties2 vkGetPhysicalDeviceImageFormatProperties2 =
nullptr; nullptr;
PFN_vkGetMemoryFdKHR vkGetMemoryFdKHR = nullptr; PFN_vkGetMemoryFdKHR vkGetMemoryFdKHR = nullptr;
PFN_vkGetSemaphoreFdKHR vkGetSemaphoreFdKHR = nullptr;
PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR
vkGetPhysicalDeviceExternalSemaphorePropertiesKHR = nullptr;
}; };
} // namespace angle } // namespace angle
......
...@@ -101,6 +101,11 @@ class GLSampler : public GLWrapper ...@@ -101,6 +101,11 @@ class GLSampler : public GLWrapper
public: public:
GLSampler() : GLWrapper(&glGenSamplers, &glDeleteSamplers) {} GLSampler() : GLWrapper(&glGenSamplers, &glDeleteSamplers) {}
}; };
class GLSemaphore : public GLWrapper
{
public:
GLSemaphore() : GLWrapper(&glGenSemaphoresEXT, &glDeleteSemaphoresEXT) {}
};
class GLTransformFeedback : public GLWrapper class GLTransformFeedback : public GLWrapper
{ {
public: public:
......
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