blob: 2636d9b683973350c1f912c7fef8cff10106c9f3 [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>
Robert Phillipse19babf2020-04-06 13:57:30 -040011#include "include/core/SkCanvas.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "include/core/SkSurface.h"
Robert Phillips6d344c32020-07-06 10:56:46 -040013#include "include/gpu/GrDirectContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "src/gpu/GrContextPriv.h"
15#include "src/gpu/GrGpu.h"
Greg Daniela3aa75a2019-04-12 14:24:55 -040016
17using namespace sk_gpu_test;
18
19static void testing_finished_proc(void* ctx) {
20 int* count = (int*)ctx;
21 *count += 1;
22}
23
Brian Salomonb0d8b762019-05-06 16:58:22 -040024static void busy_wait_for_callback(int* count, int expectedValue, GrContext* ctx,
25 skiatest::Reporter* reporter) {
26 // Busy waiting should detect that the work is done.
27 auto begin = std::chrono::steady_clock::now();
28 auto end = begin;
29 do {
30 ctx->checkAsyncWorkCompletion();
31 end = std::chrono::steady_clock::now();
32 } while (*count != expectedValue && (end - begin) < std::chrono::seconds(1));
33 if (*count != expectedValue) {
34 ERRORF(reporter, "Expected count failed to reach %d within 1 second of busy waiting.",
35 expectedValue);
36 }
37}
38
Greg Daniela3aa75a2019-04-12 14:24:55 -040039DEF_GPUTEST_FOR_RENDERING_CONTEXTS(FlushFinishedProcTest, reporter, ctxInfo) {
Robert Phillips6d344c32020-07-06 10:56:46 -040040 auto ctx = ctxInfo.directContext();
Greg Daniela3aa75a2019-04-12 14:24:55 -040041
42 SkImageInfo info =
43 SkImageInfo::Make(8, 8, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
44 sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info);
45 SkCanvas* canvas = surface->getCanvas();
46
Brian Salomonf9a1fdf2019-05-09 10:30:12 -040047 canvas->clear(SK_ColorGREEN);
48 auto image = surface->makeImageSnapshot();
49
Greg Danielce9f0162020-06-30 13:42:46 -040050 ctx->flush();
Greg Daniel0a2464f2020-05-14 15:45:44 -040051 ctx->submit(true);
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 Danielce9f0162020-06-30 13:42:46 -040059 surface->flush(flushInfoFinishedProc);
Greg Daniel0a2464f2020-05-14 15:45:44 -040060 ctx->submit();
Brian Salomonb0d8b762019-05-06 16:58:22 -040061 REPORTER_ASSERT(reporter, count == 0 || count == 1);
62 // Busy waiting should detect that the work is done.
63 busy_wait_for_callback(&count, 1, ctx, reporter);
Greg Daniela3aa75a2019-04-12 14:24:55 -040064
65 canvas->clear(SK_ColorRED);
66
Greg Danielce9f0162020-06-30 13:42:46 -040067 surface->flush(flushInfoFinishedProc);
Greg Daniel0a2464f2020-05-14 15:45:44 -040068 ctx->submit();
Greg Daniela3aa75a2019-04-12 14:24:55 -040069
Brian Salomonb0d8b762019-05-06 16:58:22 -040070 bool expectAsyncCallback =
71 ctx->backend() == GrBackendApi::kVulkan ||
Jim Van Verthf2f0e1b2019-10-01 10:10:56 -040072 ((ctx->backend() == GrBackendApi::kOpenGL) && ctx->priv().caps()->fenceSyncSupport()) ||
Stephen Whiteaf564a52020-04-16 16:13:58 -040073 ((ctx->backend() == GrBackendApi::kMetal) && ctx->priv().caps()->fenceSyncSupport()) ||
Greg Danield4928d02020-06-19 11:13:26 -040074 ctx->backend() == GrBackendApi::kDawn ||
75 ctx->backend() == GrBackendApi::kDirect3D;
Brian Salomonb0d8b762019-05-06 16:58:22 -040076 if (expectAsyncCallback) {
Greg Daniela3aa75a2019-04-12 14:24:55 -040077 // On Vulkan the command buffer we just submitted may or may not have finished immediately
78 // so the finish proc may not have been called.
79 REPORTER_ASSERT(reporter, count == 1 || count == 2);
80 } else {
81 REPORTER_ASSERT(reporter, count == 2);
82 }
Greg Danielce9f0162020-06-30 13:42:46 -040083 ctx->flush();
Greg Daniel0a2464f2020-05-14 15:45:44 -040084 ctx->submit(true);
Greg Daniela3aa75a2019-04-12 14:24:55 -040085 REPORTER_ASSERT(reporter, count == 2);
86
Brian Salomonf9a1fdf2019-05-09 10:30:12 -040087 // Test flushing via the SkImage
88 canvas->drawImage(image, 0, 0);
89 image->flush(ctx, flushInfoFinishedProc);
Greg Daniel0a2464f2020-05-14 15:45:44 -040090 ctx->submit();
Brian Salomonb0d8b762019-05-06 16:58:22 -040091 if (expectAsyncCallback) {
Greg Daniela3aa75a2019-04-12 14:24:55 -040092 // On Vulkan the command buffer we just submitted may or may not have finished immediately
93 // so the finish proc may not have been called.
94 REPORTER_ASSERT(reporter, count == 2 || count == 3);
95 } else {
96 REPORTER_ASSERT(reporter, count == 3);
97 }
Greg Danielce9f0162020-06-30 13:42:46 -040098 ctx->flush();
Greg Daniel0a2464f2020-05-14 15:45:44 -040099 ctx->submit(true);
Greg Daniela3aa75a2019-04-12 14:24:55 -0400100 REPORTER_ASSERT(reporter, count == 3);
101
Brian Salomonf9a1fdf2019-05-09 10:30:12 -0400102 // Test flushing via the GrContext
103 canvas->clear(SK_ColorBLUE);
104 ctx->flush(flushInfoFinishedProc);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400105 ctx->submit();
Brian Salomonf9a1fdf2019-05-09 10:30:12 -0400106 if (expectAsyncCallback) {
107 // On Vulkan the command buffer we just submitted may or may not have finished immediately
108 // so the finish proc may not have been called.
109 REPORTER_ASSERT(reporter, count == 3 || count == 4);
110 } else {
111 REPORTER_ASSERT(reporter, count == 4);
112 }
Greg Danielce9f0162020-06-30 13:42:46 -0400113 ctx->flush();
Greg Daniel0a2464f2020-05-14 15:45:44 -0400114 ctx->submit(true);
Brian Salomonf9a1fdf2019-05-09 10:30:12 -0400115 REPORTER_ASSERT(reporter, count == 4);
116
Brian Salomonb0d8b762019-05-06 16:58:22 -0400117 // There is no work on the surface so flushing may immediately call the finished proc.
Greg Daniele6bfb7d2019-04-17 15:26:11 -0400118 ctx->flush(flushInfoFinishedProc);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400119 ctx->submit();
Brian Salomonf9a1fdf2019-05-09 10:30:12 -0400120 REPORTER_ASSERT(reporter, count == 4 || count == 5);
121 busy_wait_for_callback(&count, 5, ctx, reporter);
Greg Daniela3aa75a2019-04-12 14:24:55 -0400122
123 count = 0;
124 int count2 = 0;
125 canvas->clear(SK_ColorGREEN);
Greg Danielce9f0162020-06-30 13:42:46 -0400126 surface->flush(flushInfoFinishedProc);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400127 ctx->submit();
Greg Daniela3aa75a2019-04-12 14:24:55 -0400128 // There is no work to be flushed here so this will return immediately, but make sure the
129 // finished call from this proc isn't called till the previous surface flush also is finished.
Greg Daniele6bfb7d2019-04-17 15:26:11 -0400130 flushInfoFinishedProc.fFinishedContext = (void*)&count2;
131 ctx->flush(flushInfoFinishedProc);
Greg Daniel0a2464f2020-05-14 15:45:44 -0400132 ctx->submit();
Brian Salomonb0d8b762019-05-06 16:58:22 -0400133 REPORTER_ASSERT(reporter, count <= 1 && count2 <= count);
Greg Daniela3aa75a2019-04-12 14:24:55 -0400134
Greg Danielce9f0162020-06-30 13:42:46 -0400135 ctx->flush();
Greg Daniel0a2464f2020-05-14 15:45:44 -0400136 ctx->submit(true);
Greg Daniela3aa75a2019-04-12 14:24:55 -0400137
138 REPORTER_ASSERT(reporter, count == 1);
139 REPORTER_ASSERT(reporter, count == count2);
140}
141