blob: 18bfd0529625c04fa9395e000013546d7c0341a2 [file] [log] [blame]
Greg Daniela3aa75a2019-04-12 14:24:55 -04001/*
2 * Copyright 2019 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "tests/Test.h"
Greg Daniela3aa75a2019-04-12 14:24:55 -04009
Brian Salomonb0d8b762019-05-06 16:58:22 -040010#include <chrono>
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "include/core/SkSurface.h"
12#include "include/gpu/GrContext.h"
13#include "src/gpu/GrContextPriv.h"
14#include "src/gpu/GrGpu.h"
Greg Daniela3aa75a2019-04-12 14:24:55 -040015
16using namespace sk_gpu_test;
17
18static void testing_finished_proc(void* ctx) {
19 int* count = (int*)ctx;
20 *count += 1;
21}
22
Brian Salomonb0d8b762019-05-06 16:58:22 -040023static void busy_wait_for_callback(int* count, int expectedValue, GrContext* ctx,
24 skiatest::Reporter* reporter) {
25 // Busy waiting should detect that the work is done.
26 auto begin = std::chrono::steady_clock::now();
27 auto end = begin;
28 do {
29 ctx->checkAsyncWorkCompletion();
30 end = std::chrono::steady_clock::now();
31 } while (*count != expectedValue && (end - begin) < std::chrono::seconds(1));
32 if (*count != expectedValue) {
33 ERRORF(reporter, "Expected count failed to reach %d within 1 second of busy waiting.",
34 expectedValue);
35 }
36}
37
Greg Daniela3aa75a2019-04-12 14:24:55 -040038DEF_GPUTEST_FOR_RENDERING_CONTEXTS(FlushFinishedProcTest, reporter, ctxInfo) {
39 GrContext* ctx = ctxInfo.grContext();
40
41 SkImageInfo info =
42 SkImageInfo::Make(8, 8, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
43 sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info);
44 SkCanvas* canvas = surface->getCanvas();
45
Brian Salomonf9a1fdf2019-05-09 10:30:12 -040046 canvas->clear(SK_ColorGREEN);
47 auto image = surface->makeImageSnapshot();
48
Greg Daniele6bfb7d2019-04-17 15:26:11 -040049 GrFlushInfo flushInfoSyncCpu;
50 flushInfoSyncCpu.fFlags = kSyncCpu_GrFlushFlag;
51 ctx->flush(flushInfoSyncCpu);
Greg Daniela3aa75a2019-04-12 14:24:55 -040052
53 int count = 0;
54
Greg Daniele6bfb7d2019-04-17 15:26:11 -040055 GrFlushInfo flushInfoFinishedProc;
56 flushInfoFinishedProc.fFinishedProc = testing_finished_proc;
57 flushInfoFinishedProc.fFinishedContext = (void*)&count;
Brian Salomonb0d8b762019-05-06 16:58:22 -040058 // There is no work on the surface so flushing may immediately call the finished proc.
Greg Daniele6bfb7d2019-04-17 15:26:11 -040059 surface->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfoFinishedProc);
Brian Salomonb0d8b762019-05-06 16:58:22 -040060 REPORTER_ASSERT(reporter, count == 0 || count == 1);
61 // Busy waiting should detect that the work is done.
62 busy_wait_for_callback(&count, 1, ctx, reporter);
Greg Daniela3aa75a2019-04-12 14:24:55 -040063
64 canvas->clear(SK_ColorRED);
65
Greg Daniele6bfb7d2019-04-17 15:26:11 -040066 surface->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfoFinishedProc);
Greg Daniela3aa75a2019-04-12 14:24:55 -040067
Brian Salomonb0d8b762019-05-06 16:58:22 -040068 bool expectAsyncCallback =
69 ctx->backend() == GrBackendApi::kVulkan ||
Jim Van Verthf2f0e1b2019-10-01 10:10:56 -040070 ((ctx->backend() == GrBackendApi::kOpenGL) && ctx->priv().caps()->fenceSyncSupport()) ||
71 ((ctx->backend() == GrBackendApi::kMetal) && ctx->priv().caps()->fenceSyncSupport());
Brian Salomonb0d8b762019-05-06 16:58:22 -040072 if (expectAsyncCallback) {
Greg Daniela3aa75a2019-04-12 14:24:55 -040073 // On Vulkan the command buffer we just submitted may or may not have finished immediately
74 // so the finish proc may not have been called.
75 REPORTER_ASSERT(reporter, count == 1 || count == 2);
76 } else {
77 REPORTER_ASSERT(reporter, count == 2);
78 }
Greg Daniele6bfb7d2019-04-17 15:26:11 -040079 ctx->flush(flushInfoSyncCpu);
Greg Daniela3aa75a2019-04-12 14:24:55 -040080 REPORTER_ASSERT(reporter, count == 2);
81
Brian Salomonf9a1fdf2019-05-09 10:30:12 -040082 // Test flushing via the SkImage
83 canvas->drawImage(image, 0, 0);
84 image->flush(ctx, flushInfoFinishedProc);
Brian Salomonb0d8b762019-05-06 16:58:22 -040085 if (expectAsyncCallback) {
Greg Daniela3aa75a2019-04-12 14:24:55 -040086 // On Vulkan the command buffer we just submitted may or may not have finished immediately
87 // so the finish proc may not have been called.
88 REPORTER_ASSERT(reporter, count == 2 || count == 3);
89 } else {
90 REPORTER_ASSERT(reporter, count == 3);
91 }
Greg Daniele6bfb7d2019-04-17 15:26:11 -040092 ctx->flush(flushInfoSyncCpu);
Greg Daniela3aa75a2019-04-12 14:24:55 -040093 REPORTER_ASSERT(reporter, count == 3);
94
Brian Salomonf9a1fdf2019-05-09 10:30:12 -040095 // Test flushing via the GrContext
96 canvas->clear(SK_ColorBLUE);
97 ctx->flush(flushInfoFinishedProc);
98 if (expectAsyncCallback) {
99 // On Vulkan the command buffer we just submitted may or may not have finished immediately
100 // so the finish proc may not have been called.
101 REPORTER_ASSERT(reporter, count == 3 || count == 4);
102 } else {
103 REPORTER_ASSERT(reporter, count == 4);
104 }
105 ctx->flush(flushInfoSyncCpu);
106 REPORTER_ASSERT(reporter, count == 4);
107
Brian Salomonb0d8b762019-05-06 16:58:22 -0400108 // There is no work on the surface so flushing may immediately call the finished proc.
Greg Daniele6bfb7d2019-04-17 15:26:11 -0400109 ctx->flush(flushInfoFinishedProc);
Brian Salomonf9a1fdf2019-05-09 10:30:12 -0400110 REPORTER_ASSERT(reporter, count == 4 || count == 5);
111 busy_wait_for_callback(&count, 5, ctx, reporter);
Greg Daniela3aa75a2019-04-12 14:24:55 -0400112
113 count = 0;
114 int count2 = 0;
115 canvas->clear(SK_ColorGREEN);
Greg Daniele6bfb7d2019-04-17 15:26:11 -0400116 surface->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfoFinishedProc);
Greg Daniela3aa75a2019-04-12 14:24:55 -0400117 // There is no work to be flushed here so this will return immediately, but make sure the
118 // finished call from this proc isn't called till the previous surface flush also is finished.
Greg Daniele6bfb7d2019-04-17 15:26:11 -0400119 flushInfoFinishedProc.fFinishedContext = (void*)&count2;
120 ctx->flush(flushInfoFinishedProc);
Brian Salomonb0d8b762019-05-06 16:58:22 -0400121 REPORTER_ASSERT(reporter, count <= 1 && count2 <= count);
Greg Daniela3aa75a2019-04-12 14:24:55 -0400122
Greg Daniele6bfb7d2019-04-17 15:26:11 -0400123 ctx->flush(flushInfoSyncCpu);
Greg Daniela3aa75a2019-04-12 14:24:55 -0400124
125 REPORTER_ASSERT(reporter, count == 1);
126 REPORTER_ASSERT(reporter, count == count2);
127}
128