blob: 996b241ea6a726e324072a1754fe6022c20630c6 [file] [log] [blame]
Greg Daniela5cb7812017-06-16 09:45:32 -04001/*
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
Mike Reedac9f0c92020-12-23 10:11:33 -05008#include "include/core/SkBitmap.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -05009#include "include/core/SkCanvas.h"
10#include "include/core/SkSurface.h"
11#include "include/gpu/GrBackendSemaphore.h"
12#include "include/gpu/GrBackendSurface.h"
Robert Phillips6d344c32020-07-06 10:56:46 -040013#include "include/gpu/GrDirectContext.h"
Robert Phillipse19babf2020-04-06 13:57:30 -040014#include "src/gpu/GrCaps.h"
Adlai Hollera0693042020-10-14 11:23:11 -040015#include "src/gpu/GrDirectContextPriv.h"
Robert Phillipse19babf2020-04-06 13:57:30 -040016#include "tests/Test.h"
17#include "tools/gpu/GrContextFactory.h"
Greg Daniela5cb7812017-06-16 09:45:32 -040018
John Rosascoa9b348f2019-11-08 13:18:15 -080019#ifdef SK_GL
Mike Kleinc0bd9f92019-04-23 12:05:21 -050020#include "src/gpu/gl/GrGLGpu.h"
21#include "src/gpu/gl/GrGLUtil.h"
John Rosascoa9b348f2019-11-08 13:18:15 -080022#endif
Greg Danieldba7e7c2017-07-20 15:47:30 -040023
Greg Daniela5cb7812017-06-16 09:45:32 -040024#ifdef SK_VULKAN
Mike Kleinc0bd9f92019-04-23 12:05:21 -050025#include "include/gpu/vk/GrVkTypes.h"
Robert Phillipse19babf2020-04-06 13:57:30 -040026#include "include/gpu/vk/GrVkVulkan.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050027#include "src/gpu/vk/GrVkCommandPool.h"
28#include "src/gpu/vk/GrVkGpu.h"
29#include "src/gpu/vk/GrVkUtil.h"
Greg Danieldba7e7c2017-07-20 15:47:30 -040030
31#ifdef VK_USE_PLATFORM_WIN32_KHR
32// windows wants to define this as CreateSemaphoreA or CreateSemaphoreW
Greg Daniel8761e0c2017-07-20 16:36:01 -040033#undef CreateSemaphore
34#endif
Greg Daniela5cb7812017-06-16 09:45:32 -040035#endif
36
37static const int MAIN_W = 8, MAIN_H = 16;
38static const int CHILD_W = 16, CHILD_H = 16;
39
40void check_pixels(skiatest::Reporter* reporter, const SkBitmap& bitmap) {
41 const uint32_t* canvasPixels = static_cast<const uint32_t*>(bitmap.getPixels());
42
43 bool failureFound = false;
44 SkPMColor expectedPixel;
45 for (int cy = 0; cy < CHILD_H && !failureFound; ++cy) {
46 for (int cx = 0; cx < CHILD_W && !failureFound; ++cx) {
47 SkPMColor canvasPixel = canvasPixels[cy * CHILD_W + cx];
48 if (cy < CHILD_H / 2) {
49 if (cx < CHILD_W / 2) {
50 expectedPixel = 0xFF0000FF; // Red
51 } else {
52 expectedPixel = 0xFFFF0000; // Blue
53 }
54 } else {
55 expectedPixel = 0xFF00FF00; // Green
56 }
57 if (expectedPixel != canvasPixel) {
58 failureFound = true;
59 ERRORF(reporter, "Wrong color at %d, %d. Got 0x%08x when we expected 0x%08x",
60 cx, cy, canvasPixel, expectedPixel);
61 }
62 }
63 }
64}
65
66void draw_child(skiatest::Reporter* reporter,
67 const sk_gpu_test::ContextInfo& childInfo,
Robert Phillipsba375a82018-04-11 10:08:06 -040068 const GrBackendTexture& backendTexture,
Greg Daniela5cb7812017-06-16 09:45:32 -040069 const GrBackendSemaphore& semaphore) {
Greg Daniela5cb7812017-06-16 09:45:32 -040070
71 childInfo.testContext()->makeCurrent();
72
73 const SkImageInfo childII = SkImageInfo::Make(CHILD_W, CHILD_H, kRGBA_8888_SkColorType,
74 kPremul_SkAlphaType);
75
Adlai Holler14dc7912020-08-11 15:48:49 +000076 auto childDContext = childInfo.directContext();
77 sk_sp<SkSurface> childSurface(SkSurface::MakeRenderTarget(childDContext, SkBudgeted::kNo,
Greg Daniela5cb7812017-06-16 09:45:32 -040078 childII, 0, kTopLeft_GrSurfaceOrigin,
79 nullptr));
80
Adlai Holler14dc7912020-08-11 15:48:49 +000081 sk_sp<SkImage> childImage = SkImage::MakeFromTexture(childDContext,
Greg Daniela5cb7812017-06-16 09:45:32 -040082 backendTexture,
83 kTopLeft_GrSurfaceOrigin,
Greg Danielf5d87582017-12-18 14:48:15 -050084 kRGBA_8888_SkColorType,
Greg Daniela5cb7812017-06-16 09:45:32 -040085 kPremul_SkAlphaType,
Greg Danielf5d87582017-12-18 14:48:15 -050086 nullptr,
87 nullptr,
Greg Daniela5cb7812017-06-16 09:45:32 -040088 nullptr);
89
90 SkCanvas* childCanvas = childSurface->getCanvas();
91 childCanvas->clear(SK_ColorRED);
92
93 childSurface->wait(1, &semaphore);
94
95 childCanvas->drawImage(childImage, CHILD_W/2, 0);
96
97 SkPaint paint;
98 paint.setColor(SK_ColorGREEN);
99 SkIRect rect = SkIRect::MakeLTRB(0, CHILD_H/2, CHILD_W, CHILD_H);
100 childCanvas->drawIRect(rect, paint);
101
102 // read pixels
103 SkBitmap bitmap;
104 bitmap.allocPixels(childII);
Mike Reedf1942192017-07-21 14:24:29 -0400105 childSurface->readPixels(bitmap, 0, 0);
Greg Daniela5cb7812017-06-16 09:45:32 -0400106
107 check_pixels(reporter, bitmap);
108}
109
Brian Salomonf9a1fdf2019-05-09 10:30:12 -0400110enum class FlushType { kSurface, kImage, kContext };
111
Greg Daniela5cb7812017-06-16 09:45:32 -0400112void surface_semaphore_test(skiatest::Reporter* reporter,
113 const sk_gpu_test::ContextInfo& mainInfo,
114 const sk_gpu_test::ContextInfo& childInfo1,
Greg Daniel51316782017-08-02 15:10:09 +0000115 const sk_gpu_test::ContextInfo& childInfo2,
Brian Salomonf9a1fdf2019-05-09 10:30:12 -0400116 FlushType flushType) {
Robert Phillips6d344c32020-07-06 10:56:46 -0400117 auto mainCtx = mainInfo.directContext();
Brian Salomon9ff5acb2019-05-08 09:04:47 -0400118 if (!mainCtx->priv().caps()->semaphoreSupport()) {
Greg Daniela5cb7812017-06-16 09:45:32 -0400119 return;
120 }
121
122 const SkImageInfo ii = SkImageInfo::Make(MAIN_W, MAIN_H, kRGBA_8888_SkColorType,
123 kPremul_SkAlphaType);
124
125 sk_sp<SkSurface> mainSurface(SkSurface::MakeRenderTarget(mainCtx, SkBudgeted::kNo,
126 ii, 0, kTopLeft_GrSurfaceOrigin,
127 nullptr));
128 SkCanvas* mainCanvas = mainSurface->getCanvas();
Brian Salomonf9a1fdf2019-05-09 10:30:12 -0400129 auto blueSurface = mainSurface->makeSurface(ii);
130 blueSurface->getCanvas()->clear(SK_ColorBLUE);
131 auto blueImage = blueSurface->makeImageSnapshot();
132 blueSurface.reset();
133 mainCanvas->drawImage(blueImage, 0, 0);
Greg Daniela5cb7812017-06-16 09:45:32 -0400134
135 SkAutoTArray<GrBackendSemaphore> semaphores(2);
Greg Daniel8761e0c2017-07-20 16:36:01 -0400136#ifdef SK_VULKAN
Greg Danielbdf12ad2018-10-12 09:31:11 -0400137 if (GrBackendApi::kVulkan == mainInfo.backend()) {
Greg Daniel8761e0c2017-07-20 16:36:01 -0400138 // Initialize the secondary semaphore instead of having Ganesh create one internally
Robert Phillips9da87e02019-02-04 13:26:26 -0500139 GrVkGpu* gpu = static_cast<GrVkGpu*>(mainCtx->priv().getGpu());
Greg Daniel8761e0c2017-07-20 16:36:01 -0400140 VkDevice device = gpu->device();
141
142 VkSemaphore vkSem;
143
144 VkSemaphoreCreateInfo createInfo;
145 createInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
146 createInfo.pNext = nullptr;
147 createInfo.flags = 0;
Greg Daniele643da62019-11-05 12:36:42 -0500148 GR_VK_CALL_ERRCHECK(gpu, CreateSemaphore(device, &createInfo, nullptr, &vkSem));
Greg Daniel8761e0c2017-07-20 16:36:01 -0400149
150 semaphores[1].initVulkan(vkSem);
151 }
152#endif
Greg Daniela5cb7812017-06-16 09:45:32 -0400153
Greg Daniele6bfb7d2019-04-17 15:26:11 -0400154 GrFlushInfo info;
155 info.fNumSemaphores = 2;
156 info.fSignalSemaphores = semaphores.get();
Brian Salomonf9a1fdf2019-05-09 10:30:12 -0400157 switch (flushType) {
158 case FlushType::kSurface:
159 mainSurface->flush(SkSurface::BackendSurfaceAccess::kNoAccess, info);
160 break;
161 case FlushType::kImage:
162 blueImage->flush(mainCtx, info);
163 break;
164 case FlushType::kContext:
165 mainCtx->flush(info);
166 break;
Greg Daniel51316782017-08-02 15:10:09 +0000167 }
Greg Daniel0a2464f2020-05-14 15:45:44 -0400168 mainCtx->submit();
Greg Daniela5cb7812017-06-16 09:45:32 -0400169
Brian Salomond63638b2021-03-05 14:00:07 -0500170 GrBackendTexture backendTexture = mainSurface->getBackendTexture(
171 SkSurface::BackendHandleAccess::kFlushRead_BackendHandleAccess);
Greg Daniela5cb7812017-06-16 09:45:32 -0400172
Robert Phillipsba375a82018-04-11 10:08:06 -0400173 draw_child(reporter, childInfo1, backendTexture, semaphores[0]);
Greg Daniela5cb7812017-06-16 09:45:32 -0400174
175#ifdef SK_VULKAN
Greg Danielbdf12ad2018-10-12 09:31:11 -0400176 if (GrBackendApi::kVulkan == mainInfo.backend()) {
Greg Daniela5cb7812017-06-16 09:45:32 -0400177 // In Vulkan we need to make sure we are sending the correct VkImageLayout in with the
178 // backendImage. After the first child draw the layout gets changed to SHADER_READ, so
179 // we just manually set that here.
Jim Van Verth6ec56882020-03-26 11:47:26 -0400180 backendTexture.setVkImageLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
Greg Daniela5cb7812017-06-16 09:45:32 -0400181 }
182#endif
183
Robert Phillipsba375a82018-04-11 10:08:06 -0400184 draw_child(reporter, childInfo2, backendTexture, semaphores[1]);
Greg Daniela5cb7812017-06-16 09:45:32 -0400185}
186
John Rosascoa9b348f2019-11-08 13:18:15 -0800187#ifdef SK_GL
Brian Salomondcfca432017-11-15 15:48:03 -0500188DEF_GPUTEST(SurfaceSemaphores, reporter, options) {
Greg Daniela5cb7812017-06-16 09:45:32 -0400189#if defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_MAC)
190 static constexpr auto kNativeGLType = sk_gpu_test::GrContextFactory::kGL_ContextType;
191#else
192 static constexpr auto kNativeGLType = sk_gpu_test::GrContextFactory::kGLES_ContextType;
193#endif
194
195 for (int typeInt = 0; typeInt < sk_gpu_test::GrContextFactory::kContextTypeCnt; ++typeInt) {
Brian Salomonf9a1fdf2019-05-09 10:30:12 -0400196 for (auto flushType : {FlushType::kSurface, FlushType::kImage, FlushType::kContext}) {
Greg Daniel51316782017-08-02 15:10:09 +0000197 sk_gpu_test::GrContextFactory::ContextType contextType =
198 (sk_gpu_test::GrContextFactory::ContextType) typeInt;
199 // Use "native" instead of explicitly trying OpenGL and OpenGL ES. Do not use GLES on
200 // desktop since tests do not account for not fixing http://skbug.com/2809
201 if (contextType == sk_gpu_test::GrContextFactory::kGL_ContextType ||
202 contextType == sk_gpu_test::GrContextFactory::kGLES_ContextType) {
203 if (contextType != kNativeGLType) {
204 continue;
205 }
206 }
Brian Salomondcfca432017-11-15 15:48:03 -0500207 sk_gpu_test::GrContextFactory factory(options);
Chris Daltonb3c97452019-06-25 20:07:56 -0600208 sk_gpu_test::ContextInfo ctxInfo = factory.getContextInfo(contextType);
Greg Daniel51316782017-08-02 15:10:09 +0000209 if (!sk_gpu_test::GrContextFactory::IsRenderingContext(contextType)) {
Greg Daniela5cb7812017-06-16 09:45:32 -0400210 continue;
211 }
Greg Daniel51316782017-08-02 15:10:09 +0000212 skiatest::ReporterContext ctx(
213 reporter, SkString(sk_gpu_test::GrContextFactory::ContextTypeName(contextType)));
Robert Phillips6d344c32020-07-06 10:56:46 -0400214 if (ctxInfo.directContext()) {
Brian Salomondcfca432017-11-15 15:48:03 -0500215 sk_gpu_test::ContextInfo child1 =
Robert Phillips00f78de2020-07-01 16:09:43 -0400216 factory.getSharedContextInfo(ctxInfo.directContext(), 0);
Brian Salomondcfca432017-11-15 15:48:03 -0500217 sk_gpu_test::ContextInfo child2 =
Robert Phillips00f78de2020-07-01 16:09:43 -0400218 factory.getSharedContextInfo(ctxInfo.directContext(), 1);
Robert Phillips6d344c32020-07-06 10:56:46 -0400219 if (!child1.directContext() || !child2.directContext()) {
Greg Daniel51316782017-08-02 15:10:09 +0000220 continue;
221 }
Yuqian Licc8eb602017-08-01 17:43:30 +0000222
Brian Salomonf9a1fdf2019-05-09 10:30:12 -0400223 surface_semaphore_test(reporter, ctxInfo, child1, child2, flushType);
Greg Daniel51316782017-08-02 15:10:09 +0000224 }
Greg Daniela5cb7812017-06-16 09:45:32 -0400225 }
226 }
227}
John Rosascoa9b348f2019-11-08 13:18:15 -0800228#endif
Greg Daniela5cb7812017-06-16 09:45:32 -0400229
Greg Danieldba7e7c2017-07-20 15:47:30 -0400230DEF_GPUTEST_FOR_RENDERING_CONTEXTS(EmptySurfaceSemaphoreTest, reporter, ctxInfo) {
Robert Phillips6d344c32020-07-06 10:56:46 -0400231 auto ctx = ctxInfo.directContext();
Brian Salomon9ff5acb2019-05-08 09:04:47 -0400232 if (!ctx->priv().caps()->semaphoreSupport()) {
Greg Danieldba7e7c2017-07-20 15:47:30 -0400233 return;
234 }
235
236 const SkImageInfo ii = SkImageInfo::Make(MAIN_W, MAIN_H, kRGBA_8888_SkColorType,
237 kPremul_SkAlphaType);
238
239 sk_sp<SkSurface> mainSurface(SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo,
240 ii, 0, kTopLeft_GrSurfaceOrigin,
241 nullptr));
242
243 // Flush surface once without semaphores to make sure there is no peneding IO for it.
Greg Daniel0a2464f2020-05-14 15:45:44 -0400244 mainSurface->flushAndSubmit();
Greg Danieldba7e7c2017-07-20 15:47:30 -0400245
246 GrBackendSemaphore semaphore;
Greg Daniel49de1032020-05-19 18:06:26 -0400247 GrFlushInfo flushInfo;
248 flushInfo.fNumSemaphores = 1;
249 flushInfo.fSignalSemaphores = &semaphore;
Greg Daniel04283f32020-05-20 13:16:00 -0400250 GrSemaphoresSubmitted submitted =
251 mainSurface->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo);
Greg Daniel51316782017-08-02 15:10:09 +0000252 REPORTER_ASSERT(reporter, GrSemaphoresSubmitted::kYes == submitted);
Greg Daniel04283f32020-05-20 13:16:00 -0400253 ctx->submit();
Greg Danieldba7e7c2017-07-20 15:47:30 -0400254
John Rosascoa9b348f2019-11-08 13:18:15 -0800255#ifdef SK_GL
Greg Danielbdf12ad2018-10-12 09:31:11 -0400256 if (GrBackendApi::kOpenGL == ctxInfo.backend()) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500257 GrGLGpu* gpu = static_cast<GrGLGpu*>(ctx->priv().getGpu());
Greg Danieldba7e7c2017-07-20 15:47:30 -0400258 const GrGLInterface* interface = gpu->glInterface();
259 GrGLsync sync = semaphore.glSync();
260 REPORTER_ASSERT(reporter, sync);
261 bool result;
262 GR_GL_CALL_RET(interface, result, IsSync(sync));
263 REPORTER_ASSERT(reporter, result);
264 }
John Rosascoa9b348f2019-11-08 13:18:15 -0800265#endif
Greg Danieldba7e7c2017-07-20 15:47:30 -0400266
267#ifdef SK_VULKAN
Greg Danielbdf12ad2018-10-12 09:31:11 -0400268 if (GrBackendApi::kVulkan == ctxInfo.backend()) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500269 GrVkGpu* gpu = static_cast<GrVkGpu*>(ctx->priv().getGpu());
Greg Danieldba7e7c2017-07-20 15:47:30 -0400270 const GrVkInterface* interface = gpu->vkInterface();
271 VkDevice device = gpu->device();
272 VkQueue queue = gpu->queue();
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500273 GrVkCommandPool* cmdPool = gpu->cmdPool();
Greg Danieldba7e7c2017-07-20 15:47:30 -0400274 VkCommandBuffer cmdBuffer;
275
276 // Create Command Buffer
277 const VkCommandBufferAllocateInfo cmdInfo = {
278 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType
279 nullptr, // pNext
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500280 cmdPool->vkCommandPool(), // commandPool
Greg Danieldba7e7c2017-07-20 15:47:30 -0400281 VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level
282 1 // bufferCount
283 };
284
285 VkResult err = GR_VK_CALL(interface, AllocateCommandBuffers(device, &cmdInfo, &cmdBuffer));
286 if (err) {
287 return;
288 }
289
290 VkCommandBufferBeginInfo cmdBufferBeginInfo;
291 memset(&cmdBufferBeginInfo, 0, sizeof(VkCommandBufferBeginInfo));
292 cmdBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
293 cmdBufferBeginInfo.pNext = nullptr;
294 cmdBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
295 cmdBufferBeginInfo.pInheritanceInfo = nullptr;
296
Greg Daniele643da62019-11-05 12:36:42 -0500297 GR_VK_CALL_ERRCHECK(gpu, BeginCommandBuffer(cmdBuffer, &cmdBufferBeginInfo));
298 GR_VK_CALL_ERRCHECK(gpu, EndCommandBuffer(cmdBuffer));
Greg Danieldba7e7c2017-07-20 15:47:30 -0400299
300 VkFenceCreateInfo fenceInfo;
301 VkFence fence;
302
303 memset(&fenceInfo, 0, sizeof(VkFenceCreateInfo));
304 fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
305 err = GR_VK_CALL(interface, CreateFence(device, &fenceInfo, nullptr, &fence));
306 SkASSERT(!err);
307
308 VkPipelineStageFlags waitStages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
309 VkSubmitInfo submitInfo;
310 memset(&submitInfo, 0, sizeof(VkSubmitInfo));
311 submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
312 submitInfo.pNext = nullptr;
313 submitInfo.waitSemaphoreCount = 1;
314 VkSemaphore vkSem = semaphore.vkSemaphore();
315 submitInfo.pWaitSemaphores = &vkSem;
316 submitInfo.pWaitDstStageMask = &waitStages;
317 submitInfo.commandBufferCount = 1;
318 submitInfo.pCommandBuffers = &cmdBuffer;
319 submitInfo.signalSemaphoreCount = 0;
320 submitInfo.pSignalSemaphores = nullptr;
Greg Daniele643da62019-11-05 12:36:42 -0500321 GR_VK_CALL_ERRCHECK(gpu, QueueSubmit(queue, 1, &submitInfo, fence));
Greg Danieldba7e7c2017-07-20 15:47:30 -0400322
323 err = GR_VK_CALL(interface, WaitForFences(device, 1, &fence, true, 3000000000));
324
325 REPORTER_ASSERT(reporter, err != VK_TIMEOUT);
326
327 GR_VK_CALL(interface, DestroyFence(device, fence, nullptr));
328 GR_VK_CALL(interface, DestroySemaphore(device, vkSem, nullptr));
329 // If the above test fails the wait semaphore will never be signaled which can cause the
330 // device to hang when tearing down (even if just tearing down GL). So we Fail here to
331 // kill things.
332 if (err == VK_TIMEOUT) {
Ben Wagnerb4aab9a2017-08-16 10:53:04 -0400333 SK_ABORT("Waiting on semaphore indefinitely");
Greg Danieldba7e7c2017-07-20 15:47:30 -0400334 }
335 }
336#endif
337}