Flutter Engine
The Flutter Engine
SurfaceSemaphoreTest.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2017 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
17#include "include/core/SkRect.h"
26#include "include/gpu/GrTypes.h"
33#include "tests/Test.h"
36
37#include <cstring>
38#include <cstdint>
39#include <initializer_list>
40
41#ifdef SK_GL
47#endif
48
49#ifdef SK_VULKAN
55
56#include <vulkan/vulkan_core.h>
57
58namespace skgpu { struct VulkanInterface; }
59
60#ifdef VK_USE_PLATFORM_WIN32_KHR
61// windows wants to define this as CreateSemaphoreA or CreateSemaphoreW
62#undef CreateSemaphore
63#endif
64#endif
65
66using namespace skia_private;
67
68struct GrContextOptions;
69
70static const int MAIN_W = 8, MAIN_H = 16;
71static const int CHILD_W = 16, CHILD_H = 16;
72
74 const uint32_t* canvasPixels = static_cast<const uint32_t*>(bitmap.getPixels());
75
76 bool failureFound = false;
77 SkPMColor expectedPixel;
78 for (int cy = 0; cy < CHILD_H && !failureFound; ++cy) {
79 for (int cx = 0; cx < CHILD_W && !failureFound; ++cx) {
80 SkPMColor canvasPixel = canvasPixels[cy * CHILD_W + cx];
81 if (cy < CHILD_H / 2) {
82 if (cx < CHILD_W / 2) {
83 expectedPixel = 0xFF0000FF; // Red
84 } else {
85 expectedPixel = 0xFFFF0000; // Blue
86 }
87 } else {
88 expectedPixel = 0xFF00FF00; // Green
89 }
90 if (expectedPixel != canvasPixel) {
91 failureFound = true;
92 ERRORF(reporter, "Wrong color at %d, %d. Got 0x%08x when we expected 0x%08x",
93 cx, cy, canvasPixel, expectedPixel);
94 }
95 }
96 }
97}
98
100 const sk_gpu_test::ContextInfo& childInfo,
101 const GrBackendTexture& backendTexture,
102 const GrBackendSemaphore& semaphore) {
103
104 childInfo.testContext()->makeCurrent();
105
108
109 auto childDContext = childInfo.directContext();
111 childDContext, skgpu::Budgeted::kNo, childII, 0, kTopLeft_GrSurfaceOrigin, nullptr));
112
113 sk_sp<SkImage> childImage = SkImages::BorrowTextureFrom(childDContext,
114 backendTexture,
118 nullptr,
119 nullptr,
120 nullptr);
121
122 SkCanvas* childCanvas = childSurface->getCanvas();
123 childCanvas->clear(SK_ColorRED);
124
125 childSurface->wait(1, &semaphore);
126
127 childCanvas->drawImage(childImage, CHILD_W/2, 0);
128
130 paint.setColor(SK_ColorGREEN);
132 childCanvas->drawIRect(rect, paint);
133
134 // read pixels
136 bitmap.allocPixels(childII);
137 childSurface->readPixels(bitmap, 0, 0);
138
140}
141
143
145 const sk_gpu_test::ContextInfo& mainInfo,
146 const sk_gpu_test::ContextInfo& childInfo1,
147 const sk_gpu_test::ContextInfo& childInfo2,
148 FlushType flushType) {
149 auto mainCtx = mainInfo.directContext();
150 if (!mainCtx->priv().caps()->backendSemaphoreSupport()) {
151 return;
152 }
153
156
158 mainCtx, skgpu::Budgeted::kNo, ii, 0, kTopLeft_GrSurfaceOrigin, nullptr));
159 SkCanvas* mainCanvas = mainSurface->getCanvas();
160 auto blueSurface = mainSurface->makeSurface(ii);
161 blueSurface->getCanvas()->clear(SK_ColorBLUE);
162 auto blueImage = blueSurface->makeImageSnapshot();
163 blueSurface.reset();
164 mainCanvas->drawImage(blueImage, 0, 0);
165
166 AutoTArray<GrBackendSemaphore> semaphores(2);
167#ifdef SK_VULKAN
168 if (GrBackendApi::kVulkan == mainInfo.backend()) {
169 // Initialize the secondary semaphore instead of having Ganesh create one internally
170 GrVkGpu* gpu = static_cast<GrVkGpu*>(mainCtx->priv().getGpu());
171 VkDevice device = gpu->device();
172
173 VkSemaphore vkSem;
174
175 VkSemaphoreCreateInfo createInfo;
177 createInfo.pNext = nullptr;
178 createInfo.flags = 0;
179 GR_VK_CALL_ERRCHECK(gpu, CreateSemaphore(device, &createInfo, nullptr, &vkSem));
180
181 semaphores[1] = GrBackendSemaphores::MakeVk(vkSem);
182 }
183#endif
184
186 info.fNumSemaphores = 2;
187 info.fSignalSemaphores = semaphores.get();
188 switch (flushType) {
190 mainCtx->flush(mainSurface.get(), SkSurfaces::BackendSurfaceAccess::kNoAccess, info);
191 break;
193 mainCtx->flush(blueImage, info);
194 break;
196 mainCtx->flush(info);
197 break;
198 }
199 mainCtx->submit();
200
203
204 draw_child(reporter, childInfo1, backendTexture, semaphores[0]);
205
206#ifdef SK_VULKAN
207 if (GrBackendApi::kVulkan == mainInfo.backend()) {
208 // In Vulkan we need to make sure we are sending the correct VkImageLayout in with the
209 // backendImage. After the first child draw the layout gets changed to SHADER_READ, so
210 // we just manually set that here.
213 }
214#endif
215
216 draw_child(reporter, childInfo2, backendTexture, semaphores[1]);
217}
218
220#if defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_MAC)
221 static constexpr auto kNativeGLType = skgpu::ContextType::kGL;
222#else
223 static constexpr auto kNativeGLType = skgpu::ContextType::kGLES;
224#endif
225
226 for (int typeInt = 0; typeInt < skgpu::kContextTypeCount; ++typeInt) {
228 skgpu::ContextType contextType = static_cast<skgpu::ContextType>(typeInt);
229#ifdef SK_GL
230 // Use "native" instead of explicitly trying OpenGL and OpenGL ES. Do not use GLES on
231 // desktop since tests do not account for not fixing http://skbug.com/2809
232 if (contextType == skgpu::ContextType::kGL ||
233 contextType == skgpu::ContextType::kGLES) {
234 if (contextType != kNativeGLType) {
235 continue;
236 }
237 }
238#else
239 sk_ignore_unused_variable(kNativeGLType); // Do something to avoid unused variable
240#endif
242 sk_gpu_test::ContextInfo ctxInfo = factory.getContextInfo(contextType);
243 if (!skgpu::IsRenderingContext(contextType)) {
244 continue;
245 }
247 if (ctxInfo.directContext()) {
249 factory.getSharedContextInfo(ctxInfo.directContext(), 0);
251 factory.getSharedContextInfo(ctxInfo.directContext(), 1);
252 if (!child1.directContext() || !child2.directContext()) {
253 continue;
254 }
255
256 surface_semaphore_test(reporter, ctxInfo, child1, child2, flushType);
257 }
258 }
259 }
260}
261
263 reporter,
264 ctxInfo,
266 auto ctx = ctxInfo.directContext();
267 if (!ctx->priv().caps()->backendSemaphoreSupport()) {
268 // For example, the GL backend does not support these.
269 return;
270 }
271
274
276 ctx, skgpu::Budgeted::kNo, ii, 0, kTopLeft_GrSurfaceOrigin, nullptr));
277
278 // Flush surface once without semaphores to make sure there is no pending IO for it.
279 ctx->flushAndSubmit(mainSurface.get(), GrSyncCpu::kNo);
280
281 GrBackendSemaphore semaphore;
282 GrFlushInfo flushInfo;
283 flushInfo.fNumSemaphores = 1;
284 flushInfo.fSignalSemaphores = &semaphore;
285 GrSemaphoresSubmitted submitted =
286 ctx->flush(mainSurface.get(), SkSurfaces::BackendSurfaceAccess::kNoAccess, flushInfo);
288 ctx->submit();
289
290#ifdef SK_VULKAN
291 if (GrBackendApi::kVulkan == ctxInfo.backend()) {
292 GrVkGpu* gpu = static_cast<GrVkGpu*>(ctx->priv().getGpu());
293 const skgpu::VulkanInterface* interface = gpu->vkInterface();
294 VkDevice device = gpu->device();
295 VkQueue queue = gpu->queue();
296 GrVkCommandPool* cmdPool = gpu->cmdPool();
297 VkCommandBuffer cmdBuffer;
298
299 // Create Command Buffer
300 const VkCommandBufferAllocateInfo cmdInfo = {
302 nullptr, // pNext
303 cmdPool->vkCommandPool(), // commandPool
305 1 // bufferCount
306 };
307
308 VkResult err = GR_VK_CALL(interface, AllocateCommandBuffers(device, &cmdInfo, &cmdBuffer));
309 if (err) {
310 return;
311 }
312
313 VkCommandBufferBeginInfo cmdBufferBeginInfo;
314 memset(&cmdBufferBeginInfo, 0, sizeof(VkCommandBufferBeginInfo));
316 cmdBufferBeginInfo.pNext = nullptr;
318 cmdBufferBeginInfo.pInheritanceInfo = nullptr;
319
320 GR_VK_CALL_ERRCHECK(gpu, BeginCommandBuffer(cmdBuffer, &cmdBufferBeginInfo));
321 GR_VK_CALL_ERRCHECK(gpu, EndCommandBuffer(cmdBuffer));
322
323 VkFenceCreateInfo fenceInfo;
324 VkFence fence;
325
326 memset(&fenceInfo, 0, sizeof(VkFenceCreateInfo));
328 err = GR_VK_CALL(interface, CreateFence(device, &fenceInfo, nullptr, &fence));
329 SkASSERT(!err);
330
332 VkSubmitInfo submitInfo;
333 memset(&submitInfo, 0, sizeof(VkSubmitInfo));
335 submitInfo.pNext = nullptr;
336 submitInfo.waitSemaphoreCount = 1;
337 VkSemaphore vkSem = GrBackendSemaphores::GetVkSemaphore(semaphore);
338 submitInfo.pWaitSemaphores = &vkSem;
339 submitInfo.pWaitDstStageMask = &waitStages;
340 submitInfo.commandBufferCount = 1;
341 submitInfo.pCommandBuffers = &cmdBuffer;
342 submitInfo.signalSemaphoreCount = 0;
343 submitInfo.pSignalSemaphores = nullptr;
344 GR_VK_CALL_ERRCHECK(gpu, QueueSubmit(queue, 1, &submitInfo, fence));
345
346 err = GR_VK_CALL(interface, WaitForFences(device, 1, &fence, true, 3000000000));
347
349
350 GR_VK_CALL(interface, DestroyFence(device, fence, nullptr));
351 GR_VK_CALL(interface, DestroySemaphore(device, vkSem, nullptr));
352 // If the above test fails the wait semaphore will never be signaled which can cause the
353 // device to hang when tearing down (even if just tearing down GL). So we Fail here to
354 // kill things.
355 if (err == VK_TIMEOUT) {
356 SK_ABORT("Waiting on semaphore indefinitely");
357 }
358 }
359#endif
360}
const char * options
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
reporter
Definition: FontMgrTest.cpp:39
@ kTopLeft_GrSurfaceOrigin
Definition: GrTypes.h:148
GrSemaphoresSubmitted
Definition: GrTypes.h:229
#define GR_VK_CALL(IFACE, X)
Definition: GrVkUtil.h:24
#define GR_VK_CALL_ERRCHECK(GPU, X)
Definition: GrVkUtil.h:50
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition: SkAlphaType.h:29
#define SK_ABORT(message,...)
Definition: SkAssert.h:70
#define SkASSERT(cond)
Definition: SkAssert.h:116
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition: SkColorType.h:24
uint32_t SkPMColor
Definition: SkColor.h:205
constexpr SkColor SK_ColorBLUE
Definition: SkColor.h:135
constexpr SkColor SK_ColorRED
Definition: SkColor.h:126
constexpr SkColor SK_ColorGREEN
Definition: SkColor.h:131
void sk_ignore_unused_variable(const T &)
Definition: SkTemplates.h:37
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(EmptySurfaceSemaphoreTest, reporter, ctxInfo, CtsEnforcement::kApiLevel_T)
void check_pixels(skiatest::Reporter *reporter, const SkBitmap &bitmap)
void surface_semaphore_test(skiatest::Reporter *reporter, const sk_gpu_test::ContextInfo &mainInfo, const sk_gpu_test::ContextInfo &childInfo1, const sk_gpu_test::ContextInfo &childInfo2, FlushType flushType)
DEF_GANESH_TEST(SurfaceSemaphores, reporter, options, CtsEnforcement::kApiLevel_T)
void draw_child(skiatest::Reporter *reporter, const sk_gpu_test::ContextInfo &childInfo, const GrBackendTexture &backendTexture, const GrBackendSemaphore &semaphore)
static const int CHILD_W
static const int CHILD_H
static const int MAIN_H
static const int MAIN_W
#define REPORTER_ASSERT(r, cond,...)
Definition: Test.h:286
#define ERRORF(r,...)
Definition: Test.h:293
VkCommandPool vkCommandPool() const
VkDevice device() const
Definition: GrVkGpu.h:71
GrVkCommandPool * cmdPool() const
Definition: GrVkGpu.h:74
VkQueue queue() const
Definition: GrVkGpu.h:72
void drawIRect(const SkIRect &rect, const SkPaint &paint)
Definition: SkCanvas.h:1358
void clear(SkColor color)
Definition: SkCanvas.h:1199
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
Definition: SkCanvas.h:1528
SkCanvas * getCanvas()
Definition: SkSurface.cpp:82
sk_sp< SkSurface > makeSurface(const SkImageInfo &imageInfo)
Definition: SkSurface.cpp:108
@ kFlushRead
back-end object is readable
bool wait(int numSemaphores, const GrBackendSemaphore *waitSemaphores, bool deleteSemaphoresAfterWait=true)
Definition: SkSurface.cpp:234
bool readPixels(const SkPixmap &dst, int srcX, int srcY)
Definition: SkSurface.cpp:125
GrBackendApi backend() const
GrDirectContext * directContext() const
TestContext * testContext() const
ContextInfo getContextInfo(ContextType type, ContextOverrides=ContextOverrides::kNone)
ContextInfo getSharedContextInfo(GrDirectContext *shareContext, uint32_t shareIndex=0)
T * get() const
Definition: SkRefCnt.h:303
const Paint & paint
Definition: color_source.cc:38
VkDevice device
Definition: main.cc:53
VkQueue queue
Definition: main.cc:55
SK_API GrBackendSemaphore MakeVk(VkSemaphore semaphore)
SK_API VkSemaphore GetVkSemaphore(const GrBackendSemaphore &)
SK_API void SetVkImageLayout(GrBackendTexture *, VkImageLayout)
SK_API sk_sp< SkImage > BorrowTextureFrom(GrRecordingContext *context, const GrBackendTexture &backendTexture, GrSurfaceOrigin origin, SkColorType colorType, SkAlphaType alphaType, sk_sp< SkColorSpace > colorSpace, TextureReleaseProc textureReleaseProc=nullptr, ReleaseContext releaseContext=nullptr)
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
@ kNoAccess
back-end surface will not be used by client
SK_API GrBackendTexture GetBackendTexture(SkSurface *, BackendHandleAccess)
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)
Definition: bitmap.py:1
Definition: GpuTools.h:21
static const int kContextTypeCount
Definition: ContextType.h:42
ContextType
Definition: ContextType.h:19
@ kGLES
OpenGL context.
const char * ContextTypeName(skgpu::ContextType type)
Definition: ContextType.cpp:13
bool IsRenderingContext(skgpu::ContextType type)
Definition: ContextType.cpp:88
static constexpr auto kNativeGLType
GrBackendSemaphore * fSignalSemaphores
Definition: GrTypes.h:218
size_t fNumSemaphores
Definition: GrTypes.h:217
Definition: SkRect.h:32
static constexpr SkIRect MakeLTRB(int32_t l, int32_t t, int32_t r, int32_t b)
Definition: SkRect.h:91
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
const VkCommandBufferInheritanceInfo * pInheritanceInfo
Definition: vulkan_core.h:3894
VkStructureType sType
Definition: vulkan_core.h:3891
VkCommandBufferUsageFlags flags
Definition: vulkan_core.h:3893
VkStructureType sType
Definition: vulkan_core.h:3386
VkStructureType sType
Definition: vulkan_core.h:3392
VkSemaphoreCreateFlags flags
Definition: vulkan_core.h:3394
uint32_t waitSemaphoreCount
Definition: vulkan_core.h:3285
const VkPipelineStageFlags * pWaitDstStageMask
Definition: vulkan_core.h:3287
uint32_t commandBufferCount
Definition: vulkan_core.h:3288
const VkSemaphore * pWaitSemaphores
Definition: vulkan_core.h:3286
uint32_t signalSemaphoreCount
Definition: vulkan_core.h:3290
const VkCommandBuffer * pCommandBuffers
Definition: vulkan_core.h:3289
const void * pNext
Definition: vulkan_core.h:3284
const VkSemaphore * pSignalSemaphores
Definition: vulkan_core.h:3291
VkStructureType sType
Definition: vulkan_core.h:3283
VkFlags VkPipelineStageFlags
Definition: vulkan_core.h:2470
@ VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
Definition: vulkan_core.h:1336
@ VK_COMMAND_BUFFER_LEVEL_PRIMARY
Definition: vulkan_core.h:2178
@ VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
Definition: vulkan_core.h:2830
VkResult
Definition: vulkan_core.h:140
@ VK_TIMEOUT
Definition: vulkan_core.h:143
@ VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
Definition: vulkan_core.h:2451
@ VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO
Definition: vulkan_core.h:211
@ VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO
Definition: vulkan_core.h:242
@ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO
Definition: vulkan_core.h:244
@ VK_STRUCTURE_TYPE_FENCE_CREATE_INFO
Definition: vulkan_core.h:210
@ VK_STRUCTURE_TYPE_SUBMIT_INFO
Definition: vulkan_core.h:206