1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2017 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "include/core/SkBitmap.h"
9cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h"
10cb93a386Sopenharmony_ci#include "include/core/SkSurface.h"
11cb93a386Sopenharmony_ci#include "include/gpu/GrBackendSemaphore.h"
12cb93a386Sopenharmony_ci#include "include/gpu/GrBackendSurface.h"
13cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h"
14cb93a386Sopenharmony_ci#include "src/gpu/GrCaps.h"
15cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h"
16cb93a386Sopenharmony_ci#include "tests/Test.h"
17cb93a386Sopenharmony_ci#include "tools/gpu/GrContextFactory.h"
18cb93a386Sopenharmony_ci
19cb93a386Sopenharmony_ci#ifdef SK_GL
20cb93a386Sopenharmony_ci#include "src/gpu/gl/GrGLGpu.h"
21cb93a386Sopenharmony_ci#include "src/gpu/gl/GrGLUtil.h"
22cb93a386Sopenharmony_ci#endif
23cb93a386Sopenharmony_ci
24cb93a386Sopenharmony_ci#ifdef SK_VULKAN
25cb93a386Sopenharmony_ci#include "include/gpu/vk/GrVkTypes.h"
26cb93a386Sopenharmony_ci#include "include/gpu/vk/GrVkVulkan.h"
27cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkCommandPool.h"
28cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkGpu.h"
29cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkUtil.h"
30cb93a386Sopenharmony_ci
31cb93a386Sopenharmony_ci#ifdef VK_USE_PLATFORM_WIN32_KHR
32cb93a386Sopenharmony_ci// windows wants to define this as CreateSemaphoreA or CreateSemaphoreW
33cb93a386Sopenharmony_ci#undef CreateSemaphore
34cb93a386Sopenharmony_ci#endif
35cb93a386Sopenharmony_ci#endif
36cb93a386Sopenharmony_ci
37cb93a386Sopenharmony_cistatic const int MAIN_W = 8, MAIN_H = 16;
38cb93a386Sopenharmony_cistatic const int CHILD_W = 16, CHILD_H = 16;
39cb93a386Sopenharmony_ci
40cb93a386Sopenharmony_civoid check_pixels(skiatest::Reporter* reporter, const SkBitmap& bitmap) {
41cb93a386Sopenharmony_ci    const uint32_t* canvasPixels = static_cast<const uint32_t*>(bitmap.getPixels());
42cb93a386Sopenharmony_ci
43cb93a386Sopenharmony_ci    bool failureFound = false;
44cb93a386Sopenharmony_ci    SkPMColor expectedPixel;
45cb93a386Sopenharmony_ci    for (int cy = 0; cy < CHILD_H && !failureFound; ++cy) {
46cb93a386Sopenharmony_ci        for (int cx = 0; cx < CHILD_W && !failureFound; ++cx) {
47cb93a386Sopenharmony_ci            SkPMColor canvasPixel = canvasPixels[cy * CHILD_W + cx];
48cb93a386Sopenharmony_ci            if (cy < CHILD_H / 2) {
49cb93a386Sopenharmony_ci                if (cx < CHILD_W / 2) {
50cb93a386Sopenharmony_ci                    expectedPixel = 0xFF0000FF; // Red
51cb93a386Sopenharmony_ci                } else {
52cb93a386Sopenharmony_ci                    expectedPixel = 0xFFFF0000; // Blue
53cb93a386Sopenharmony_ci                }
54cb93a386Sopenharmony_ci            } else {
55cb93a386Sopenharmony_ci                expectedPixel = 0xFF00FF00; // Green
56cb93a386Sopenharmony_ci            }
57cb93a386Sopenharmony_ci            if (expectedPixel != canvasPixel) {
58cb93a386Sopenharmony_ci                failureFound = true;
59cb93a386Sopenharmony_ci                ERRORF(reporter, "Wrong color at %d, %d. Got 0x%08x when we expected 0x%08x",
60cb93a386Sopenharmony_ci                       cx, cy, canvasPixel, expectedPixel);
61cb93a386Sopenharmony_ci            }
62cb93a386Sopenharmony_ci        }
63cb93a386Sopenharmony_ci    }
64cb93a386Sopenharmony_ci}
65cb93a386Sopenharmony_ci
66cb93a386Sopenharmony_civoid draw_child(skiatest::Reporter* reporter,
67cb93a386Sopenharmony_ci                const sk_gpu_test::ContextInfo& childInfo,
68cb93a386Sopenharmony_ci                const GrBackendTexture& backendTexture,
69cb93a386Sopenharmony_ci                const GrBackendSemaphore& semaphore) {
70cb93a386Sopenharmony_ci
71cb93a386Sopenharmony_ci    childInfo.testContext()->makeCurrent();
72cb93a386Sopenharmony_ci
73cb93a386Sopenharmony_ci    const SkImageInfo childII = SkImageInfo::Make(CHILD_W, CHILD_H, kRGBA_8888_SkColorType,
74cb93a386Sopenharmony_ci                                                  kPremul_SkAlphaType);
75cb93a386Sopenharmony_ci
76cb93a386Sopenharmony_ci    auto childDContext = childInfo.directContext();
77cb93a386Sopenharmony_ci    sk_sp<SkSurface> childSurface(SkSurface::MakeRenderTarget(childDContext, SkBudgeted::kNo,
78cb93a386Sopenharmony_ci                                                              childII, 0, kTopLeft_GrSurfaceOrigin,
79cb93a386Sopenharmony_ci                                                              nullptr));
80cb93a386Sopenharmony_ci
81cb93a386Sopenharmony_ci    sk_sp<SkImage> childImage = SkImage::MakeFromTexture(childDContext,
82cb93a386Sopenharmony_ci                                                         backendTexture,
83cb93a386Sopenharmony_ci                                                         kTopLeft_GrSurfaceOrigin,
84cb93a386Sopenharmony_ci                                                         kRGBA_8888_SkColorType,
85cb93a386Sopenharmony_ci                                                         kPremul_SkAlphaType,
86cb93a386Sopenharmony_ci                                                         nullptr,
87cb93a386Sopenharmony_ci                                                         nullptr,
88cb93a386Sopenharmony_ci                                                         nullptr);
89cb93a386Sopenharmony_ci
90cb93a386Sopenharmony_ci    SkCanvas* childCanvas = childSurface->getCanvas();
91cb93a386Sopenharmony_ci    childCanvas->clear(SK_ColorRED);
92cb93a386Sopenharmony_ci
93cb93a386Sopenharmony_ci    childSurface->wait(1, &semaphore);
94cb93a386Sopenharmony_ci
95cb93a386Sopenharmony_ci    childCanvas->drawImage(childImage, CHILD_W/2, 0);
96cb93a386Sopenharmony_ci
97cb93a386Sopenharmony_ci    SkPaint paint;
98cb93a386Sopenharmony_ci    paint.setColor(SK_ColorGREEN);
99cb93a386Sopenharmony_ci    SkIRect rect = SkIRect::MakeLTRB(0, CHILD_H/2, CHILD_W, CHILD_H);
100cb93a386Sopenharmony_ci    childCanvas->drawIRect(rect, paint);
101cb93a386Sopenharmony_ci
102cb93a386Sopenharmony_ci    // read pixels
103cb93a386Sopenharmony_ci    SkBitmap bitmap;
104cb93a386Sopenharmony_ci    bitmap.allocPixels(childII);
105cb93a386Sopenharmony_ci    childSurface->readPixels(bitmap, 0, 0);
106cb93a386Sopenharmony_ci
107cb93a386Sopenharmony_ci    check_pixels(reporter, bitmap);
108cb93a386Sopenharmony_ci}
109cb93a386Sopenharmony_ci
110cb93a386Sopenharmony_cienum class FlushType { kSurface, kImage, kContext };
111cb93a386Sopenharmony_ci
112cb93a386Sopenharmony_civoid surface_semaphore_test(skiatest::Reporter* reporter,
113cb93a386Sopenharmony_ci                            const sk_gpu_test::ContextInfo& mainInfo,
114cb93a386Sopenharmony_ci                            const sk_gpu_test::ContextInfo& childInfo1,
115cb93a386Sopenharmony_ci                            const sk_gpu_test::ContextInfo& childInfo2,
116cb93a386Sopenharmony_ci                            FlushType flushType) {
117cb93a386Sopenharmony_ci    auto mainCtx = mainInfo.directContext();
118cb93a386Sopenharmony_ci    if (!mainCtx->priv().caps()->semaphoreSupport()) {
119cb93a386Sopenharmony_ci        return;
120cb93a386Sopenharmony_ci    }
121cb93a386Sopenharmony_ci
122cb93a386Sopenharmony_ci    const SkImageInfo ii = SkImageInfo::Make(MAIN_W, MAIN_H, kRGBA_8888_SkColorType,
123cb93a386Sopenharmony_ci                                             kPremul_SkAlphaType);
124cb93a386Sopenharmony_ci
125cb93a386Sopenharmony_ci    sk_sp<SkSurface> mainSurface(SkSurface::MakeRenderTarget(mainCtx, SkBudgeted::kNo,
126cb93a386Sopenharmony_ci                                                             ii, 0, kTopLeft_GrSurfaceOrigin,
127cb93a386Sopenharmony_ci                                                             nullptr));
128cb93a386Sopenharmony_ci    SkCanvas* mainCanvas = mainSurface->getCanvas();
129cb93a386Sopenharmony_ci    auto blueSurface = mainSurface->makeSurface(ii);
130cb93a386Sopenharmony_ci    blueSurface->getCanvas()->clear(SK_ColorBLUE);
131cb93a386Sopenharmony_ci    auto blueImage = blueSurface->makeImageSnapshot();
132cb93a386Sopenharmony_ci    blueSurface.reset();
133cb93a386Sopenharmony_ci    mainCanvas->drawImage(blueImage, 0, 0);
134cb93a386Sopenharmony_ci
135cb93a386Sopenharmony_ci    SkAutoTArray<GrBackendSemaphore> semaphores(2);
136cb93a386Sopenharmony_ci#ifdef SK_VULKAN
137cb93a386Sopenharmony_ci    if (GrBackendApi::kVulkan == mainInfo.backend()) {
138cb93a386Sopenharmony_ci        // Initialize the secondary semaphore instead of having Ganesh create one internally
139cb93a386Sopenharmony_ci        GrVkGpu* gpu = static_cast<GrVkGpu*>(mainCtx->priv().getGpu());
140cb93a386Sopenharmony_ci        VkDevice device = gpu->device();
141cb93a386Sopenharmony_ci
142cb93a386Sopenharmony_ci        VkSemaphore vkSem;
143cb93a386Sopenharmony_ci
144cb93a386Sopenharmony_ci        VkSemaphoreCreateInfo createInfo;
145cb93a386Sopenharmony_ci        createInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
146cb93a386Sopenharmony_ci        createInfo.pNext = nullptr;
147cb93a386Sopenharmony_ci        createInfo.flags = 0;
148cb93a386Sopenharmony_ci        GR_VK_CALL_ERRCHECK(gpu, CreateSemaphore(device, &createInfo, nullptr, &vkSem));
149cb93a386Sopenharmony_ci
150cb93a386Sopenharmony_ci        semaphores[1].initVulkan(vkSem);
151cb93a386Sopenharmony_ci    }
152cb93a386Sopenharmony_ci#endif
153cb93a386Sopenharmony_ci
154cb93a386Sopenharmony_ci    GrFlushInfo info;
155cb93a386Sopenharmony_ci    info.fNumSemaphores = 2;
156cb93a386Sopenharmony_ci    info.fSignalSemaphores = semaphores.get();
157cb93a386Sopenharmony_ci    switch (flushType) {
158cb93a386Sopenharmony_ci        case FlushType::kSurface:
159cb93a386Sopenharmony_ci            mainSurface->flush(SkSurface::BackendSurfaceAccess::kNoAccess, info);
160cb93a386Sopenharmony_ci            break;
161cb93a386Sopenharmony_ci        case FlushType::kImage:
162cb93a386Sopenharmony_ci            blueImage->flush(mainCtx, info);
163cb93a386Sopenharmony_ci            break;
164cb93a386Sopenharmony_ci        case FlushType::kContext:
165cb93a386Sopenharmony_ci            mainCtx->flush(info);
166cb93a386Sopenharmony_ci            break;
167cb93a386Sopenharmony_ci    }
168cb93a386Sopenharmony_ci    mainCtx->submit();
169cb93a386Sopenharmony_ci
170cb93a386Sopenharmony_ci    GrBackendTexture backendTexture = mainSurface->getBackendTexture(
171cb93a386Sopenharmony_ci            SkSurface::BackendHandleAccess::kFlushRead_BackendHandleAccess);
172cb93a386Sopenharmony_ci
173cb93a386Sopenharmony_ci    draw_child(reporter, childInfo1, backendTexture, semaphores[0]);
174cb93a386Sopenharmony_ci
175cb93a386Sopenharmony_ci#ifdef SK_VULKAN
176cb93a386Sopenharmony_ci    if (GrBackendApi::kVulkan == mainInfo.backend()) {
177cb93a386Sopenharmony_ci        // In Vulkan we need to make sure we are sending the correct VkImageLayout in with the
178cb93a386Sopenharmony_ci        // backendImage. After the first child draw the layout gets changed to SHADER_READ, so
179cb93a386Sopenharmony_ci        // we just manually set that here.
180cb93a386Sopenharmony_ci        backendTexture.setVkImageLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
181cb93a386Sopenharmony_ci    }
182cb93a386Sopenharmony_ci#endif
183cb93a386Sopenharmony_ci
184cb93a386Sopenharmony_ci    draw_child(reporter, childInfo2, backendTexture, semaphores[1]);
185cb93a386Sopenharmony_ci}
186cb93a386Sopenharmony_ci
187cb93a386Sopenharmony_ci#ifdef SK_GL
188cb93a386Sopenharmony_ciDEF_GPUTEST(SurfaceSemaphores, reporter, options) {
189cb93a386Sopenharmony_ci#if defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_MAC)
190cb93a386Sopenharmony_ci    static constexpr auto kNativeGLType = sk_gpu_test::GrContextFactory::kGL_ContextType;
191cb93a386Sopenharmony_ci#else
192cb93a386Sopenharmony_ci    static constexpr auto kNativeGLType = sk_gpu_test::GrContextFactory::kGLES_ContextType;
193cb93a386Sopenharmony_ci#endif
194cb93a386Sopenharmony_ci
195cb93a386Sopenharmony_ci    for (int typeInt = 0; typeInt < sk_gpu_test::GrContextFactory::kContextTypeCnt; ++typeInt) {
196cb93a386Sopenharmony_ci        for (auto flushType : {FlushType::kSurface, FlushType::kImage, FlushType::kContext}) {
197cb93a386Sopenharmony_ci            sk_gpu_test::GrContextFactory::ContextType contextType =
198cb93a386Sopenharmony_ci                    (sk_gpu_test::GrContextFactory::ContextType) typeInt;
199cb93a386Sopenharmony_ci            // Use "native" instead of explicitly trying OpenGL and OpenGL ES. Do not use GLES on
200cb93a386Sopenharmony_ci            // desktop since tests do not account for not fixing http://skbug.com/2809
201cb93a386Sopenharmony_ci            if (contextType == sk_gpu_test::GrContextFactory::kGL_ContextType ||
202cb93a386Sopenharmony_ci                contextType == sk_gpu_test::GrContextFactory::kGLES_ContextType) {
203cb93a386Sopenharmony_ci                if (contextType != kNativeGLType) {
204cb93a386Sopenharmony_ci                    continue;
205cb93a386Sopenharmony_ci                }
206cb93a386Sopenharmony_ci            }
207cb93a386Sopenharmony_ci            sk_gpu_test::GrContextFactory factory(options);
208cb93a386Sopenharmony_ci            sk_gpu_test::ContextInfo ctxInfo = factory.getContextInfo(contextType);
209cb93a386Sopenharmony_ci            if (!sk_gpu_test::GrContextFactory::IsRenderingContext(contextType)) {
210cb93a386Sopenharmony_ci                continue;
211cb93a386Sopenharmony_ci            }
212cb93a386Sopenharmony_ci            skiatest::ReporterContext ctx(
213cb93a386Sopenharmony_ci                   reporter, SkString(sk_gpu_test::GrContextFactory::ContextTypeName(contextType)));
214cb93a386Sopenharmony_ci            if (ctxInfo.directContext()) {
215cb93a386Sopenharmony_ci                sk_gpu_test::ContextInfo child1 =
216cb93a386Sopenharmony_ci                        factory.getSharedContextInfo(ctxInfo.directContext(), 0);
217cb93a386Sopenharmony_ci                sk_gpu_test::ContextInfo child2 =
218cb93a386Sopenharmony_ci                        factory.getSharedContextInfo(ctxInfo.directContext(), 1);
219cb93a386Sopenharmony_ci                if (!child1.directContext() || !child2.directContext()) {
220cb93a386Sopenharmony_ci                    continue;
221cb93a386Sopenharmony_ci                }
222cb93a386Sopenharmony_ci
223cb93a386Sopenharmony_ci                surface_semaphore_test(reporter, ctxInfo, child1, child2, flushType);
224cb93a386Sopenharmony_ci            }
225cb93a386Sopenharmony_ci        }
226cb93a386Sopenharmony_ci    }
227cb93a386Sopenharmony_ci}
228cb93a386Sopenharmony_ci#endif
229cb93a386Sopenharmony_ci
230cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(EmptySurfaceSemaphoreTest, reporter, ctxInfo) {
231cb93a386Sopenharmony_ci    auto ctx = ctxInfo.directContext();
232cb93a386Sopenharmony_ci    if (!ctx->priv().caps()->semaphoreSupport()) {
233cb93a386Sopenharmony_ci        return;
234cb93a386Sopenharmony_ci    }
235cb93a386Sopenharmony_ci
236cb93a386Sopenharmony_ci    const SkImageInfo ii = SkImageInfo::Make(MAIN_W, MAIN_H, kRGBA_8888_SkColorType,
237cb93a386Sopenharmony_ci                                             kPremul_SkAlphaType);
238cb93a386Sopenharmony_ci
239cb93a386Sopenharmony_ci    sk_sp<SkSurface> mainSurface(SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo,
240cb93a386Sopenharmony_ci                                                             ii, 0, kTopLeft_GrSurfaceOrigin,
241cb93a386Sopenharmony_ci                                                             nullptr));
242cb93a386Sopenharmony_ci
243cb93a386Sopenharmony_ci    // Flush surface once without semaphores to make sure there is no peneding IO for it.
244cb93a386Sopenharmony_ci    mainSurface->flushAndSubmit();
245cb93a386Sopenharmony_ci
246cb93a386Sopenharmony_ci    GrBackendSemaphore semaphore;
247cb93a386Sopenharmony_ci    GrFlushInfo flushInfo;
248cb93a386Sopenharmony_ci    flushInfo.fNumSemaphores = 1;
249cb93a386Sopenharmony_ci    flushInfo.fSignalSemaphores = &semaphore;
250cb93a386Sopenharmony_ci    GrSemaphoresSubmitted submitted =
251cb93a386Sopenharmony_ci            mainSurface->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo);
252cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, GrSemaphoresSubmitted::kYes == submitted);
253cb93a386Sopenharmony_ci    ctx->submit();
254cb93a386Sopenharmony_ci
255cb93a386Sopenharmony_ci#ifdef SK_GL
256cb93a386Sopenharmony_ci    if (GrBackendApi::kOpenGL == ctxInfo.backend()) {
257cb93a386Sopenharmony_ci        GrGLGpu* gpu = static_cast<GrGLGpu*>(ctx->priv().getGpu());
258cb93a386Sopenharmony_ci        const GrGLInterface* interface = gpu->glInterface();
259cb93a386Sopenharmony_ci        GrGLsync sync = semaphore.glSync();
260cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, sync);
261cb93a386Sopenharmony_ci        bool result;
262cb93a386Sopenharmony_ci        GR_GL_CALL_RET(interface, result, IsSync(sync));
263cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, result);
264cb93a386Sopenharmony_ci    }
265cb93a386Sopenharmony_ci#endif
266cb93a386Sopenharmony_ci
267cb93a386Sopenharmony_ci#ifdef SK_VULKAN
268cb93a386Sopenharmony_ci    if (GrBackendApi::kVulkan == ctxInfo.backend()) {
269cb93a386Sopenharmony_ci        GrVkGpu* gpu = static_cast<GrVkGpu*>(ctx->priv().getGpu());
270cb93a386Sopenharmony_ci        const GrVkInterface* interface = gpu->vkInterface();
271cb93a386Sopenharmony_ci        VkDevice device = gpu->device();
272cb93a386Sopenharmony_ci        VkQueue queue = gpu->queue();
273cb93a386Sopenharmony_ci        GrVkCommandPool* cmdPool = gpu->cmdPool();
274cb93a386Sopenharmony_ci        VkCommandBuffer cmdBuffer;
275cb93a386Sopenharmony_ci
276cb93a386Sopenharmony_ci        // Create Command Buffer
277cb93a386Sopenharmony_ci        const VkCommandBufferAllocateInfo cmdInfo = {
278cb93a386Sopenharmony_ci            VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,   // sType
279cb93a386Sopenharmony_ci            nullptr,                                          // pNext
280cb93a386Sopenharmony_ci            cmdPool->vkCommandPool(),                         // commandPool
281cb93a386Sopenharmony_ci            VK_COMMAND_BUFFER_LEVEL_PRIMARY,                  // level
282cb93a386Sopenharmony_ci            1                                                 // bufferCount
283cb93a386Sopenharmony_ci        };
284cb93a386Sopenharmony_ci
285cb93a386Sopenharmony_ci        VkResult err = GR_VK_CALL(interface, AllocateCommandBuffers(device, &cmdInfo, &cmdBuffer));
286cb93a386Sopenharmony_ci        if (err) {
287cb93a386Sopenharmony_ci            return;
288cb93a386Sopenharmony_ci        }
289cb93a386Sopenharmony_ci
290cb93a386Sopenharmony_ci        VkCommandBufferBeginInfo cmdBufferBeginInfo;
291cb93a386Sopenharmony_ci        memset(&cmdBufferBeginInfo, 0, sizeof(VkCommandBufferBeginInfo));
292cb93a386Sopenharmony_ci        cmdBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
293cb93a386Sopenharmony_ci        cmdBufferBeginInfo.pNext = nullptr;
294cb93a386Sopenharmony_ci        cmdBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
295cb93a386Sopenharmony_ci        cmdBufferBeginInfo.pInheritanceInfo = nullptr;
296cb93a386Sopenharmony_ci
297cb93a386Sopenharmony_ci        GR_VK_CALL_ERRCHECK(gpu, BeginCommandBuffer(cmdBuffer, &cmdBufferBeginInfo));
298cb93a386Sopenharmony_ci        GR_VK_CALL_ERRCHECK(gpu, EndCommandBuffer(cmdBuffer));
299cb93a386Sopenharmony_ci
300cb93a386Sopenharmony_ci        VkFenceCreateInfo fenceInfo;
301cb93a386Sopenharmony_ci        VkFence fence;
302cb93a386Sopenharmony_ci
303cb93a386Sopenharmony_ci        memset(&fenceInfo, 0, sizeof(VkFenceCreateInfo));
304cb93a386Sopenharmony_ci        fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
305cb93a386Sopenharmony_ci        err = GR_VK_CALL(interface, CreateFence(device, &fenceInfo, nullptr, &fence));
306cb93a386Sopenharmony_ci        SkASSERT(!err);
307cb93a386Sopenharmony_ci
308cb93a386Sopenharmony_ci        VkPipelineStageFlags waitStages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
309cb93a386Sopenharmony_ci        VkSubmitInfo submitInfo;
310cb93a386Sopenharmony_ci        memset(&submitInfo, 0, sizeof(VkSubmitInfo));
311cb93a386Sopenharmony_ci        submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
312cb93a386Sopenharmony_ci        submitInfo.pNext = nullptr;
313cb93a386Sopenharmony_ci        submitInfo.waitSemaphoreCount = 1;
314cb93a386Sopenharmony_ci        VkSemaphore vkSem = semaphore.vkSemaphore();
315cb93a386Sopenharmony_ci        submitInfo.pWaitSemaphores = &vkSem;
316cb93a386Sopenharmony_ci        submitInfo.pWaitDstStageMask = &waitStages;
317cb93a386Sopenharmony_ci        submitInfo.commandBufferCount = 1;
318cb93a386Sopenharmony_ci        submitInfo.pCommandBuffers = &cmdBuffer;
319cb93a386Sopenharmony_ci        submitInfo.signalSemaphoreCount = 0;
320cb93a386Sopenharmony_ci        submitInfo.pSignalSemaphores = nullptr;
321cb93a386Sopenharmony_ci        GR_VK_CALL_ERRCHECK(gpu, QueueSubmit(queue, 1, &submitInfo, fence));
322cb93a386Sopenharmony_ci
323cb93a386Sopenharmony_ci        err = GR_VK_CALL(interface, WaitForFences(device, 1, &fence, true, 3000000000));
324cb93a386Sopenharmony_ci
325cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, err != VK_TIMEOUT);
326cb93a386Sopenharmony_ci
327cb93a386Sopenharmony_ci        GR_VK_CALL(interface, DestroyFence(device, fence, nullptr));
328cb93a386Sopenharmony_ci        GR_VK_CALL(interface, DestroySemaphore(device, vkSem, nullptr));
329cb93a386Sopenharmony_ci        // If the above test fails the wait semaphore will never be signaled which can cause the
330cb93a386Sopenharmony_ci        // device to hang when tearing down (even if just tearing down GL). So we Fail here to
331cb93a386Sopenharmony_ci        // kill things.
332cb93a386Sopenharmony_ci        if (err == VK_TIMEOUT) {
333cb93a386Sopenharmony_ci            SK_ABORT("Waiting on semaphore indefinitely");
334cb93a386Sopenharmony_ci        }
335cb93a386Sopenharmony_ci    }
336cb93a386Sopenharmony_ci#endif
337cb93a386Sopenharmony_ci}
338