Commit de4611c9 by Xiaoxuan Liu Committed by Commit Bot

Vulkan: Update eglDupNativeFenceFDANDROID() implementation.

When exporting vkfence FD with vkGetFenceFdKHR() in SYNC_FD semantic, vkfence could be reset. Dup and store the SYNC_FD created vkfence's FD in SyncHelperNativeFence by exporting FD during initializeWithFd() meanwhile make the eglDupNativeFenceFDANDROID() only dup the mNativeFenceFd in SyncHelperNativeFence. Test: angle_end2end_tests --gtest_filter=EGLSyncTest.AndroidNativeFence_* Bug: angleproject:2517 Change-Id: I354185d26d0fda72baeb61702c879ed5665db6ec Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2230062Reviewed-by: 's avatarJeff Vigil <j.vigil@samsung.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent 9db618cc
...@@ -15,6 +15,12 @@ ...@@ -15,6 +15,12 @@
#include "libANGLE/renderer/vulkan/ContextVk.h" #include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/DisplayVk.h" #include "libANGLE/renderer/vulkan/DisplayVk.h"
#if !defined(ANGLE_PLATFORM_WINDOWS)
# include <unistd.h>
#else
# include <io.h>
#endif
namespace rx namespace rx
{ {
namespace vk namespace vk
...@@ -121,61 +127,57 @@ angle::Result SyncHelper::getStatus(Context *context, bool *signaled) const ...@@ -121,61 +127,57 @@ angle::Result SyncHelper::getStatus(Context *context, bool *signaled) const
return angle::Result::Continue; return angle::Result::Continue;
} }
SyncHelperNativeFence::SyncHelperNativeFence() : mNativeFenceFd(kInvalidFenceFd) {}
SyncHelperNativeFence::~SyncHelperNativeFence()
{
if (mNativeFenceFd != kInvalidFenceFd)
{
close(mNativeFenceFd);
}
}
void SyncHelperNativeFence::releaseToRenderer(RendererVk *renderer) void SyncHelperNativeFence::releaseToRenderer(RendererVk *renderer)
{ {
renderer->collectGarbageAndReinit(&mUse, &mFenceWithFd); renderer->collectGarbageAndReinit(&mUse, &mFenceWithFd);
} }
// Note: Having mFenceWithFd hold the FD, so that ownership is with ICD. Any call to clientWait // Note: Having mFenceWithFd hold the FD, so that ownership is with ICD. Meanwhile store a dup
// of FD in SyncHelperNativeFence for further reference, i.e. dup of FD. Any call to clientWait
// or serverWait will ensure the FD or dup of FD goes to application or ICD. At release, above // or serverWait will ensure the FD or dup of FD goes to application or ICD. At release, above
// it's Garbage collected/destroyed. Otherwise can't time when to close(fd); // it's Garbage collected/destroyed. Otherwise can't time when to close(fd);
angle::Result SyncHelperNativeFence::initializeWithFd(ContextVk *contextVk, int inFd) angle::Result SyncHelperNativeFence::initializeWithFd(ContextVk *contextVk, int inFd)
{ {
ASSERT(inFd >= kInvalidFenceFd);
RendererVk *renderer = contextVk->getRenderer(); RendererVk *renderer = contextVk->getRenderer();
VkDevice device = renderer->getDevice(); VkDevice device = renderer->getDevice();
DeviceScoped<vk::Fence> fence(device);
VkExportFenceCreateInfo exportCreateInfo = {};
exportCreateInfo.sType = VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO;
exportCreateInfo.pNext = nullptr;
exportCreateInfo.handleTypes = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR;
// Create fenceInfo base. // Create fenceInfo base.
VkFenceCreateInfo fenceCreateInfo = {}; VkFenceCreateInfo fenceCreateInfo = {};
fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fenceCreateInfo.flags = 0; fenceCreateInfo.flags = 0;
fenceCreateInfo.pNext = &exportCreateInfo;
// Initialize/create a VkFence handle
ANGLE_VK_TRY(contextVk, fence.get().init(device, fenceCreateInfo));
int importFenceFd = kInvalidFenceFd;
// If valid FD provided by application - import it to fence. // If valid FD provided by application - import it to fence.
if (inFd > kInvalidFenceFd) if (inFd > kInvalidFenceFd)
{ {
// Initialize/create a VkFence handle importFenceFd = inFd;
ANGLE_VK_TRY(contextVk, mFenceWithFd.init(device, fenceCreateInfo));
// Import FD - after creating fence.
VkImportFenceFdInfoKHR importFenceFdInfo = {};
importFenceFdInfo.sType = VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR;
importFenceFdInfo.pNext = nullptr;
importFenceFdInfo.fence = mFenceWithFd.getHandle();
importFenceFdInfo.flags = VK_FENCE_IMPORT_TEMPORARY_BIT_KHR;
importFenceFdInfo.handleType = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT;
importFenceFdInfo.fd = inFd;
VkResult result = mFenceWithFd.importFd(device, importFenceFdInfo);
if (result != VK_SUCCESS)
{
mFenceWithFd.destroy(device);
ANGLE_VK_TRY(contextVk, result);
}
retain(&contextVk->getResourceUseList());
return angle::Result::Continue;
} }
// If invalid FD provided by application - create one with fence. // If invalid FD provided by application - create one with fence.
if (inFd == kInvalidFenceFd) else
{ {
// Attach export FD-handleType, pNext struct, to indicate we may want to export FD.
VkExportFenceCreateInfo exportCreateInfo = {};
exportCreateInfo.sType = VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO;
exportCreateInfo.handleTypes = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR;
fenceCreateInfo.pNext = &exportCreateInfo;
// Initialize/create a VkFence handle
ANGLE_VK_TRY(contextVk, mFenceWithFd.init(device, fenceCreateInfo));
/* /*
Spec: "When a fence sync object is created or when an EGL native fence sync Spec: "When a fence sync object is created or when an EGL native fence sync
object is created with the EGL_SYNC_NATIVE_FENCE_FD_ANDROID attribute set to object is created with the EGL_SYNC_NATIVE_FENCE_FD_ANDROID attribute set to
...@@ -191,16 +193,37 @@ angle::Result SyncHelperNativeFence::initializeWithFd(ContextVk *contextVk, int ...@@ -191,16 +193,37 @@ angle::Result SyncHelperNativeFence::initializeWithFd(ContextVk *contextVk, int
Serial serialOut; Serial serialOut;
VkSubmitInfo submitInfo = {}; VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
if (renderer->queueSubmit(contextVk, contextVk->getPriority(), submitInfo, &mFenceWithFd, ANGLE_TRY(renderer->queueSubmit(contextVk, contextVk->getPriority(), submitInfo,
&serialOut) != angle::Result::Continue) &fence.get(), &serialOut));
{
mFenceWithFd.destroy(device); VkFenceGetFdInfoKHR fenceGetFdInfo = {};
return angle::Result::Stop; fenceGetFdInfo.sType = VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR;
} fenceGetFdInfo.fence = fence.get().getHandle();
return angle::Result::Continue; fenceGetFdInfo.handleType = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR;
ANGLE_VK_TRY(contextVk, fence.get().exportFd(device, fenceGetFdInfo, &importFenceFd));
} }
// Should not get here
return angle::Result::Stop; // Spec: Importing a fence payload from a file descriptor transfers ownership of the file
// descriptor from the application to the Vulkan implementation. The application must not
// perform any operations on the file descriptor after a successful import.
// Make a dup of importFenceFd before tranfering ownership to created fence.
mNativeFenceFd = dup(importFenceFd);
// Import FD - after creating fence.
VkImportFenceFdInfoKHR importFenceFdInfo = {};
importFenceFdInfo.sType = VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR;
importFenceFdInfo.pNext = nullptr;
importFenceFdInfo.fence = fence.get().getHandle();
importFenceFdInfo.flags = VK_FENCE_IMPORT_TEMPORARY_BIT_KHR;
importFenceFdInfo.handleType = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT;
importFenceFdInfo.fd = importFenceFd;
ANGLE_VK_TRY(contextVk, fence.get().importFd(device, importFenceFdInfo));
mFenceWithFd = fence.release();
retain(&contextVk->getResourceUseList());
return angle::Result::Continue;
} }
angle::Result SyncHelperNativeFence::clientWait(Context *context, angle::Result SyncHelperNativeFence::clientWait(Context *context,
...@@ -254,14 +277,6 @@ angle::Result SyncHelperNativeFence::serverWait(ContextVk *contextVk) ...@@ -254,14 +277,6 @@ angle::Result SyncHelperNativeFence::serverWait(ContextVk *contextVk)
RendererVk *renderer = contextVk->getRenderer(); RendererVk *renderer = contextVk->getRenderer();
VkDevice device = renderer->getDevice(); VkDevice device = renderer->getDevice();
// Export an FD from mFenceWithFd
int fenceFd = kInvalidFenceFd;
VkFenceGetFdInfoKHR getFdInfo = {};
getFdInfo.sType = VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR;
getFdInfo.fence = mFenceWithFd.getHandle();
getFdInfo.handleType = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR;
ANGLE_VK_TRY(contextVk, mFenceWithFd.exportFd(device, getFdInfo, &fenceFd));
DeviceScoped<Semaphore> waitSemaphore(device); DeviceScoped<Semaphore> waitSemaphore(device);
// Wait semaphore for next vkQueueSubmit(). // Wait semaphore for next vkQueueSubmit().
// Create a Semaphore with imported fenceFd. // Create a Semaphore with imported fenceFd.
...@@ -272,7 +287,7 @@ angle::Result SyncHelperNativeFence::serverWait(ContextVk *contextVk) ...@@ -272,7 +287,7 @@ angle::Result SyncHelperNativeFence::serverWait(ContextVk *contextVk)
importFdInfo.semaphore = waitSemaphore.get().getHandle(); importFdInfo.semaphore = waitSemaphore.get().getHandle();
importFdInfo.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR; importFdInfo.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR;
importFdInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR; importFdInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR;
importFdInfo.fd = fenceFd; importFdInfo.fd = dup(mNativeFenceFd);
ANGLE_VK_TRY(contextVk, waitSemaphore.get().importFd(device, importFdInfo)); ANGLE_VK_TRY(contextVk, waitSemaphore.get().importFd(device, importFdInfo));
// Flush current work, block after current pending commands. // Flush current work, block after current pending commands.
...@@ -298,16 +313,13 @@ angle::Result SyncHelperNativeFence::getStatus(Context *context, bool *signaled) ...@@ -298,16 +313,13 @@ angle::Result SyncHelperNativeFence::getStatus(Context *context, bool *signaled)
angle::Result SyncHelperNativeFence::dupNativeFenceFD(Context *context, int *fdOut) const angle::Result SyncHelperNativeFence::dupNativeFenceFD(Context *context, int *fdOut) const
{ {
if (!mFenceWithFd.valid()) if (!mFenceWithFd.valid() || mNativeFenceFd == kInvalidFenceFd)
{ {
return angle::Result::Stop; return angle::Result::Stop;
} }
VkFenceGetFdInfoKHR fenceGetFdInfo = {}; *fdOut = dup(mNativeFenceFd);
fenceGetFdInfo.sType = VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR;
fenceGetFdInfo.fence = mFenceWithFd.getHandle();
fenceGetFdInfo.handleType = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR;
ANGLE_VK_TRY(context, mFenceWithFd.exportFd(context->getDevice(), fenceGetFdInfo, fdOut));
return angle::Result::Continue; return angle::Result::Continue;
} }
......
...@@ -64,8 +64,8 @@ class SyncHelper : public vk::Resource ...@@ -64,8 +64,8 @@ class SyncHelper : public vk::Resource
class SyncHelperNativeFence : public SyncHelper class SyncHelperNativeFence : public SyncHelper
{ {
public: public:
SyncHelperNativeFence() {} SyncHelperNativeFence();
~SyncHelperNativeFence() override {} ~SyncHelperNativeFence() override;
void releaseToRenderer(RendererVk *renderer) override; void releaseToRenderer(RendererVk *renderer) override;
...@@ -81,6 +81,7 @@ class SyncHelperNativeFence : public SyncHelper ...@@ -81,6 +81,7 @@ class SyncHelperNativeFence : public SyncHelper
private: private:
vk::Fence mFenceWithFd; vk::Fence mFenceWithFd;
int mNativeFenceFd;
}; };
} // namespace vk } // namespace vk
......
...@@ -294,7 +294,7 @@ TEST_P(EGLSyncTest, AndroidNativeFence_ClientWait) ...@@ -294,7 +294,7 @@ TEST_P(EGLSyncTest, AndroidNativeFence_ClientWait)
// Create work to do // Create work to do
glClearColor(0.0f, 1.0f, 0.0f, 1.0f); glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
glFinish(); glFlush();
// Wait for draw to complete // Wait for draw to complete
EXPECT_EQ(EGL_CONDITION_SATISFIED, EXPECT_EQ(EGL_CONDITION_SATISFIED,
...@@ -312,7 +312,7 @@ TEST_P(EGLSyncTest, AndroidNativeFence_ClientWait) ...@@ -312,7 +312,7 @@ TEST_P(EGLSyncTest, AndroidNativeFence_ClientWait)
TEST_P(EGLSyncTest, AndroidNativeFence_WaitSync) TEST_P(EGLSyncTest, AndroidNativeFence_WaitSync)
{ {
ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension()); ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension());
ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension() || !hasGLSyncExtension()); ANGLE_SKIP_TEST_IF(!hasWaitSyncExtension() || !hasGLSyncExtension());
ANGLE_SKIP_TEST_IF(!hasAndroidNativeFenceSyncExtension()); ANGLE_SKIP_TEST_IF(!hasAndroidNativeFenceSyncExtension());
EGLint value = 0; EGLint value = 0;
...@@ -332,7 +332,7 @@ TEST_P(EGLSyncTest, AndroidNativeFence_WaitSync) ...@@ -332,7 +332,7 @@ TEST_P(EGLSyncTest, AndroidNativeFence_WaitSync)
// Create work to do // Create work to do
glClearColor(0.0f, 1.0f, 0.0f, 1.0f); glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
glFinish(); glFlush();
/*- Second Context ------------------------*/ /*- Second Context ------------------------*/
if (fd > EGL_NO_NATIVE_FENCE_FD_ANDROID) if (fd > EGL_NO_NATIVE_FENCE_FD_ANDROID)
...@@ -354,7 +354,7 @@ TEST_P(EGLSyncTest, AndroidNativeFence_WaitSync) ...@@ -354,7 +354,7 @@ TEST_P(EGLSyncTest, AndroidNativeFence_WaitSync)
// Create work to do // Create work to do
glClearColor(1.0f, 0.0f, 0.0f, 1.0f); glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
glFinish(); glFlush();
} }
// Wait for second draw to complete // Wait for second draw to complete
...@@ -389,7 +389,7 @@ TEST_P(EGLSyncTest, AndroidNativeFence_WaitSync) ...@@ -389,7 +389,7 @@ TEST_P(EGLSyncTest, AndroidNativeFence_WaitSync)
TEST_P(EGLSyncTest, AndroidNativeFence_withFences) TEST_P(EGLSyncTest, AndroidNativeFence_withFences)
{ {
ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension()); ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension());
ANGLE_SKIP_TEST_IF(!hasFenceSyncExtension() || !hasGLSyncExtension()); ANGLE_SKIP_TEST_IF(!hasWaitSyncExtension() || !hasGLSyncExtension());
ANGLE_SKIP_TEST_IF(!hasAndroidNativeFenceSyncExtension()); ANGLE_SKIP_TEST_IF(!hasAndroidNativeFenceSyncExtension());
EGLint value = 0; EGLint value = 0;
......
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