Flutter Engine
The Flutter Engine
GrFinishedFlushTest.cpp
Go to the documentation of this file.
1/*
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
15#include "include/core/SkRect.h"
21#include "include/gpu/GrTypes.h"
26#include "tests/Test.h"
27#include "tools/gpu/FenceSync.h"
29
30#include <chrono>
31#include <memory>
32
33struct GrContextOptions;
34
35using namespace sk_gpu_test;
36
37static void testing_finished_proc(void* ctx) {
38 int* count = (int*)ctx;
39 *count += 1;
40}
41
42static void busy_wait_for_callback(int* count, int expectedValue, GrDirectContext* dContext,
44 // Busy waiting should detect that the work is done.
45 auto begin = std::chrono::steady_clock::now();
46 auto end = begin;
47 do {
48 dContext->checkAsyncWorkCompletion();
49 end = std::chrono::steady_clock::now();
50 } while (*count != expectedValue && (end - begin) < std::chrono::seconds(1));
51 if (*count != expectedValue) {
52 ERRORF(reporter, "Expected count failed to reach %d within 1 second of busy waiting.",
53 expectedValue);
54 }
55}
56
59 ctxInfo,
61 auto dContext = ctxInfo.directContext();
62
66 SkCanvas* canvas = surface->getCanvas();
67
68 canvas->clear(SK_ColorGREEN);
69 auto image = surface->makeImageSnapshot();
70
71 dContext->flush();
72 dContext->submit(GrSyncCpu::kYes);
73
74 int count = 0;
75
76 GrFlushInfo flushInfoFinishedProc;
77 flushInfoFinishedProc.fFinishedProc = testing_finished_proc;
78 flushInfoFinishedProc.fFinishedContext = (void*)&count;
79 // There is no work on the surface so flushing may immediately call the finished proc.
80 dContext->flush(surface.get(), flushInfoFinishedProc);
81 dContext->submit();
82 REPORTER_ASSERT(reporter, count == 0 || count == 1);
83 // Busy waiting should detect that the work is done.
85
86 canvas->clear(SK_ColorRED);
87
88 dContext->flush(surface.get(), flushInfoFinishedProc);
89 dContext->submit(GrSyncCpu::kNo);
90
91 bool expectAsyncCallback = dContext->priv().caps()->finishedProcAsyncCallbackSupport();
92 if (expectAsyncCallback) {
93 // On Vulkan the command buffer we just submitted may or may not have finished immediately
94 // so the finish proc may not have been called.
95 REPORTER_ASSERT(reporter, count == 1 || count == 2);
96 } else {
98 }
99 dContext->flush();
100 dContext->submit(GrSyncCpu::kYes);
102
103 // Test flushing via the SkImage
104 canvas->drawImage(image, 0, 0);
105 dContext->flush(image, flushInfoFinishedProc);
106 dContext->submit(GrSyncCpu::kNo);
107 if (expectAsyncCallback) {
108 // On Vulkan the command buffer we just submitted may or may not have finished immediately
109 // so the finish proc may not have been called.
110 REPORTER_ASSERT(reporter, count == 2 || count == 3);
111 } else {
113 }
114 dContext->flush();
115 dContext->submit(GrSyncCpu::kYes);
117
118 // Test flushing via the GrDirectContext
119 canvas->clear(SK_ColorBLUE);
120 dContext->flush(flushInfoFinishedProc);
121 dContext->submit(GrSyncCpu::kNo);
122 if (expectAsyncCallback) {
123 // On Vulkan the command buffer we just submitted may or may not have finished immediately
124 // so the finish proc may not have been called.
125 REPORTER_ASSERT(reporter, count == 3 || count == 4);
126 } else {
128 }
129 dContext->flush();
130 dContext->submit(GrSyncCpu::kYes);
132
133 // There is no work on the surface so flushing may immediately call the finished proc.
134 dContext->flush(flushInfoFinishedProc);
135 dContext->submit(GrSyncCpu::kNo);
136 REPORTER_ASSERT(reporter, count == 4 || count == 5);
137 busy_wait_for_callback(&count, 5, dContext, reporter);
138
139 count = 0;
140 int count2 = 0;
141 canvas->clear(SK_ColorGREEN);
142 dContext->flush(surface.get(), flushInfoFinishedProc);
143 dContext->submit(GrSyncCpu::kNo);
144 // There is no work to be flushed here so this will return immediately, but make sure the
145 // finished call from this proc isn't called till the previous surface flush also is finished.
146 flushInfoFinishedProc.fFinishedContext = (void*)&count2;
147 dContext->flush(flushInfoFinishedProc);
148 dContext->submit(GrSyncCpu::kNo);
149 REPORTER_ASSERT(reporter, count <= 1 && count2 <= count);
150
151 dContext->flush();
152 dContext->submit(GrSyncCpu::kYes);
153
155 REPORTER_ASSERT(reporter, count == count2);
156}
157
158
159static void abandon_context(void* context) {
160 ((GrDirectContext*)context)->abandonContext();
161}
162
163static void async_callback(void* c, std::unique_ptr<const SkImage::AsyncReadResult> result) {
164 // We don't actually care about the results so just drop them without doing anything.
165}
166
167// This test checks that calls to the async read pixels callback can safely be made even if the
168// context has been abandoned previously. Specifically there was a bug where the client buffer
169// manager stored on the GrDirectContext was accessed in the async callback after it was deleted.
170// This bug is detected on ASAN bots running non GL backends (GL isn't affected purely based on
171// how we call finish callbacks during abandon).
172DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(FinishedAsyncProcWhenAbandonedTest,
173 reporter,
174 ctxInfo,
176 auto dContext = ctxInfo.directContext();
177
180
181 auto mbet = sk_gpu_test::ManagedBackendTexture::MakeFromInfo(
183 if (!mbet) {
184 return;
185 }
186
188 mbet->texture(),
190 /*sample count*/ 1,
192 /*color space*/ nullptr,
193 /*surface props*/ nullptr,
194 sk_gpu_test::ManagedBackendTexture::ReleaseProc,
195 mbet->releaseContext(nullptr, nullptr));
196
197 if (!surface) {
198 return;
199 }
200 SkCanvas* canvas = surface->getCanvas();
201 canvas->clear(SK_ColorGREEN);
202
203 // To trigger bug we must have a finish callback that abanonds the context before an asyc
204 // read callbck on the same command buffer. So we add the abandon callback first and flush
205 // then add the asyc to enforce this order.
206 GrFlushInfo flushInfo;
207 flushInfo.fFinishedProc = abandon_context;
208 flushInfo.fFinishedContext = dContext;
209
210 dContext->flush(flushInfo);
211
212 surface->asyncRescaleAndReadPixels(info,
213 SkIRect::MakeWH(8, 8),
217 nullptr);
218
219 surface.reset();
220
221 dContext->flushAndSubmit(GrSyncCpu::kYes);
222}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
reporter
Definition: FontMgrTest.cpp:39
int count
Definition: FontMgrTest.cpp:50
static void async_callback(void *c, std::unique_ptr< const SkImage::AsyncReadResult > result)
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(FlushFinishedProcTest, reporter, ctxInfo, CtsEnforcement::kApiLevel_T)
static void abandon_context(void *context)
static void testing_finished_proc(void *ctx)
static void busy_wait_for_callback(int *count, int expectedValue, GrDirectContext *dContext, skiatest::Reporter *reporter)
@ kTopLeft_GrSurfaceOrigin
Definition: GrTypes.h:148
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition: SkAlphaType.h:29
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition: SkColorType.h:24
constexpr SkColor SK_ColorBLUE
Definition: SkColor.h:135
constexpr SkColor SK_ColorRED
Definition: SkColor.h:126
constexpr SkColor SK_ColorGREEN
Definition: SkColor.h:131
#define REPORTER_ASSERT(r, cond,...)
Definition: Test.h:286
#define ERRORF(r,...)
Definition: Test.h:293
void checkAsyncWorkCompletion()
void clear(SkColor color)
Definition: SkCanvas.h:1199
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
Definition: SkCanvas.h:1528
static const char * begin(const StringSlice &s)
Definition: editor.cpp:252
VkSurfaceKHR surface
Definition: main.cc:49
glong glong end
GAsyncResult * result
sk_sp< const SkImage > image
Definition: SkRecords.h:269
SK_API sk_sp< SkSurface > WrapBackendTexture(GrRecordingContext *context, const GrBackendTexture &backendTexture, GrSurfaceOrigin origin, int sampleCnt, SkColorType colorType, sk_sp< SkColorSpace > colorSpace, const SkSurfaceProps *surfaceProps, TextureReleaseProc textureReleaseProc=nullptr, ReleaseContext releaseContext=nullptr)
SK_API sk_sp< SkSurface > RenderTarget(GrRecordingContext *context, skgpu::Budgeted budgeted, const SkImageInfo &imageInfo, int sampleCount, GrSurfaceOrigin surfaceOrigin, const SkSurfaceProps *surfaceProps, bool shouldCreateWithMips=false, bool isProtected=false)
GrGpuFinishedContext fFinishedContext
Definition: GrTypes.h:220
GrGpuFinishedProc fFinishedProc
Definition: GrTypes.h:219
static constexpr SkIRect MakeWH(int32_t w, int32_t h)
Definition: SkRect.h:56
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)