xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/vulkan/SyncVk.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2016 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker // SyncVk.cpp:
7*8975f5c5SAndroid Build Coastguard Worker //    Implements the class methods for SyncVk.
8*8975f5c5SAndroid Build Coastguard Worker //
9*8975f5c5SAndroid Build Coastguard Worker 
10*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/SyncVk.h"
11*8975f5c5SAndroid Build Coastguard Worker 
12*8975f5c5SAndroid Build Coastguard Worker #include "common/debug.h"
13*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Context.h"
14*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Display.h"
15*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/ContextVk.h"
16*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/DisplayVk.h"
17*8975f5c5SAndroid Build Coastguard Worker 
18*8975f5c5SAndroid Build Coastguard Worker #if !defined(ANGLE_PLATFORM_WINDOWS)
19*8975f5c5SAndroid Build Coastguard Worker #    include <poll.h>
20*8975f5c5SAndroid Build Coastguard Worker #    include <unistd.h>
21*8975f5c5SAndroid Build Coastguard Worker #else
22*8975f5c5SAndroid Build Coastguard Worker #    include <io.h>
23*8975f5c5SAndroid Build Coastguard Worker #endif
24*8975f5c5SAndroid Build Coastguard Worker 
25*8975f5c5SAndroid Build Coastguard Worker namespace
26*8975f5c5SAndroid Build Coastguard Worker {
27*8975f5c5SAndroid Build Coastguard Worker // Wait for file descriptor to be signaled
SyncWaitFd(int fd,uint64_t timeoutNs,VkResult timeoutResult=VK_TIMEOUT)28*8975f5c5SAndroid Build Coastguard Worker VkResult SyncWaitFd(int fd, uint64_t timeoutNs, VkResult timeoutResult = VK_TIMEOUT)
29*8975f5c5SAndroid Build Coastguard Worker {
30*8975f5c5SAndroid Build Coastguard Worker #if !defined(ANGLE_PLATFORM_WINDOWS)
31*8975f5c5SAndroid Build Coastguard Worker     struct pollfd fds;
32*8975f5c5SAndroid Build Coastguard Worker     int ret;
33*8975f5c5SAndroid Build Coastguard Worker 
34*8975f5c5SAndroid Build Coastguard Worker     // Convert nanoseconds to milliseconds
35*8975f5c5SAndroid Build Coastguard Worker     int timeoutMs = static_cast<int>(timeoutNs / 1000000);
36*8975f5c5SAndroid Build Coastguard Worker     // If timeoutNs was non-zero but less than one millisecond, make it a millisecond.
37*8975f5c5SAndroid Build Coastguard Worker     if (timeoutNs > 0 && timeoutNs < 1000000)
38*8975f5c5SAndroid Build Coastguard Worker     {
39*8975f5c5SAndroid Build Coastguard Worker         timeoutMs = 1;
40*8975f5c5SAndroid Build Coastguard Worker     }
41*8975f5c5SAndroid Build Coastguard Worker 
42*8975f5c5SAndroid Build Coastguard Worker     ASSERT(fd >= 0);
43*8975f5c5SAndroid Build Coastguard Worker 
44*8975f5c5SAndroid Build Coastguard Worker     fds.fd     = fd;
45*8975f5c5SAndroid Build Coastguard Worker     fds.events = POLLIN;
46*8975f5c5SAndroid Build Coastguard Worker 
47*8975f5c5SAndroid Build Coastguard Worker     do
48*8975f5c5SAndroid Build Coastguard Worker     {
49*8975f5c5SAndroid Build Coastguard Worker         ret = poll(&fds, 1, timeoutMs);
50*8975f5c5SAndroid Build Coastguard Worker         if (ret > 0)
51*8975f5c5SAndroid Build Coastguard Worker         {
52*8975f5c5SAndroid Build Coastguard Worker             if (fds.revents & (POLLERR | POLLNVAL))
53*8975f5c5SAndroid Build Coastguard Worker             {
54*8975f5c5SAndroid Build Coastguard Worker                 return VK_ERROR_UNKNOWN;
55*8975f5c5SAndroid Build Coastguard Worker             }
56*8975f5c5SAndroid Build Coastguard Worker             return VK_SUCCESS;
57*8975f5c5SAndroid Build Coastguard Worker         }
58*8975f5c5SAndroid Build Coastguard Worker         else if (ret == 0)
59*8975f5c5SAndroid Build Coastguard Worker         {
60*8975f5c5SAndroid Build Coastguard Worker             return timeoutResult;
61*8975f5c5SAndroid Build Coastguard Worker         }
62*8975f5c5SAndroid Build Coastguard Worker     } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
63*8975f5c5SAndroid Build Coastguard Worker 
64*8975f5c5SAndroid Build Coastguard Worker     return VK_ERROR_UNKNOWN;
65*8975f5c5SAndroid Build Coastguard Worker #else
66*8975f5c5SAndroid Build Coastguard Worker     UNREACHABLE();
67*8975f5c5SAndroid Build Coastguard Worker     return VK_ERROR_UNKNOWN;
68*8975f5c5SAndroid Build Coastguard Worker #endif
69*8975f5c5SAndroid Build Coastguard Worker }
70*8975f5c5SAndroid Build Coastguard Worker 
71*8975f5c5SAndroid Build Coastguard Worker // Map VkResult to GLenum
MapVkResultToGlenum(VkResult vkResult,angle::Result angleResult,void * outResult)72*8975f5c5SAndroid Build Coastguard Worker void MapVkResultToGlenum(VkResult vkResult, angle::Result angleResult, void *outResult)
73*8975f5c5SAndroid Build Coastguard Worker {
74*8975f5c5SAndroid Build Coastguard Worker     GLenum *glEnumOut = static_cast<GLenum *>(outResult);
75*8975f5c5SAndroid Build Coastguard Worker     ASSERT(glEnumOut);
76*8975f5c5SAndroid Build Coastguard Worker 
77*8975f5c5SAndroid Build Coastguard Worker     if (angleResult != angle::Result::Continue)
78*8975f5c5SAndroid Build Coastguard Worker     {
79*8975f5c5SAndroid Build Coastguard Worker         *glEnumOut = GL_WAIT_FAILED;
80*8975f5c5SAndroid Build Coastguard Worker         return;
81*8975f5c5SAndroid Build Coastguard Worker     }
82*8975f5c5SAndroid Build Coastguard Worker 
83*8975f5c5SAndroid Build Coastguard Worker     switch (vkResult)
84*8975f5c5SAndroid Build Coastguard Worker     {
85*8975f5c5SAndroid Build Coastguard Worker         case VK_EVENT_SET:
86*8975f5c5SAndroid Build Coastguard Worker             *glEnumOut = GL_ALREADY_SIGNALED;
87*8975f5c5SAndroid Build Coastguard Worker             break;
88*8975f5c5SAndroid Build Coastguard Worker         case VK_SUCCESS:
89*8975f5c5SAndroid Build Coastguard Worker             *glEnumOut = GL_CONDITION_SATISFIED;
90*8975f5c5SAndroid Build Coastguard Worker             break;
91*8975f5c5SAndroid Build Coastguard Worker         case VK_TIMEOUT:
92*8975f5c5SAndroid Build Coastguard Worker             *glEnumOut = GL_TIMEOUT_EXPIRED;
93*8975f5c5SAndroid Build Coastguard Worker             break;
94*8975f5c5SAndroid Build Coastguard Worker         default:
95*8975f5c5SAndroid Build Coastguard Worker             *glEnumOut = GL_WAIT_FAILED;
96*8975f5c5SAndroid Build Coastguard Worker             break;
97*8975f5c5SAndroid Build Coastguard Worker     }
98*8975f5c5SAndroid Build Coastguard Worker }
99*8975f5c5SAndroid Build Coastguard Worker 
100*8975f5c5SAndroid Build Coastguard Worker // Map VkResult to EGLint
MapVkResultToEglint(VkResult result,angle::Result angleResult,void * outResult)101*8975f5c5SAndroid Build Coastguard Worker void MapVkResultToEglint(VkResult result, angle::Result angleResult, void *outResult)
102*8975f5c5SAndroid Build Coastguard Worker {
103*8975f5c5SAndroid Build Coastguard Worker     EGLint *eglIntOut = static_cast<EGLint *>(outResult);
104*8975f5c5SAndroid Build Coastguard Worker     ASSERT(eglIntOut);
105*8975f5c5SAndroid Build Coastguard Worker 
106*8975f5c5SAndroid Build Coastguard Worker     if (angleResult != angle::Result::Continue)
107*8975f5c5SAndroid Build Coastguard Worker     {
108*8975f5c5SAndroid Build Coastguard Worker         *eglIntOut = EGL_FALSE;
109*8975f5c5SAndroid Build Coastguard Worker         return;
110*8975f5c5SAndroid Build Coastguard Worker     }
111*8975f5c5SAndroid Build Coastguard Worker 
112*8975f5c5SAndroid Build Coastguard Worker     switch (result)
113*8975f5c5SAndroid Build Coastguard Worker     {
114*8975f5c5SAndroid Build Coastguard Worker         case VK_EVENT_SET:
115*8975f5c5SAndroid Build Coastguard Worker             // fall through.  EGL doesn't differentiate between event being already set, or set
116*8975f5c5SAndroid Build Coastguard Worker             // before timeout.
117*8975f5c5SAndroid Build Coastguard Worker         case VK_SUCCESS:
118*8975f5c5SAndroid Build Coastguard Worker             *eglIntOut = EGL_CONDITION_SATISFIED_KHR;
119*8975f5c5SAndroid Build Coastguard Worker             break;
120*8975f5c5SAndroid Build Coastguard Worker         case VK_TIMEOUT:
121*8975f5c5SAndroid Build Coastguard Worker             *eglIntOut = EGL_TIMEOUT_EXPIRED_KHR;
122*8975f5c5SAndroid Build Coastguard Worker             break;
123*8975f5c5SAndroid Build Coastguard Worker         default:
124*8975f5c5SAndroid Build Coastguard Worker             *eglIntOut = EGL_FALSE;
125*8975f5c5SAndroid Build Coastguard Worker             break;
126*8975f5c5SAndroid Build Coastguard Worker     }
127*8975f5c5SAndroid Build Coastguard Worker }
128*8975f5c5SAndroid Build Coastguard Worker 
129*8975f5c5SAndroid Build Coastguard Worker }  // anonymous namespace
130*8975f5c5SAndroid Build Coastguard Worker 
131*8975f5c5SAndroid Build Coastguard Worker namespace rx
132*8975f5c5SAndroid Build Coastguard Worker {
133*8975f5c5SAndroid Build Coastguard Worker namespace vk
134*8975f5c5SAndroid Build Coastguard Worker {
SyncHelper()135*8975f5c5SAndroid Build Coastguard Worker SyncHelper::SyncHelper() {}
136*8975f5c5SAndroid Build Coastguard Worker 
~SyncHelper()137*8975f5c5SAndroid Build Coastguard Worker SyncHelper::~SyncHelper() {}
138*8975f5c5SAndroid Build Coastguard Worker 
releaseToRenderer(Renderer * renderer)139*8975f5c5SAndroid Build Coastguard Worker void SyncHelper::releaseToRenderer(Renderer *renderer) {}
140*8975f5c5SAndroid Build Coastguard Worker 
initialize(ContextVk * contextVk,SyncFenceScope scope)141*8975f5c5SAndroid Build Coastguard Worker angle::Result SyncHelper::initialize(ContextVk *contextVk, SyncFenceScope scope)
142*8975f5c5SAndroid Build Coastguard Worker {
143*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mUse.valid());
144*8975f5c5SAndroid Build Coastguard Worker     return contextVk->onSyncObjectInit(this, scope);
145*8975f5c5SAndroid Build Coastguard Worker }
146*8975f5c5SAndroid Build Coastguard Worker 
prepareForClientWait(Context * context,ContextVk * contextVk,bool flushCommands,uint64_t timeout,VkResult * resultOut)147*8975f5c5SAndroid Build Coastguard Worker angle::Result SyncHelper::prepareForClientWait(Context *context,
148*8975f5c5SAndroid Build Coastguard Worker                                                ContextVk *contextVk,
149*8975f5c5SAndroid Build Coastguard Worker                                                bool flushCommands,
150*8975f5c5SAndroid Build Coastguard Worker                                                uint64_t timeout,
151*8975f5c5SAndroid Build Coastguard Worker                                                VkResult *resultOut)
152*8975f5c5SAndroid Build Coastguard Worker {
153*8975f5c5SAndroid Build Coastguard Worker     // If the event is already set, don't wait
154*8975f5c5SAndroid Build Coastguard Worker     bool alreadySignaled = false;
155*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(getStatus(context, contextVk, &alreadySignaled));
156*8975f5c5SAndroid Build Coastguard Worker     if (alreadySignaled)
157*8975f5c5SAndroid Build Coastguard Worker     {
158*8975f5c5SAndroid Build Coastguard Worker         *resultOut = VK_EVENT_SET;
159*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
160*8975f5c5SAndroid Build Coastguard Worker     }
161*8975f5c5SAndroid Build Coastguard Worker 
162*8975f5c5SAndroid Build Coastguard Worker     // If timeout is zero, there's no need to wait, so return timeout already.
163*8975f5c5SAndroid Build Coastguard Worker     if (timeout == 0)
164*8975f5c5SAndroid Build Coastguard Worker     {
165*8975f5c5SAndroid Build Coastguard Worker         *resultOut = VK_TIMEOUT;
166*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
167*8975f5c5SAndroid Build Coastguard Worker     }
168*8975f5c5SAndroid Build Coastguard Worker 
169*8975f5c5SAndroid Build Coastguard Worker     // Submit commands if requested
170*8975f5c5SAndroid Build Coastguard Worker     if (flushCommands && contextVk)
171*8975f5c5SAndroid Build Coastguard Worker     {
172*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(contextVk->flushCommandsAndEndRenderPassIfDeferredSyncInit(
173*8975f5c5SAndroid Build Coastguard Worker             RenderPassClosureReason::SyncObjectClientWait));
174*8975f5c5SAndroid Build Coastguard Worker     }
175*8975f5c5SAndroid Build Coastguard Worker 
176*8975f5c5SAndroid Build Coastguard Worker     *resultOut = VK_INCOMPLETE;
177*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
178*8975f5c5SAndroid Build Coastguard Worker }
179*8975f5c5SAndroid Build Coastguard Worker 
clientWait(Context * context,ContextVk * contextVk,bool flushCommands,uint64_t timeout,MapVkResultToApiType mappingFunction,void * resultOut)180*8975f5c5SAndroid Build Coastguard Worker angle::Result SyncHelper::clientWait(Context *context,
181*8975f5c5SAndroid Build Coastguard Worker                                      ContextVk *contextVk,
182*8975f5c5SAndroid Build Coastguard Worker                                      bool flushCommands,
183*8975f5c5SAndroid Build Coastguard Worker                                      uint64_t timeout,
184*8975f5c5SAndroid Build Coastguard Worker                                      MapVkResultToApiType mappingFunction,
185*8975f5c5SAndroid Build Coastguard Worker                                      void *resultOut)
186*8975f5c5SAndroid Build Coastguard Worker {
187*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRACE_EVENT0("gpu.angle", "SyncHelper::clientWait");
188*8975f5c5SAndroid Build Coastguard Worker 
189*8975f5c5SAndroid Build Coastguard Worker     VkResult status = VK_INCOMPLETE;
190*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(prepareForClientWait(context, contextVk, flushCommands, timeout, &status));
191*8975f5c5SAndroid Build Coastguard Worker 
192*8975f5c5SAndroid Build Coastguard Worker     if (status != VK_INCOMPLETE)
193*8975f5c5SAndroid Build Coastguard Worker     {
194*8975f5c5SAndroid Build Coastguard Worker         mappingFunction(status, angle::Result::Continue, resultOut);
195*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
196*8975f5c5SAndroid Build Coastguard Worker     }
197*8975f5c5SAndroid Build Coastguard Worker 
198*8975f5c5SAndroid Build Coastguard Worker     Renderer *renderer = context->getRenderer();
199*8975f5c5SAndroid Build Coastguard Worker 
200*8975f5c5SAndroid Build Coastguard Worker     // If we need to perform a CPU wait don't set the resultOut parameter passed into the
201*8975f5c5SAndroid Build Coastguard Worker     // method, instead set the parameter passed into the unlocked tail call.
202*8975f5c5SAndroid Build Coastguard Worker     auto clientWaitUnlocked = [renderer, context, mappingFunction, use = mUse,
203*8975f5c5SAndroid Build Coastguard Worker                                timeout](void *resultOut) {
204*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRACE_EVENT0("gpu.angle", "SyncHelper::clientWait block (unlocked)");
205*8975f5c5SAndroid Build Coastguard Worker 
206*8975f5c5SAndroid Build Coastguard Worker         VkResult status = VK_INCOMPLETE;
207*8975f5c5SAndroid Build Coastguard Worker         angle::Result angleResult =
208*8975f5c5SAndroid Build Coastguard Worker             renderer->waitForResourceUseToFinishWithUserTimeout(context, use, timeout, &status);
209*8975f5c5SAndroid Build Coastguard Worker         // Note: resultOut may be nullptr through the glFinishFenceNV path, which does not have a
210*8975f5c5SAndroid Build Coastguard Worker         // return value.
211*8975f5c5SAndroid Build Coastguard Worker         if (resultOut != nullptr)
212*8975f5c5SAndroid Build Coastguard Worker         {
213*8975f5c5SAndroid Build Coastguard Worker             mappingFunction(status, angleResult, resultOut);
214*8975f5c5SAndroid Build Coastguard Worker         }
215*8975f5c5SAndroid Build Coastguard Worker     };
216*8975f5c5SAndroid Build Coastguard Worker 
217*8975f5c5SAndroid Build Coastguard Worker     // Schedule the wait to be run at the tail of the current call.
218*8975f5c5SAndroid Build Coastguard Worker     egl::Display::GetCurrentThreadUnlockedTailCall()->add(clientWaitUnlocked);
219*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
220*8975f5c5SAndroid Build Coastguard Worker }
221*8975f5c5SAndroid Build Coastguard Worker 
finish(ContextVk * contextVk)222*8975f5c5SAndroid Build Coastguard Worker angle::Result SyncHelper::finish(ContextVk *contextVk)
223*8975f5c5SAndroid Build Coastguard Worker {
224*8975f5c5SAndroid Build Coastguard Worker     GLenum result;
225*8975f5c5SAndroid Build Coastguard Worker     return clientWait(contextVk, contextVk, true, UINT64_MAX, MapVkResultToGlenum, &result);
226*8975f5c5SAndroid Build Coastguard Worker }
227*8975f5c5SAndroid Build Coastguard Worker 
serverWait(ContextVk * contextVk)228*8975f5c5SAndroid Build Coastguard Worker angle::Result SyncHelper::serverWait(ContextVk *contextVk)
229*8975f5c5SAndroid Build Coastguard Worker {
230*8975f5c5SAndroid Build Coastguard Worker     // If already signaled, no need to wait
231*8975f5c5SAndroid Build Coastguard Worker     bool alreadySignaled = false;
232*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(getStatus(contextVk, contextVk, &alreadySignaled));
233*8975f5c5SAndroid Build Coastguard Worker     if (alreadySignaled)
234*8975f5c5SAndroid Build Coastguard Worker     {
235*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
236*8975f5c5SAndroid Build Coastguard Worker     }
237*8975f5c5SAndroid Build Coastguard Worker 
238*8975f5c5SAndroid Build Coastguard Worker     // Every resource already tracks its usage and issues the appropriate barriers, so there's
239*8975f5c5SAndroid Build Coastguard Worker     // really nothing to do here.  An execution barrier is issued to strictly satisfy what the
240*8975f5c5SAndroid Build Coastguard Worker     // application asked for.
241*8975f5c5SAndroid Build Coastguard Worker     vk::OutsideRenderPassCommandBuffer *commandBuffer;
242*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &commandBuffer));
243*8975f5c5SAndroid Build Coastguard Worker     commandBuffer->pipelineBarrier(VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
244*8975f5c5SAndroid Build Coastguard Worker                                    VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 0,
245*8975f5c5SAndroid Build Coastguard Worker                                    nullptr);
246*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
247*8975f5c5SAndroid Build Coastguard Worker }
248*8975f5c5SAndroid Build Coastguard Worker 
getStatus(Context * context,ContextVk * contextVk,bool * signaledOut)249*8975f5c5SAndroid Build Coastguard Worker angle::Result SyncHelper::getStatus(Context *context, ContextVk *contextVk, bool *signaledOut)
250*8975f5c5SAndroid Build Coastguard Worker {
251*8975f5c5SAndroid Build Coastguard Worker     // Submit commands if it was deferred on the context that issued the sync object
252*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(submitSyncIfDeferred(contextVk, RenderPassClosureReason::SyncObjectClientWait));
253*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mUse.valid());
254*8975f5c5SAndroid Build Coastguard Worker     Renderer *renderer = context->getRenderer();
255*8975f5c5SAndroid Build Coastguard Worker     if (renderer->hasResourceUseFinished(mUse))
256*8975f5c5SAndroid Build Coastguard Worker     {
257*8975f5c5SAndroid Build Coastguard Worker         *signaledOut = true;
258*8975f5c5SAndroid Build Coastguard Worker     }
259*8975f5c5SAndroid Build Coastguard Worker     else
260*8975f5c5SAndroid Build Coastguard Worker     {
261*8975f5c5SAndroid Build Coastguard Worker         // Check completed commands once before returning, perhaps the serial is actually already
262*8975f5c5SAndroid Build Coastguard Worker         // finished.
263*8975f5c5SAndroid Build Coastguard Worker         // We don't call checkCompletedCommandsAndCleanup() to cleanup finished commands immediately
264*8975f5c5SAndroid Build Coastguard Worker         // if isAsyncCommandBufferResetAndGarbageCleanupEnabled feature is turned off.
265*8975f5c5SAndroid Build Coastguard Worker         // Because when isAsyncCommandBufferResetAndGarbageCleanupEnabled feature is turned off,
266*8975f5c5SAndroid Build Coastguard Worker         // vkResetCommandBuffer() is called in cleanup step, and it must take the
267*8975f5c5SAndroid Build Coastguard Worker         // CommandPoolAccess::mCmdPoolMutex lock, see details in
268*8975f5c5SAndroid Build Coastguard Worker         // CommandPoolAccess::collectPrimaryCommandBuffer. This means the cleanup step can
269*8975f5c5SAndroid Build Coastguard Worker         // be blocked by command buffer recording if another thread calls
270*8975f5c5SAndroid Build Coastguard Worker         // CommandPoolAccess::flushRenderPassCommands(), which is against EGL spec when
271*8975f5c5SAndroid Build Coastguard Worker         // eglClientWaitSync() should return immediately with timeout == 0.
272*8975f5c5SAndroid Build Coastguard Worker         if (renderer->isAsyncCommandBufferResetAndGarbageCleanupEnabled())
273*8975f5c5SAndroid Build Coastguard Worker         {
274*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(renderer->checkCompletedCommandsAndCleanup(context));
275*8975f5c5SAndroid Build Coastguard Worker         }
276*8975f5c5SAndroid Build Coastguard Worker         else
277*8975f5c5SAndroid Build Coastguard Worker         {
278*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(renderer->checkCompletedCommands(context));
279*8975f5c5SAndroid Build Coastguard Worker         }
280*8975f5c5SAndroid Build Coastguard Worker 
281*8975f5c5SAndroid Build Coastguard Worker         *signaledOut = renderer->hasResourceUseFinished(mUse);
282*8975f5c5SAndroid Build Coastguard Worker     }
283*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
284*8975f5c5SAndroid Build Coastguard Worker }
285*8975f5c5SAndroid Build Coastguard Worker 
submitSyncIfDeferred(ContextVk * contextVk,RenderPassClosureReason reason)286*8975f5c5SAndroid Build Coastguard Worker angle::Result SyncHelper::submitSyncIfDeferred(ContextVk *contextVk, RenderPassClosureReason reason)
287*8975f5c5SAndroid Build Coastguard Worker {
288*8975f5c5SAndroid Build Coastguard Worker     if (contextVk == nullptr)
289*8975f5c5SAndroid Build Coastguard Worker     {
290*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
291*8975f5c5SAndroid Build Coastguard Worker     }
292*8975f5c5SAndroid Build Coastguard Worker 
293*8975f5c5SAndroid Build Coastguard Worker     if (contextVk->getRenderer()->hasResourceUseSubmitted(mUse))
294*8975f5c5SAndroid Build Coastguard Worker     {
295*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
296*8975f5c5SAndroid Build Coastguard Worker     }
297*8975f5c5SAndroid Build Coastguard Worker 
298*8975f5c5SAndroid Build Coastguard Worker     // The submission of a sync object may be deferred to allow further optimizations to an open
299*8975f5c5SAndroid Build Coastguard Worker     // render pass before a submission happens for another reason.  If the sync object is being
300*8975f5c5SAndroid Build Coastguard Worker     // waited on by the current context, the application must have used GL_SYNC_FLUSH_COMMANDS_BIT.
301*8975f5c5SAndroid Build Coastguard Worker     // However, when waited on by other contexts, the application must have ensured the original
302*8975f5c5SAndroid Build Coastguard Worker     // context is flushed.  Due to deferred flushes, a glFlush is not sufficient to guarantee this.
303*8975f5c5SAndroid Build Coastguard Worker     //
304*8975f5c5SAndroid Build Coastguard Worker     // Deferring the submission is restricted to non-EGL sync objects, so it's sufficient to ensure
305*8975f5c5SAndroid Build Coastguard Worker     // that the contexts in the share group issue their deferred flushes.
306*8975f5c5SAndroid Build Coastguard Worker     for (auto context : contextVk->getShareGroup()->getContexts())
307*8975f5c5SAndroid Build Coastguard Worker     {
308*8975f5c5SAndroid Build Coastguard Worker         ContextVk *sharedContextVk = vk::GetImpl(context.second);
309*8975f5c5SAndroid Build Coastguard Worker         if (sharedContextVk->hasUnsubmittedUse(mUse))
310*8975f5c5SAndroid Build Coastguard Worker         {
311*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(sharedContextVk->flushCommandsAndEndRenderPassIfDeferredSyncInit(reason));
312*8975f5c5SAndroid Build Coastguard Worker             break;
313*8975f5c5SAndroid Build Coastguard Worker         }
314*8975f5c5SAndroid Build Coastguard Worker     }
315*8975f5c5SAndroid Build Coastguard Worker     // Note mUse could still be invalid here if it is inserted on a fresh created context, i.e.,
316*8975f5c5SAndroid Build Coastguard Worker     // fence is tracking nothing and is finished when inserted..
317*8975f5c5SAndroid Build Coastguard Worker     ASSERT(contextVk->getRenderer()->hasResourceUseSubmitted(mUse));
318*8975f5c5SAndroid Build Coastguard Worker 
319*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
320*8975f5c5SAndroid Build Coastguard Worker }
321*8975f5c5SAndroid Build Coastguard Worker 
ExternalFence()322*8975f5c5SAndroid Build Coastguard Worker ExternalFence::ExternalFence()
323*8975f5c5SAndroid Build Coastguard Worker     : mDevice(VK_NULL_HANDLE), mFenceFdStatus(VK_INCOMPLETE), mFenceFd(kInvalidFenceFd)
324*8975f5c5SAndroid Build Coastguard Worker {}
325*8975f5c5SAndroid Build Coastguard Worker 
~ExternalFence()326*8975f5c5SAndroid Build Coastguard Worker ExternalFence::~ExternalFence()
327*8975f5c5SAndroid Build Coastguard Worker {
328*8975f5c5SAndroid Build Coastguard Worker     if (mDevice != VK_NULL_HANDLE)
329*8975f5c5SAndroid Build Coastguard Worker     {
330*8975f5c5SAndroid Build Coastguard Worker         mFence.destroy(mDevice);
331*8975f5c5SAndroid Build Coastguard Worker     }
332*8975f5c5SAndroid Build Coastguard Worker 
333*8975f5c5SAndroid Build Coastguard Worker     if (mFenceFd != kInvalidFenceFd)
334*8975f5c5SAndroid Build Coastguard Worker     {
335*8975f5c5SAndroid Build Coastguard Worker         close(mFenceFd);
336*8975f5c5SAndroid Build Coastguard Worker     }
337*8975f5c5SAndroid Build Coastguard Worker }
338*8975f5c5SAndroid Build Coastguard Worker 
init(VkDevice device,const VkFenceCreateInfo & createInfo)339*8975f5c5SAndroid Build Coastguard Worker VkResult ExternalFence::init(VkDevice device, const VkFenceCreateInfo &createInfo)
340*8975f5c5SAndroid Build Coastguard Worker {
341*8975f5c5SAndroid Build Coastguard Worker     ASSERT(device != VK_NULL_HANDLE);
342*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mFenceFdStatus == VK_INCOMPLETE && mFenceFd == kInvalidFenceFd);
343*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mDevice == VK_NULL_HANDLE);
344*8975f5c5SAndroid Build Coastguard Worker     mDevice = device;
345*8975f5c5SAndroid Build Coastguard Worker     return mFence.init(device, createInfo);
346*8975f5c5SAndroid Build Coastguard Worker }
347*8975f5c5SAndroid Build Coastguard Worker 
init(int fenceFd)348*8975f5c5SAndroid Build Coastguard Worker void ExternalFence::init(int fenceFd)
349*8975f5c5SAndroid Build Coastguard Worker {
350*8975f5c5SAndroid Build Coastguard Worker     ASSERT(fenceFd != kInvalidFenceFd);
351*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mFenceFdStatus == VK_INCOMPLETE && mFenceFd == kInvalidFenceFd);
352*8975f5c5SAndroid Build Coastguard Worker     mFenceFdStatus = VK_SUCCESS;
353*8975f5c5SAndroid Build Coastguard Worker     mFenceFd       = fenceFd;
354*8975f5c5SAndroid Build Coastguard Worker }
355*8975f5c5SAndroid Build Coastguard Worker 
getStatus(VkDevice device) const356*8975f5c5SAndroid Build Coastguard Worker VkResult ExternalFence::getStatus(VkDevice device) const
357*8975f5c5SAndroid Build Coastguard Worker {
358*8975f5c5SAndroid Build Coastguard Worker     if (mFenceFdStatus == VK_SUCCESS)
359*8975f5c5SAndroid Build Coastguard Worker     {
360*8975f5c5SAndroid Build Coastguard Worker         return SyncWaitFd(mFenceFd, 0, VK_NOT_READY);
361*8975f5c5SAndroid Build Coastguard Worker     }
362*8975f5c5SAndroid Build Coastguard Worker     return mFence.getStatus(device);
363*8975f5c5SAndroid Build Coastguard Worker }
364*8975f5c5SAndroid Build Coastguard Worker 
wait(VkDevice device,uint64_t timeout) const365*8975f5c5SAndroid Build Coastguard Worker VkResult ExternalFence::wait(VkDevice device, uint64_t timeout) const
366*8975f5c5SAndroid Build Coastguard Worker {
367*8975f5c5SAndroid Build Coastguard Worker     if (mFenceFdStatus == VK_SUCCESS)
368*8975f5c5SAndroid Build Coastguard Worker     {
369*8975f5c5SAndroid Build Coastguard Worker         return SyncWaitFd(mFenceFd, timeout);
370*8975f5c5SAndroid Build Coastguard Worker     }
371*8975f5c5SAndroid Build Coastguard Worker     return mFence.wait(device, timeout);
372*8975f5c5SAndroid Build Coastguard Worker }
373*8975f5c5SAndroid Build Coastguard Worker 
exportFd(VkDevice device,const VkFenceGetFdInfoKHR & fenceGetFdInfo)374*8975f5c5SAndroid Build Coastguard Worker void ExternalFence::exportFd(VkDevice device, const VkFenceGetFdInfoKHR &fenceGetFdInfo)
375*8975f5c5SAndroid Build Coastguard Worker {
376*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mFenceFdStatus == VK_INCOMPLETE && mFenceFd == kInvalidFenceFd);
377*8975f5c5SAndroid Build Coastguard Worker     mFenceFdStatus = mFence.exportFd(device, fenceGetFdInfo, &mFenceFd);
378*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mFenceFdStatus != VK_INCOMPLETE);
379*8975f5c5SAndroid Build Coastguard Worker }
380*8975f5c5SAndroid Build Coastguard Worker 
SyncHelperNativeFence()381*8975f5c5SAndroid Build Coastguard Worker SyncHelperNativeFence::SyncHelperNativeFence()
382*8975f5c5SAndroid Build Coastguard Worker {
383*8975f5c5SAndroid Build Coastguard Worker     mExternalFence = std::make_shared<ExternalFence>();
384*8975f5c5SAndroid Build Coastguard Worker }
385*8975f5c5SAndroid Build Coastguard Worker 
~SyncHelperNativeFence()386*8975f5c5SAndroid Build Coastguard Worker SyncHelperNativeFence::~SyncHelperNativeFence() {}
387*8975f5c5SAndroid Build Coastguard Worker 
releaseToRenderer(Renderer * renderer)388*8975f5c5SAndroid Build Coastguard Worker void SyncHelperNativeFence::releaseToRenderer(Renderer *renderer)
389*8975f5c5SAndroid Build Coastguard Worker {
390*8975f5c5SAndroid Build Coastguard Worker     mExternalFence.reset();
391*8975f5c5SAndroid Build Coastguard Worker }
392*8975f5c5SAndroid Build Coastguard Worker 
initializeWithFd(ContextVk * contextVk,int inFd)393*8975f5c5SAndroid Build Coastguard Worker angle::Result SyncHelperNativeFence::initializeWithFd(ContextVk *contextVk, int inFd)
394*8975f5c5SAndroid Build Coastguard Worker {
395*8975f5c5SAndroid Build Coastguard Worker     ASSERT(inFd >= kInvalidFenceFd);
396*8975f5c5SAndroid Build Coastguard Worker 
397*8975f5c5SAndroid Build Coastguard Worker     // If valid FD provided by application - import it to fence.
398*8975f5c5SAndroid Build Coastguard Worker     if (inFd > kInvalidFenceFd)
399*8975f5c5SAndroid Build Coastguard Worker     {
400*8975f5c5SAndroid Build Coastguard Worker         // File descriptor ownership: EGL_ANDROID_native_fence_sync
401*8975f5c5SAndroid Build Coastguard Worker         // Whenever a file descriptor is passed into or returned from an
402*8975f5c5SAndroid Build Coastguard Worker         // EGL call in this extension, ownership of that file descriptor is
403*8975f5c5SAndroid Build Coastguard Worker         // transferred. The recipient of the file descriptor must close it when it is
404*8975f5c5SAndroid Build Coastguard Worker         // no longer needed, and the provider of the file descriptor must dup it
405*8975f5c5SAndroid Build Coastguard Worker         // before providing it if they require continued use of the native fence.
406*8975f5c5SAndroid Build Coastguard Worker         mExternalFence->init(inFd);
407*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
408*8975f5c5SAndroid Build Coastguard Worker     }
409*8975f5c5SAndroid Build Coastguard Worker 
410*8975f5c5SAndroid Build Coastguard Worker     Renderer *renderer = contextVk->getRenderer();
411*8975f5c5SAndroid Build Coastguard Worker     VkDevice device    = renderer->getDevice();
412*8975f5c5SAndroid Build Coastguard Worker 
413*8975f5c5SAndroid Build Coastguard Worker     VkExportFenceCreateInfo exportCreateInfo = {};
414*8975f5c5SAndroid Build Coastguard Worker     exportCreateInfo.sType                   = VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO;
415*8975f5c5SAndroid Build Coastguard Worker     exportCreateInfo.pNext                   = nullptr;
416*8975f5c5SAndroid Build Coastguard Worker     exportCreateInfo.handleTypes             = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR;
417*8975f5c5SAndroid Build Coastguard Worker 
418*8975f5c5SAndroid Build Coastguard Worker     // Create fenceInfo base.
419*8975f5c5SAndroid Build Coastguard Worker     VkFenceCreateInfo fenceCreateInfo = {};
420*8975f5c5SAndroid Build Coastguard Worker     fenceCreateInfo.sType             = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
421*8975f5c5SAndroid Build Coastguard Worker     fenceCreateInfo.flags             = 0;
422*8975f5c5SAndroid Build Coastguard Worker     fenceCreateInfo.pNext             = &exportCreateInfo;
423*8975f5c5SAndroid Build Coastguard Worker 
424*8975f5c5SAndroid Build Coastguard Worker     // Initialize/create a VkFence handle
425*8975f5c5SAndroid Build Coastguard Worker     ANGLE_VK_TRY(contextVk, mExternalFence->init(device, fenceCreateInfo));
426*8975f5c5SAndroid Build Coastguard Worker 
427*8975f5c5SAndroid Build Coastguard Worker     // invalid FD provided by application - create one with fence.
428*8975f5c5SAndroid Build Coastguard Worker     /*
429*8975f5c5SAndroid Build Coastguard Worker       Spec: "When a fence sync object is created or when an EGL native fence sync
430*8975f5c5SAndroid Build Coastguard Worker       object is created with the EGL_SYNC_NATIVE_FENCE_FD_ANDROID attribute set to
431*8975f5c5SAndroid Build Coastguard Worker       EGL_NO_NATIVE_FENCE_FD_ANDROID, eglCreateSyncKHR also inserts a fence command
432*8975f5c5SAndroid Build Coastguard Worker       into the command stream of the bound client API's current context and associates it
433*8975f5c5SAndroid Build Coastguard Worker       with the newly created sync object.
434*8975f5c5SAndroid Build Coastguard Worker     */
435*8975f5c5SAndroid Build Coastguard Worker     // Flush current pending set of commands providing the fence...
436*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(contextVk->flushAndSubmitCommands(nullptr, &mExternalFence,
437*8975f5c5SAndroid Build Coastguard Worker                                                 RenderPassClosureReason::SyncObjectWithFdInit));
438*8975f5c5SAndroid Build Coastguard Worker     QueueSerial submitSerial = contextVk->getLastSubmittedQueueSerial();
439*8975f5c5SAndroid Build Coastguard Worker 
440*8975f5c5SAndroid Build Coastguard Worker     // exportFd is exporting VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR type handle which
441*8975f5c5SAndroid Build Coastguard Worker     // obeys copy semantics. This means that the fence must already be signaled or the work to
442*8975f5c5SAndroid Build Coastguard Worker     // signal it is in the graphics pipeline at the time we export the fd. Thus we need to
443*8975f5c5SAndroid Build Coastguard Worker     // call waitForQueueSerialToBeSubmittedToDevice() here.
444*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(renderer->waitForQueueSerialToBeSubmittedToDevice(contextVk, submitSerial));
445*8975f5c5SAndroid Build Coastguard Worker 
446*8975f5c5SAndroid Build Coastguard Worker     ANGLE_VK_TRY(contextVk, mExternalFence->getFenceFdStatus());
447*8975f5c5SAndroid Build Coastguard Worker 
448*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
449*8975f5c5SAndroid Build Coastguard Worker }
450*8975f5c5SAndroid Build Coastguard Worker 
prepareForClientWait(Context * context,ContextVk * contextVk,bool flushCommands,uint64_t timeout,VkResult * resultOut)451*8975f5c5SAndroid Build Coastguard Worker angle::Result SyncHelperNativeFence::prepareForClientWait(Context *context,
452*8975f5c5SAndroid Build Coastguard Worker                                                           ContextVk *contextVk,
453*8975f5c5SAndroid Build Coastguard Worker                                                           bool flushCommands,
454*8975f5c5SAndroid Build Coastguard Worker                                                           uint64_t timeout,
455*8975f5c5SAndroid Build Coastguard Worker                                                           VkResult *resultOut)
456*8975f5c5SAndroid Build Coastguard Worker {
457*8975f5c5SAndroid Build Coastguard Worker     // If already signaled, don't wait
458*8975f5c5SAndroid Build Coastguard Worker     bool alreadySignaled = false;
459*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(getStatus(context, contextVk, &alreadySignaled));
460*8975f5c5SAndroid Build Coastguard Worker     if (alreadySignaled)
461*8975f5c5SAndroid Build Coastguard Worker     {
462*8975f5c5SAndroid Build Coastguard Worker         *resultOut = VK_SUCCESS;
463*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
464*8975f5c5SAndroid Build Coastguard Worker     }
465*8975f5c5SAndroid Build Coastguard Worker 
466*8975f5c5SAndroid Build Coastguard Worker     // If timeout is zero, there's no need to wait, so return timeout already.
467*8975f5c5SAndroid Build Coastguard Worker     if (timeout == 0)
468*8975f5c5SAndroid Build Coastguard Worker     {
469*8975f5c5SAndroid Build Coastguard Worker         *resultOut = VK_TIMEOUT;
470*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
471*8975f5c5SAndroid Build Coastguard Worker     }
472*8975f5c5SAndroid Build Coastguard Worker 
473*8975f5c5SAndroid Build Coastguard Worker     if (flushCommands && contextVk)
474*8975f5c5SAndroid Build Coastguard Worker     {
475*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(contextVk->flushAndSubmitCommands(nullptr, nullptr,
476*8975f5c5SAndroid Build Coastguard Worker                                                     RenderPassClosureReason::SyncObjectClientWait));
477*8975f5c5SAndroid Build Coastguard Worker     }
478*8975f5c5SAndroid Build Coastguard Worker 
479*8975f5c5SAndroid Build Coastguard Worker     *resultOut = VK_INCOMPLETE;
480*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
481*8975f5c5SAndroid Build Coastguard Worker }
482*8975f5c5SAndroid Build Coastguard Worker 
clientWait(Context * context,ContextVk * contextVk,bool flushCommands,uint64_t timeout,MapVkResultToApiType mappingFunction,void * resultOut)483*8975f5c5SAndroid Build Coastguard Worker angle::Result SyncHelperNativeFence::clientWait(Context *context,
484*8975f5c5SAndroid Build Coastguard Worker                                                 ContextVk *contextVk,
485*8975f5c5SAndroid Build Coastguard Worker                                                 bool flushCommands,
486*8975f5c5SAndroid Build Coastguard Worker                                                 uint64_t timeout,
487*8975f5c5SAndroid Build Coastguard Worker                                                 MapVkResultToApiType mappingFunction,
488*8975f5c5SAndroid Build Coastguard Worker                                                 void *resultOut)
489*8975f5c5SAndroid Build Coastguard Worker {
490*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRACE_EVENT0("gpu.angle", "SyncHelperNativeFence::clientWait");
491*8975f5c5SAndroid Build Coastguard Worker 
492*8975f5c5SAndroid Build Coastguard Worker     VkResult status = VK_INCOMPLETE;
493*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(prepareForClientWait(context, contextVk, flushCommands, timeout, &status));
494*8975f5c5SAndroid Build Coastguard Worker 
495*8975f5c5SAndroid Build Coastguard Worker     if (status != VK_INCOMPLETE)
496*8975f5c5SAndroid Build Coastguard Worker     {
497*8975f5c5SAndroid Build Coastguard Worker         mappingFunction(status, angle::Result::Continue, resultOut);
498*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
499*8975f5c5SAndroid Build Coastguard Worker     }
500*8975f5c5SAndroid Build Coastguard Worker 
501*8975f5c5SAndroid Build Coastguard Worker     Renderer *renderer = context->getRenderer();
502*8975f5c5SAndroid Build Coastguard Worker 
503*8975f5c5SAndroid Build Coastguard Worker     auto clientWaitUnlocked = [device = renderer->getDevice(), fence = mExternalFence,
504*8975f5c5SAndroid Build Coastguard Worker                                mappingFunction, timeout](void *resultOut) {
505*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRACE_EVENT0("gpu.angle", "SyncHelperNativeFence::clientWait block (unlocked)");
506*8975f5c5SAndroid Build Coastguard Worker         ASSERT(resultOut);
507*8975f5c5SAndroid Build Coastguard Worker 
508*8975f5c5SAndroid Build Coastguard Worker         VkResult status = fence->wait(device, timeout);
509*8975f5c5SAndroid Build Coastguard Worker         mappingFunction(status, angle::Result::Continue, resultOut);
510*8975f5c5SAndroid Build Coastguard Worker     };
511*8975f5c5SAndroid Build Coastguard Worker 
512*8975f5c5SAndroid Build Coastguard Worker     egl::Display::GetCurrentThreadUnlockedTailCall()->add(clientWaitUnlocked);
513*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
514*8975f5c5SAndroid Build Coastguard Worker }
515*8975f5c5SAndroid Build Coastguard Worker 
serverWait(ContextVk * contextVk)516*8975f5c5SAndroid Build Coastguard Worker angle::Result SyncHelperNativeFence::serverWait(ContextVk *contextVk)
517*8975f5c5SAndroid Build Coastguard Worker {
518*8975f5c5SAndroid Build Coastguard Worker     Renderer *renderer = contextVk->getRenderer();
519*8975f5c5SAndroid Build Coastguard Worker 
520*8975f5c5SAndroid Build Coastguard Worker     // If already signaled, no need to wait
521*8975f5c5SAndroid Build Coastguard Worker     bool alreadySignaled = false;
522*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(getStatus(contextVk, contextVk, &alreadySignaled));
523*8975f5c5SAndroid Build Coastguard Worker     if (alreadySignaled)
524*8975f5c5SAndroid Build Coastguard Worker     {
525*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
526*8975f5c5SAndroid Build Coastguard Worker     }
527*8975f5c5SAndroid Build Coastguard Worker 
528*8975f5c5SAndroid Build Coastguard Worker     VkDevice device = renderer->getDevice();
529*8975f5c5SAndroid Build Coastguard Worker     DeviceScoped<Semaphore> waitSemaphore(device);
530*8975f5c5SAndroid Build Coastguard Worker     // Wait semaphore for next vkQueueSubmit().
531*8975f5c5SAndroid Build Coastguard Worker     // Create a Semaphore with imported fenceFd.
532*8975f5c5SAndroid Build Coastguard Worker     ANGLE_VK_TRY(contextVk, waitSemaphore.get().init(device));
533*8975f5c5SAndroid Build Coastguard Worker 
534*8975f5c5SAndroid Build Coastguard Worker     VkImportSemaphoreFdInfoKHR importFdInfo = {};
535*8975f5c5SAndroid Build Coastguard Worker     importFdInfo.sType                      = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR;
536*8975f5c5SAndroid Build Coastguard Worker     importFdInfo.semaphore                  = waitSemaphore.get().getHandle();
537*8975f5c5SAndroid Build Coastguard Worker     importFdInfo.flags                      = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR;
538*8975f5c5SAndroid Build Coastguard Worker     importFdInfo.handleType                 = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR;
539*8975f5c5SAndroid Build Coastguard Worker     importFdInfo.fd                         = dup(mExternalFence->getFenceFd());
540*8975f5c5SAndroid Build Coastguard Worker     ANGLE_VK_TRY(contextVk, waitSemaphore.get().importFd(device, importFdInfo));
541*8975f5c5SAndroid Build Coastguard Worker 
542*8975f5c5SAndroid Build Coastguard Worker     // Add semaphore to next submit job.
543*8975f5c5SAndroid Build Coastguard Worker     contextVk->addWaitSemaphore(waitSemaphore.get().getHandle(),
544*8975f5c5SAndroid Build Coastguard Worker                                 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
545*8975f5c5SAndroid Build Coastguard Worker     contextVk->addGarbage(&waitSemaphore.get());  // This releases the handle.
546*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
547*8975f5c5SAndroid Build Coastguard Worker }
548*8975f5c5SAndroid Build Coastguard Worker 
getStatus(Context * context,ContextVk * contextVk,bool * signaledOut)549*8975f5c5SAndroid Build Coastguard Worker angle::Result SyncHelperNativeFence::getStatus(Context *context,
550*8975f5c5SAndroid Build Coastguard Worker                                                ContextVk *contextVk,
551*8975f5c5SAndroid Build Coastguard Worker                                                bool *signaledOut)
552*8975f5c5SAndroid Build Coastguard Worker {
553*8975f5c5SAndroid Build Coastguard Worker     VkResult result = mExternalFence->getStatus(context->getDevice());
554*8975f5c5SAndroid Build Coastguard Worker     if (result != VK_NOT_READY)
555*8975f5c5SAndroid Build Coastguard Worker     {
556*8975f5c5SAndroid Build Coastguard Worker         ANGLE_VK_TRY(context, result);
557*8975f5c5SAndroid Build Coastguard Worker     }
558*8975f5c5SAndroid Build Coastguard Worker     *signaledOut = (result == VK_SUCCESS);
559*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
560*8975f5c5SAndroid Build Coastguard Worker }
561*8975f5c5SAndroid Build Coastguard Worker 
dupNativeFenceFD(Context * context,int * fdOut) const562*8975f5c5SAndroid Build Coastguard Worker angle::Result SyncHelperNativeFence::dupNativeFenceFD(Context *context, int *fdOut) const
563*8975f5c5SAndroid Build Coastguard Worker {
564*8975f5c5SAndroid Build Coastguard Worker     if (mExternalFence->getFenceFd() == kInvalidFenceFd)
565*8975f5c5SAndroid Build Coastguard Worker     {
566*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Stop;
567*8975f5c5SAndroid Build Coastguard Worker     }
568*8975f5c5SAndroid Build Coastguard Worker 
569*8975f5c5SAndroid Build Coastguard Worker     *fdOut = dup(mExternalFence->getFenceFd());
570*8975f5c5SAndroid Build Coastguard Worker 
571*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
572*8975f5c5SAndroid Build Coastguard Worker }
573*8975f5c5SAndroid Build Coastguard Worker 
574*8975f5c5SAndroid Build Coastguard Worker }  // namespace vk
575*8975f5c5SAndroid Build Coastguard Worker 
SyncVk()576*8975f5c5SAndroid Build Coastguard Worker SyncVk::SyncVk() : SyncImpl() {}
577*8975f5c5SAndroid Build Coastguard Worker 
~SyncVk()578*8975f5c5SAndroid Build Coastguard Worker SyncVk::~SyncVk() {}
579*8975f5c5SAndroid Build Coastguard Worker 
onDestroy(const gl::Context * context)580*8975f5c5SAndroid Build Coastguard Worker void SyncVk::onDestroy(const gl::Context *context)
581*8975f5c5SAndroid Build Coastguard Worker {
582*8975f5c5SAndroid Build Coastguard Worker     mSyncHelper.releaseToRenderer(vk::GetImpl(context)->getRenderer());
583*8975f5c5SAndroid Build Coastguard Worker }
584*8975f5c5SAndroid Build Coastguard Worker 
set(const gl::Context * context,GLenum condition,GLbitfield flags)585*8975f5c5SAndroid Build Coastguard Worker angle::Result SyncVk::set(const gl::Context *context, GLenum condition, GLbitfield flags)
586*8975f5c5SAndroid Build Coastguard Worker {
587*8975f5c5SAndroid Build Coastguard Worker     ASSERT(condition == GL_SYNC_GPU_COMMANDS_COMPLETE);
588*8975f5c5SAndroid Build Coastguard Worker     ASSERT(flags == 0);
589*8975f5c5SAndroid Build Coastguard Worker 
590*8975f5c5SAndroid Build Coastguard Worker     return mSyncHelper.initialize(vk::GetImpl(context), SyncFenceScope::CurrentContextToShareGroup);
591*8975f5c5SAndroid Build Coastguard Worker }
592*8975f5c5SAndroid Build Coastguard Worker 
clientWait(const gl::Context * context,GLbitfield flags,GLuint64 timeout,GLenum * outResult)593*8975f5c5SAndroid Build Coastguard Worker angle::Result SyncVk::clientWait(const gl::Context *context,
594*8975f5c5SAndroid Build Coastguard Worker                                  GLbitfield flags,
595*8975f5c5SAndroid Build Coastguard Worker                                  GLuint64 timeout,
596*8975f5c5SAndroid Build Coastguard Worker                                  GLenum *outResult)
597*8975f5c5SAndroid Build Coastguard Worker {
598*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk = vk::GetImpl(context);
599*8975f5c5SAndroid Build Coastguard Worker 
600*8975f5c5SAndroid Build Coastguard Worker     ASSERT((flags & ~GL_SYNC_FLUSH_COMMANDS_BIT) == 0);
601*8975f5c5SAndroid Build Coastguard Worker 
602*8975f5c5SAndroid Build Coastguard Worker     bool flush = (flags & GL_SYNC_FLUSH_COMMANDS_BIT) != 0;
603*8975f5c5SAndroid Build Coastguard Worker 
604*8975f5c5SAndroid Build Coastguard Worker     return mSyncHelper.clientWait(contextVk, contextVk, flush, static_cast<uint64_t>(timeout),
605*8975f5c5SAndroid Build Coastguard Worker                                   MapVkResultToGlenum, outResult);
606*8975f5c5SAndroid Build Coastguard Worker }
607*8975f5c5SAndroid Build Coastguard Worker 
serverWait(const gl::Context * context,GLbitfield flags,GLuint64 timeout)608*8975f5c5SAndroid Build Coastguard Worker angle::Result SyncVk::serverWait(const gl::Context *context, GLbitfield flags, GLuint64 timeout)
609*8975f5c5SAndroid Build Coastguard Worker {
610*8975f5c5SAndroid Build Coastguard Worker     ASSERT(flags == 0);
611*8975f5c5SAndroid Build Coastguard Worker     ASSERT(timeout == GL_TIMEOUT_IGNORED);
612*8975f5c5SAndroid Build Coastguard Worker 
613*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk = vk::GetImpl(context);
614*8975f5c5SAndroid Build Coastguard Worker     return mSyncHelper.serverWait(contextVk);
615*8975f5c5SAndroid Build Coastguard Worker }
616*8975f5c5SAndroid Build Coastguard Worker 
getStatus(const gl::Context * context,GLint * outResult)617*8975f5c5SAndroid Build Coastguard Worker angle::Result SyncVk::getStatus(const gl::Context *context, GLint *outResult)
618*8975f5c5SAndroid Build Coastguard Worker {
619*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk = vk::GetImpl(context);
620*8975f5c5SAndroid Build Coastguard Worker     bool signaled        = false;
621*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mSyncHelper.getStatus(contextVk, contextVk, &signaled));
622*8975f5c5SAndroid Build Coastguard Worker 
623*8975f5c5SAndroid Build Coastguard Worker     *outResult = signaled ? GL_SIGNALED : GL_UNSIGNALED;
624*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
625*8975f5c5SAndroid Build Coastguard Worker }
626*8975f5c5SAndroid Build Coastguard Worker 
EGLSyncVk()627*8975f5c5SAndroid Build Coastguard Worker EGLSyncVk::EGLSyncVk() : EGLSyncImpl(), mSyncHelper(nullptr) {}
628*8975f5c5SAndroid Build Coastguard Worker 
~EGLSyncVk()629*8975f5c5SAndroid Build Coastguard Worker EGLSyncVk::~EGLSyncVk() {}
630*8975f5c5SAndroid Build Coastguard Worker 
onDestroy(const egl::Display * display)631*8975f5c5SAndroid Build Coastguard Worker void EGLSyncVk::onDestroy(const egl::Display *display)
632*8975f5c5SAndroid Build Coastguard Worker {
633*8975f5c5SAndroid Build Coastguard Worker     mSyncHelper->releaseToRenderer(vk::GetImpl(display)->getRenderer());
634*8975f5c5SAndroid Build Coastguard Worker }
635*8975f5c5SAndroid Build Coastguard Worker 
initialize(const egl::Display * display,const gl::Context * context,EGLenum type,const egl::AttributeMap & attribs)636*8975f5c5SAndroid Build Coastguard Worker egl::Error EGLSyncVk::initialize(const egl::Display *display,
637*8975f5c5SAndroid Build Coastguard Worker                                  const gl::Context *context,
638*8975f5c5SAndroid Build Coastguard Worker                                  EGLenum type,
639*8975f5c5SAndroid Build Coastguard Worker                                  const egl::AttributeMap &attribs)
640*8975f5c5SAndroid Build Coastguard Worker {
641*8975f5c5SAndroid Build Coastguard Worker     ASSERT(context != nullptr);
642*8975f5c5SAndroid Build Coastguard Worker 
643*8975f5c5SAndroid Build Coastguard Worker     switch (type)
644*8975f5c5SAndroid Build Coastguard Worker     {
645*8975f5c5SAndroid Build Coastguard Worker         case EGL_SYNC_FENCE_KHR:
646*8975f5c5SAndroid Build Coastguard Worker         case EGL_SYNC_GLOBAL_FENCE_ANGLE:
647*8975f5c5SAndroid Build Coastguard Worker         {
648*8975f5c5SAndroid Build Coastguard Worker             vk::SyncHelper *syncHelper = new vk::SyncHelper();
649*8975f5c5SAndroid Build Coastguard Worker             mSyncHelper.reset(syncHelper);
650*8975f5c5SAndroid Build Coastguard Worker             const SyncFenceScope scope = type == EGL_SYNC_GLOBAL_FENCE_ANGLE
651*8975f5c5SAndroid Build Coastguard Worker                                              ? SyncFenceScope::AllContextsToAllContexts
652*8975f5c5SAndroid Build Coastguard Worker                                              : SyncFenceScope::CurrentContextToAllContexts;
653*8975f5c5SAndroid Build Coastguard Worker             if (syncHelper->initialize(vk::GetImpl(context), scope) == angle::Result::Stop)
654*8975f5c5SAndroid Build Coastguard Worker             {
655*8975f5c5SAndroid Build Coastguard Worker                 return egl::Error(EGL_BAD_ALLOC, "eglCreateSyncKHR failed to create sync object");
656*8975f5c5SAndroid Build Coastguard Worker             }
657*8975f5c5SAndroid Build Coastguard Worker             return egl::NoError();
658*8975f5c5SAndroid Build Coastguard Worker         }
659*8975f5c5SAndroid Build Coastguard Worker         case EGL_SYNC_NATIVE_FENCE_ANDROID:
660*8975f5c5SAndroid Build Coastguard Worker         {
661*8975f5c5SAndroid Build Coastguard Worker             vk::SyncHelperNativeFence *syncHelper = new vk::SyncHelperNativeFence();
662*8975f5c5SAndroid Build Coastguard Worker             mSyncHelper.reset(syncHelper);
663*8975f5c5SAndroid Build Coastguard Worker             EGLint nativeFenceFd =
664*8975f5c5SAndroid Build Coastguard Worker                 attribs.getAsInt(EGL_SYNC_NATIVE_FENCE_FD_ANDROID, EGL_NO_NATIVE_FENCE_FD_ANDROID);
665*8975f5c5SAndroid Build Coastguard Worker             return angle::ToEGL(syncHelper->initializeWithFd(vk::GetImpl(context), nativeFenceFd),
666*8975f5c5SAndroid Build Coastguard Worker                                 EGL_BAD_ALLOC);
667*8975f5c5SAndroid Build Coastguard Worker         }
668*8975f5c5SAndroid Build Coastguard Worker         default:
669*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
670*8975f5c5SAndroid Build Coastguard Worker             return egl::Error(EGL_BAD_ALLOC);
671*8975f5c5SAndroid Build Coastguard Worker     }
672*8975f5c5SAndroid Build Coastguard Worker }
673*8975f5c5SAndroid Build Coastguard Worker 
clientWait(const egl::Display * display,const gl::Context * context,EGLint flags,EGLTime timeout,EGLint * outResult)674*8975f5c5SAndroid Build Coastguard Worker egl::Error EGLSyncVk::clientWait(const egl::Display *display,
675*8975f5c5SAndroid Build Coastguard Worker                                  const gl::Context *context,
676*8975f5c5SAndroid Build Coastguard Worker                                  EGLint flags,
677*8975f5c5SAndroid Build Coastguard Worker                                  EGLTime timeout,
678*8975f5c5SAndroid Build Coastguard Worker                                  EGLint *outResult)
679*8975f5c5SAndroid Build Coastguard Worker {
680*8975f5c5SAndroid Build Coastguard Worker     ASSERT((flags & ~EGL_SYNC_FLUSH_COMMANDS_BIT_KHR) == 0);
681*8975f5c5SAndroid Build Coastguard Worker 
682*8975f5c5SAndroid Build Coastguard Worker     bool flush = (flags & EGL_SYNC_FLUSH_COMMANDS_BIT_KHR) != 0;
683*8975f5c5SAndroid Build Coastguard Worker 
684*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk = context != nullptr && flush ? vk::GetImpl(context) : nullptr;
685*8975f5c5SAndroid Build Coastguard Worker     if (mSyncHelper->clientWait(vk::GetImpl(display), contextVk, flush,
686*8975f5c5SAndroid Build Coastguard Worker                                 static_cast<uint64_t>(timeout), MapVkResultToEglint,
687*8975f5c5SAndroid Build Coastguard Worker                                 outResult) == angle::Result::Stop)
688*8975f5c5SAndroid Build Coastguard Worker     {
689*8975f5c5SAndroid Build Coastguard Worker         return egl::Error(EGL_BAD_ALLOC);
690*8975f5c5SAndroid Build Coastguard Worker     }
691*8975f5c5SAndroid Build Coastguard Worker 
692*8975f5c5SAndroid Build Coastguard Worker     return egl::NoError();
693*8975f5c5SAndroid Build Coastguard Worker }
694*8975f5c5SAndroid Build Coastguard Worker 
serverWait(const egl::Display * display,const gl::Context * context,EGLint flags)695*8975f5c5SAndroid Build Coastguard Worker egl::Error EGLSyncVk::serverWait(const egl::Display *display,
696*8975f5c5SAndroid Build Coastguard Worker                                  const gl::Context *context,
697*8975f5c5SAndroid Build Coastguard Worker                                  EGLint flags)
698*8975f5c5SAndroid Build Coastguard Worker {
699*8975f5c5SAndroid Build Coastguard Worker     // Server wait requires a valid bound context.
700*8975f5c5SAndroid Build Coastguard Worker     ASSERT(context);
701*8975f5c5SAndroid Build Coastguard Worker 
702*8975f5c5SAndroid Build Coastguard Worker     // No flags are currently implemented.
703*8975f5c5SAndroid Build Coastguard Worker     ASSERT(flags == 0);
704*8975f5c5SAndroid Build Coastguard Worker 
705*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk = vk::GetImpl(context);
706*8975f5c5SAndroid Build Coastguard Worker     return angle::ToEGL(mSyncHelper->serverWait(contextVk), EGL_BAD_ALLOC);
707*8975f5c5SAndroid Build Coastguard Worker }
708*8975f5c5SAndroid Build Coastguard Worker 
getStatus(const egl::Display * display,EGLint * outStatus)709*8975f5c5SAndroid Build Coastguard Worker egl::Error EGLSyncVk::getStatus(const egl::Display *display, EGLint *outStatus)
710*8975f5c5SAndroid Build Coastguard Worker {
711*8975f5c5SAndroid Build Coastguard Worker     bool signaled = false;
712*8975f5c5SAndroid Build Coastguard Worker     if (mSyncHelper->getStatus(vk::GetImpl(display), nullptr, &signaled) == angle::Result::Stop)
713*8975f5c5SAndroid Build Coastguard Worker     {
714*8975f5c5SAndroid Build Coastguard Worker         return egl::Error(EGL_BAD_ALLOC);
715*8975f5c5SAndroid Build Coastguard Worker     }
716*8975f5c5SAndroid Build Coastguard Worker 
717*8975f5c5SAndroid Build Coastguard Worker     *outStatus = signaled ? EGL_SIGNALED_KHR : EGL_UNSIGNALED_KHR;
718*8975f5c5SAndroid Build Coastguard Worker     return egl::NoError();
719*8975f5c5SAndroid Build Coastguard Worker }
720*8975f5c5SAndroid Build Coastguard Worker 
dupNativeFenceFD(const egl::Display * display,EGLint * fdOut) const721*8975f5c5SAndroid Build Coastguard Worker egl::Error EGLSyncVk::dupNativeFenceFD(const egl::Display *display, EGLint *fdOut) const
722*8975f5c5SAndroid Build Coastguard Worker {
723*8975f5c5SAndroid Build Coastguard Worker     return angle::ToEGL(mSyncHelper->dupNativeFenceFD(vk::GetImpl(display), fdOut),
724*8975f5c5SAndroid Build Coastguard Worker                         EGL_BAD_PARAMETER);
725*8975f5c5SAndroid Build Coastguard Worker }
726*8975f5c5SAndroid Build Coastguard Worker 
727*8975f5c5SAndroid Build Coastguard Worker }  // namespace rx
728