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