Commit e20f36f4 by Jeff Vigil Committed by Commit Bot

EGL: Implement EGL_ANDROID_native_fence_sync on vulkan

Check the following - 1. Vulkan ICD supports VK_KHR_external_fence_fd 2. ExternalFenceProperties and ExternalSemaphoreProperties support Android FD. eglCreateSync - if FD was provided import to VkFence, else create VkFence with new FD and then flush and submit VkFence on next vkQueueSubmit. eglGetSyncAttrib - for status call vkGetFenceStatus. eglDupNativeFenceFdANDROID - return FD from vkGetFenceFD call. eglClientWaitSync - call vkWaitForFences. eglWaitSync - dup FD, create VkSemaphore and import FD, then flush() and add VkSemaphore to next vkQueueSubmit as a waiting semaphore. Extended end2end test suite with nativefence test cases. Bug: angleproject:2517 Test: angle_end2end_tests --gtest_filter=EGLSyncTest.AndroidNativeFence_* Change-Id: I8f6a6f4c3d71d83007f662b78377aa015a740035 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2026177 Commit-Queue: Mohan Maiya <m.maiya@samsung.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 963759a3
......@@ -120,6 +120,16 @@ struct FeaturesVk : FeatureSetBase
"supports_external_memory_fuchsia", FeatureCategory::VulkanFeatures,
"VkDevice supports the VK_FUCHSIA_external_memory extension", &members};
// Whether the VkDevice supports the VK_KHR_external_fence_capabilities extension.
Feature supportsExternalFenceCapabilities = {
"supports_external_fence_capabilities", FeatureCategory::VulkanFeatures,
"VkDevice supports the VK_KHR_external_fence_capabilities extension", &members};
// Whether the VkDevice supports the VK_KHR_external_semaphore_capabilities extension.
Feature supportsExternalSemaphoreCapabilities = {
"supports_external_semaphore_capabilities", FeatureCategory::VulkanFeatures,
"VkDevice supports the VK_KHR_external_semaphore_capabilities 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 = {
......@@ -132,6 +142,19 @@ struct FeaturesVk : FeatureSetBase
"supports_external_semaphore_fuchsia", FeatureCategory::VulkanFeatures,
"VkDevice supports the VK_FUCHSIA_external_semaphore extension", &members};
// Whether the VkDevice supports the VK_KHR_external_fence_fd extension, on which the
// EGL_ANDROID_native_fence extension can be layered.
Feature supportsExternalFenceFd = {"supports_external_fence_fd",
FeatureCategory::VulkanFeatures,
"VkDevice supports the VK_KHR_external_fence_fd extension",
&members, "http://anglebug.com/2517"};
// Whether the VkDevice can support EGL_ANDROID_native_fence_sync extension.
Feature supportsAndroidNativeFenceSync = {
"supports_android_native_fence_sync", FeatureCategory::VulkanFeatures,
"VkDevice supports the EGL_ANDROID_native_fence_sync extension", &members,
"http://anglebug.com/2517"};
// 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.
......
......@@ -21,9 +21,21 @@ Sync::Sync(rx::EGLImplFactory *factory, EGLenum type, const AttributeMap &attrib
: mFence(factory->createSync(attribs)),
mLabel(nullptr),
mType(type),
mCondition(EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR),
mNativeFenceFD(
attribs.getAsInt(EGL_SYNC_NATIVE_FENCE_FD_ANDROID, EGL_NO_NATIVE_FENCE_FD_ANDROID))
{}
{
// Per extension spec: Signaling Condition.
// "If the EGL_SYNC_NATIVE_FENCE_FD_ANDROID attribute is not
// EGL_NO_NATIVE_FENCE_FD_ANDROID then the EGL_SYNC_CONDITION_KHR attribute
// is set to EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID and the EGL_SYNC_STATUS_KHR
// attribute is set to reflect the signal status of the native fence object.
if ((mType == EGL_SYNC_NATIVE_FENCE_ANDROID) &&
(mNativeFenceFD != EGL_NO_NATIVE_FENCE_FD_ANDROID))
{
mCondition = EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID;
}
}
void Sync::onDestroy(const Display *display)
{
......
......@@ -61,7 +61,7 @@ class Sync final : public angle::RefCountObject<Display, angle::Result>, public
EGLLabelKHR mLabel;
EGLenum mType;
static constexpr EGLint mCondition = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
EGLint mCondition;
EGLint mNativeFenceFD;
};
......
......@@ -48,7 +48,7 @@ class EGLSyncImpl : angle::NonCopyable
EGLint flags) = 0;
virtual egl::Error getStatus(const egl::Display *display, EGLint *outStatus) = 0;
virtual egl::Error dupNativeFenceFD(const egl::Display *display, EGLint *result) const = 0;
virtual egl::Error dupNativeFenceFD(const egl::Display *display, EGLint *fdOut) const = 0;
};
} // namespace rx
......
......@@ -221,6 +221,11 @@ void DisplayVk::generateExtensions(egl::DisplayExtensions *outExtensions) const
outExtensions->contextPriority = !getRenderer()->getFeatures().allocateNonZeroMemory.enabled;
outExtensions->noConfigContext = true;
#if defined(ANGLE_PLATFORM_ANDROID)
outExtensions->nativeFenceSyncANDROID =
getRenderer()->getFeatures().supportsAndroidNativeFenceSync.enabled;
#endif // defined(ANGLE_PLATFORM_ANDROID)
#if defined(ANGLE_PLATFORM_GGP)
outExtensions->ggpStreamDescriptor = true;
outExtensions->swapWithFrameToken = true;
......
......@@ -563,6 +563,54 @@ gl::Version LimitVersionTo(const gl::Version &current, const gl::Version &lower)
{
return std::min(current, lower);
}
ANGLE_MAYBE_UNUSED bool FencePropertiesCompatibleWithAndroid(
const VkExternalFenceProperties &externalFenceProperties)
{
// handleType here is the external fence type -
// we want type compatible with creating and export/dup() Android FD
// Imported handleType that can be exported - need for vkGetFenceFdKHR()
if ((externalFenceProperties.exportFromImportedHandleTypes &
VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR) == 0)
{
return false;
}
// HandleTypes which can be specified at creating a fence
if ((externalFenceProperties.compatibleHandleTypes &
VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR) == 0)
{
return false;
}
constexpr VkExternalFenceFeatureFlags kFeatureFlags =
(VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT_KHR |
VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT_KHR);
if ((externalFenceProperties.externalFenceFeatures & kFeatureFlags) != kFeatureFlags)
{
return false;
}
return true;
}
ANGLE_MAYBE_UNUSED bool SemaphorePropertiesCompatibleWithAndroid(
const VkExternalSemaphoreProperties &externalSemaphoreProperties)
{
// handleType here is the external semaphore type -
// we want type compatible with importing an Android FD
constexpr VkExternalSemaphoreFeatureFlags kFeatureFlags =
(VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR);
if ((externalSemaphoreProperties.externalSemaphoreFeatures & kFeatureFlags) != kFeatureFlags)
{
return false;
}
return true;
}
} // namespace
// RendererVk implementation.
......@@ -576,6 +624,8 @@ RendererVk::RendererVk()
mDebugUtilsMessenger(VK_NULL_HANDLE),
mDebugReportCallback(VK_NULL_HANDLE),
mPhysicalDevice(VK_NULL_HANDLE),
mExternalFenceProperties{},
mExternalSemaphoreProperties{},
mCurrentQueueFamilyIndex(std::numeric_limits<uint32_t>::max()),
mMaxVertexAttribDivisor(1),
mMaxVertexAttribStride(0),
......@@ -1044,6 +1094,32 @@ void RendererVk::queryDeviceExtensionFeatures(const ExtensionNameList &deviceExt
vkGetPhysicalDeviceFeatures2KHR(mPhysicalDevice, &deviceFeatures);
vkGetPhysicalDeviceProperties2KHR(mPhysicalDevice, &deviceProperties);
// Fence properties
if (mFeatures.supportsExternalFenceCapabilities.enabled)
{
mExternalFenceProperties.sType = VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES;
VkPhysicalDeviceExternalFenceInfo externalFenceInfo = {};
externalFenceInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO;
externalFenceInfo.handleType = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR;
vkGetPhysicalDeviceExternalFencePropertiesKHR(mPhysicalDevice, &externalFenceInfo,
&mExternalFenceProperties);
}
// Semaphore properties
if (mFeatures.supportsExternalSemaphoreCapabilities.enabled)
{
mExternalSemaphoreProperties.sType = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES;
VkPhysicalDeviceExternalSemaphoreInfo externalSemaphoreInfo = {};
externalSemaphoreInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO;
externalSemaphoreInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR;
vkGetPhysicalDeviceExternalSemaphorePropertiesKHR(mPhysicalDevice, &externalSemaphoreInfo,
&mExternalSemaphoreProperties);
}
// Clean up pNext chains
mLineRasterizationFeatures.pNext = nullptr;
mProvokingVertexFeatures.pNext = nullptr;
......@@ -1198,11 +1274,26 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
enabledDeviceExtensions.push_back(VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME);
}
if (getFeatures().supportsExternalSemaphoreCapabilities.enabled)
{
enabledDeviceExtensions.push_back(VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME);
}
if (getFeatures().supportsExternalFenceCapabilities.enabled)
{
enabledDeviceExtensions.push_back(VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME);
}
if (getFeatures().supportsExternalSemaphoreFd.enabled)
{
enabledDeviceExtensions.push_back(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME);
}
if (getFeatures().supportsExternalFenceFd.enabled)
{
enabledDeviceExtensions.push_back(VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME);
}
if (getFeatures().supportsExternalSemaphoreFuchsia.enabled)
{
enabledDeviceExtensions.push_back(VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME);
......@@ -1636,6 +1727,14 @@ void RendererVk::initFeatures(DisplayVk *displayVk, const ExtensionNameList &dev
ExtensionFound(VK_FUCHSIA_EXTERNAL_MEMORY_EXTENSION_NAME, deviceExtensionNames));
ANGLE_FEATURE_CONDITION(
&mFeatures, supportsExternalFenceCapabilities,
ExtensionFound(VK_KHR_EXTERNAL_FENCE_CAPABILITIES_EXTENSION_NAME, deviceExtensionNames));
ANGLE_FEATURE_CONDITION(&mFeatures, supportsExternalSemaphoreCapabilities,
ExtensionFound(VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME,
deviceExtensionNames));
ANGLE_FEATURE_CONDITION(
&mFeatures, supportsExternalSemaphoreFd,
ExtensionFound(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, deviceExtensionNames));
......@@ -1644,6 +1743,29 @@ void RendererVk::initFeatures(DisplayVk *displayVk, const ExtensionNameList &dev
ExtensionFound(VK_FUCHSIA_EXTERNAL_SEMAPHORE_EXTENSION_NAME, deviceExtensionNames));
ANGLE_FEATURE_CONDITION(
&mFeatures, supportsExternalFenceFd,
ExtensionFound(VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME, deviceExtensionNames));
#if defined(ANGLE_PLATFORM_ANDROID)
if (mFeatures.supportsExternalFenceCapabilities.enabled &&
mFeatures.supportsExternalSemaphoreCapabilities.enabled)
{
ANGLE_FEATURE_CONDITION(
&mFeatures, supportsAndroidNativeFenceSync,
(mFeatures.supportsExternalFenceFd.enabled &&
FencePropertiesCompatibleWithAndroid(mExternalFenceProperties) &&
mFeatures.supportsExternalSemaphoreFd.enabled &&
SemaphorePropertiesCompatibleWithAndroid(mExternalSemaphoreProperties)));
}
else
{
ANGLE_FEATURE_CONDITION(&mFeatures, supportsAndroidNativeFenceSync,
(mFeatures.supportsExternalFenceFd.enabled &&
mFeatures.supportsExternalSemaphoreFd.enabled));
}
#endif // defined(ANGLE_PLATFORM_ANDROID)
ANGLE_FEATURE_CONDITION(
&mFeatures, supportsShaderStencilExport,
ExtensionFound(VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME, deviceExtensionNames));
......
......@@ -287,6 +287,8 @@ class RendererVk : angle::NonCopyable
VkPhysicalDevice mPhysicalDevice;
VkPhysicalDeviceProperties mPhysicalDeviceProperties;
VkPhysicalDeviceFeatures mPhysicalDeviceFeatures;
VkExternalFenceProperties mExternalFenceProperties;
VkExternalSemaphoreProperties mExternalSemaphoreProperties;
VkPhysicalDeviceLineRasterizationFeaturesEXT mLineRasterizationFeatures;
VkPhysicalDeviceProvokingVertexFeaturesEXT mProvokingVertexFeatures;
VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT mVertexAttributeDivisorFeatures;
......
......@@ -23,24 +23,33 @@ namespace rx
{
namespace vk
{
// The behaviors of SyncImpl and EGLSyncImpl as fence syncs (only supported type) are currently
// Represents an invalid native fence FD.
constexpr int kInvalidFenceFd = EGL_NO_NATIVE_FENCE_FD_ANDROID;
// Implementation of fence types - glFenceSync, and EGLSync(EGL_SYNC_FENCE_KHR).
// The behaviors of SyncVk and EGLFenceSyncVk as fence syncs are currently
// identical for the Vulkan backend, and this class implements both interfaces.
class SyncHelper : public vk::Resource
{
public:
SyncHelper();
~SyncHelper();
void releaseToRenderer(RendererVk *renderer);
angle::Result initialize(ContextVk *contextVk);
angle::Result clientWait(Context *context,
ContextVk *contextVk,
bool flushCommands,
uint64_t timeout,
VkResult *outResult);
angle::Result serverWait(ContextVk *contextVk);
angle::Result getStatus(Context *context, bool *signaled);
virtual ~SyncHelper();
virtual void releaseToRenderer(RendererVk *renderer);
virtual angle::Result initialize(ContextVk *contextVk);
virtual angle::Result clientWait(Context *context,
ContextVk *contextVk,
bool flushCommands,
uint64_t timeout,
VkResult *outResult);
virtual angle::Result serverWait(ContextVk *contextVk);
virtual angle::Result getStatus(Context *context, bool *signaled) const;
virtual angle::Result dupNativeFenceFD(Context *context, int *fdOut) const
{
return angle::Result::Stop;
}
private:
// The vkEvent that's signaled on `init` and can be waited on in `serverWait`, or queried with
......@@ -50,8 +59,33 @@ class SyncHelper : public vk::Resource
// `clientWait` waits on this fence.
Shared<Fence> mFence;
};
// Implementation of sync types: EGLSync(EGL_SYNC_ANDROID_NATIVE_FENCE_ANDROID).
class SyncHelperNativeFence : public SyncHelper
{
public:
SyncHelperNativeFence() {}
~SyncHelperNativeFence() override {}
void releaseToRenderer(RendererVk *renderer) override;
angle::Result initializeWithFd(ContextVk *contextVk, int inFd);
angle::Result clientWait(Context *context,
ContextVk *contextVk,
bool flushCommands,
uint64_t timeout,
VkResult *outResult) override;
angle::Result serverWait(ContextVk *contextVk) override;
angle::Result getStatus(Context *context, bool *signaled) const override;
angle::Result dupNativeFenceFD(Context *context, int *fdOut) const override;
private:
vk::Fence mFenceWithFd;
};
} // namespace vk
// Implementor for glFenceSync.
class SyncVk final : public SyncImpl
{
public:
......@@ -71,9 +105,10 @@ class SyncVk final : public SyncImpl
angle::Result getStatus(const gl::Context *context, GLint *outResult) override;
private:
vk::SyncHelper mFenceSync;
vk::SyncHelper mSyncHelper;
};
// Implementor for EGLSync.
class EGLSyncVk final : public EGLSyncImpl
{
public:
......@@ -95,10 +130,12 @@ class EGLSyncVk final : public EGLSyncImpl
EGLint flags) override;
egl::Error getStatus(const egl::Display *display, EGLint *outStatus) override;
egl::Error dupNativeFenceFD(const egl::Display *display, EGLint *result) const override;
egl::Error dupNativeFenceFD(const egl::Display *display, EGLint *fdOut) const override;
private:
vk::SyncHelper mFenceSync;
EGLenum mType;
vk::SyncHelper *mSyncHelper; // SyncHelper or SyncHelperNativeFence decided at run-time.
const egl::AttributeMap &mAttribs;
};
} // namespace rx
......
......@@ -427,6 +427,8 @@ class Semaphore final : public WrappedObject<Semaphore, VkSemaphore>
void destroy(VkDevice device);
VkResult init(VkDevice device);
VkResult init(VkDevice device, const VkSemaphoreCreateInfo &createInfo);
VkResult importFd(VkDevice device, const VkImportSemaphoreFdInfoKHR &importFdInfo) const;
};
class Framebuffer final : public WrappedObject<Framebuffer, VkFramebuffer>
......@@ -600,6 +602,8 @@ class Fence final : public WrappedObject<Fence, VkFence>
VkResult reset(VkDevice device);
VkResult getStatus(VkDevice device) const;
VkResult wait(VkDevice device, uint64_t timeout) const;
VkResult importFd(VkDevice device, const VkImportFenceFdInfoKHR &importFenceFdInfo) const;
VkResult exportFd(VkDevice device, const VkFenceGetFdInfoKHR &fenceGetFdInfo, int *outFd) const;
};
class QueryPool final : public WrappedObject<QueryPool, VkQueryPool>
......@@ -1263,6 +1267,19 @@ ANGLE_INLINE VkResult Semaphore::init(VkDevice device)
return vkCreateSemaphore(device, &semaphoreInfo, nullptr, &mHandle);
}
ANGLE_INLINE VkResult Semaphore::init(VkDevice device, const VkSemaphoreCreateInfo &createInfo)
{
ASSERT(valid());
return vkCreateSemaphore(device, &createInfo, nullptr, &mHandle);
}
ANGLE_INLINE VkResult Semaphore::importFd(VkDevice device,
const VkImportSemaphoreFdInfoKHR &importFdInfo) const
{
ASSERT(valid());
return vkImportSemaphoreFdKHR(device, &importFdInfo);
}
// Framebuffer implementation.
ANGLE_INLINE void Framebuffer::destroy(VkDevice device)
{
......@@ -1675,6 +1692,21 @@ ANGLE_INLINE VkResult Fence::wait(VkDevice device, uint64_t timeout) const
return vkWaitForFences(device, 1, &mHandle, true, timeout);
}
ANGLE_INLINE VkResult Fence::importFd(VkDevice device,
const VkImportFenceFdInfoKHR &importFenceFdInfo) const
{
ASSERT(valid());
return vkImportFenceFdKHR(device, &importFenceFdInfo);
}
ANGLE_INLINE VkResult Fence::exportFd(VkDevice device,
const VkFenceGetFdInfoKHR &fenceGetFdInfo,
int *fdOut) const
{
ASSERT(valid());
return vkGetFenceFdKHR(device, &fenceGetFdInfo, fdOut);
}
// QueryPool implementation.
ANGLE_INLINE void QueryPool::destroy(VkDevice device)
{
......
......@@ -4221,12 +4221,6 @@ Error ValidateDupNativeFenceFDANDROID(const Display *display, const Sync *sync)
ANGLE_TRY(ValidateSync(display, sync));
if (sync->getNativeFenceFD() == EGL_NO_NATIVE_FENCE_FD_ANDROID)
{
return EglBadParameter() << "EGL_NATIVE_FENCE_FD_ANDROID attribute of sync is "
"EGL_NO_NATIVE_FENCE_FD_ANDROID";
}
return NoError();
}
......
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