blob: 43aea5afa39d8ed6cacc10c666f8150c2821a80e [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
8#include "SkTypes.h"
9
Robert Phillipsf35fd8d2018-01-22 10:48:15 -050010#include "GrContextPriv.h"
Greg Daniela5cb7812017-06-16 09:45:32 -040011#include "GrContextFactory.h"
Greg Daniela5cb7812017-06-16 09:45:32 -040012#include "Test.h"
13
14#include "GrBackendSemaphore.h"
15#include "GrBackendSurface.h"
16#include "SkCanvas.h"
17#include "SkSurface.h"
18
Greg Danieldba7e7c2017-07-20 15:47:30 -040019#include "gl/GrGLGpu.h"
20#include "gl/GrGLUtil.h"
21
Greg Daniela5cb7812017-06-16 09:45:32 -040022#ifdef SK_VULKAN
Greg Danieldba7e7c2017-07-20 15:47:30 -040023#include "vk/GrVkGpu.h"
Greg Daniela5cb7812017-06-16 09:45:32 -040024#include "vk/GrVkTypes.h"
Greg Danieldba7e7c2017-07-20 15:47:30 -040025#include "vk/GrVkUtil.h"
26
27#ifdef VK_USE_PLATFORM_WIN32_KHR
28// windows wants to define this as CreateSemaphoreA or CreateSemaphoreW
Greg Daniel8761e0c2017-07-20 16:36:01 -040029#undef CreateSemaphore
30#endif
Greg Daniela5cb7812017-06-16 09:45:32 -040031#endif
32
33static const int MAIN_W = 8, MAIN_H = 16;
34static const int CHILD_W = 16, CHILD_H = 16;
35
36void check_pixels(skiatest::Reporter* reporter, const SkBitmap& bitmap) {
37 const uint32_t* canvasPixels = static_cast<const uint32_t*>(bitmap.getPixels());
38
39 bool failureFound = false;
40 SkPMColor expectedPixel;
41 for (int cy = 0; cy < CHILD_H && !failureFound; ++cy) {
42 for (int cx = 0; cx < CHILD_W && !failureFound; ++cx) {
43 SkPMColor canvasPixel = canvasPixels[cy * CHILD_W + cx];
44 if (cy < CHILD_H / 2) {
45 if (cx < CHILD_W / 2) {
46 expectedPixel = 0xFF0000FF; // Red
47 } else {
48 expectedPixel = 0xFFFF0000; // Blue
49 }
50 } else {
51 expectedPixel = 0xFF00FF00; // Green
52 }
53 if (expectedPixel != canvasPixel) {
54 failureFound = true;
55 ERRORF(reporter, "Wrong color at %d, %d. Got 0x%08x when we expected 0x%08x",
56 cx, cy, canvasPixel, expectedPixel);
57 }
58 }
59 }
60}
61
62void draw_child(skiatest::Reporter* reporter,
63 const sk_gpu_test::ContextInfo& childInfo,
Robert Phillipsba375a82018-04-11 10:08:06 -040064 const GrBackendTexture& backendTexture,
Greg Daniela5cb7812017-06-16 09:45:32 -040065 const GrBackendSemaphore& semaphore) {
Greg Daniela5cb7812017-06-16 09:45:32 -040066
67 childInfo.testContext()->makeCurrent();
68
69 const SkImageInfo childII = SkImageInfo::Make(CHILD_W, CHILD_H, kRGBA_8888_SkColorType,
70 kPremul_SkAlphaType);
71
72 GrContext* childCtx = childInfo.grContext();
73 sk_sp<SkSurface> childSurface(SkSurface::MakeRenderTarget(childCtx, SkBudgeted::kNo,
74 childII, 0, kTopLeft_GrSurfaceOrigin,
75 nullptr));
76
77 sk_sp<SkImage> childImage = SkImage::MakeFromTexture(childCtx,
78 backendTexture,
79 kTopLeft_GrSurfaceOrigin,
Greg Danielf5d87582017-12-18 14:48:15 -050080 kRGBA_8888_SkColorType,
Greg Daniela5cb7812017-06-16 09:45:32 -040081 kPremul_SkAlphaType,
Greg Danielf5d87582017-12-18 14:48:15 -050082 nullptr,
83 nullptr,
Greg Daniela5cb7812017-06-16 09:45:32 -040084 nullptr);
85
86 SkCanvas* childCanvas = childSurface->getCanvas();
87 childCanvas->clear(SK_ColorRED);
88
89 childSurface->wait(1, &semaphore);
90
91 childCanvas->drawImage(childImage, CHILD_W/2, 0);
92
93 SkPaint paint;
94 paint.setColor(SK_ColorGREEN);
95 SkIRect rect = SkIRect::MakeLTRB(0, CHILD_H/2, CHILD_W, CHILD_H);
96 childCanvas->drawIRect(rect, paint);
97
98 // read pixels
99 SkBitmap bitmap;
100 bitmap.allocPixels(childII);
Mike Reedf1942192017-07-21 14:24:29 -0400101 childSurface->readPixels(bitmap, 0, 0);
Greg Daniela5cb7812017-06-16 09:45:32 -0400102
103 check_pixels(reporter, bitmap);
104}
105
106void surface_semaphore_test(skiatest::Reporter* reporter,
107 const sk_gpu_test::ContextInfo& mainInfo,
108 const sk_gpu_test::ContextInfo& childInfo1,
Greg Daniel51316782017-08-02 15:10:09 +0000109 const sk_gpu_test::ContextInfo& childInfo2,
110 bool flushContext) {
Greg Daniela5cb7812017-06-16 09:45:32 -0400111 GrContext* mainCtx = mainInfo.grContext();
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400112 if (!mainCtx->contextPriv().caps()->fenceSyncSupport()) {
Greg Daniela5cb7812017-06-16 09:45:32 -0400113 return;
114 }
115
116 const SkImageInfo ii = SkImageInfo::Make(MAIN_W, MAIN_H, kRGBA_8888_SkColorType,
117 kPremul_SkAlphaType);
118
119 sk_sp<SkSurface> mainSurface(SkSurface::MakeRenderTarget(mainCtx, SkBudgeted::kNo,
120 ii, 0, kTopLeft_GrSurfaceOrigin,
121 nullptr));
122 SkCanvas* mainCanvas = mainSurface->getCanvas();
123 mainCanvas->clear(SK_ColorBLUE);
124
125 SkAutoTArray<GrBackendSemaphore> semaphores(2);
Greg Daniel8761e0c2017-07-20 16:36:01 -0400126#ifdef SK_VULKAN
127 if (kVulkan_GrBackend == mainInfo.backend()) {
128 // Initialize the secondary semaphore instead of having Ganesh create one internally
Robert Phillipsf35fd8d2018-01-22 10:48:15 -0500129 GrVkGpu* gpu = static_cast<GrVkGpu*>(mainCtx->contextPriv().getGpu());
Greg Daniel8761e0c2017-07-20 16:36:01 -0400130 const GrVkInterface* interface = gpu->vkInterface();
131 VkDevice device = gpu->device();
132
133 VkSemaphore vkSem;
134
135 VkSemaphoreCreateInfo createInfo;
136 createInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
137 createInfo.pNext = nullptr;
138 createInfo.flags = 0;
139 GR_VK_CALL_ERRCHECK(interface, CreateSemaphore(device, &createInfo, nullptr, &vkSem));
140
141 semaphores[1].initVulkan(vkSem);
142 }
143#endif
Greg Daniela5cb7812017-06-16 09:45:32 -0400144
Greg Daniel51316782017-08-02 15:10:09 +0000145 if (flushContext) {
146 mainCtx->flushAndSignalSemaphores(2, semaphores.get());
147 } else {
148 mainSurface->flushAndSignalSemaphores(2, semaphores.get());
149 }
Greg Daniela5cb7812017-06-16 09:45:32 -0400150
151 sk_sp<SkImage> mainImage = mainSurface->makeImageSnapshot();
Robert Phillipsba375a82018-04-11 10:08:06 -0400152 GrBackendTexture backendTexture = mainImage->getBackendTexture(false);
Greg Daniela5cb7812017-06-16 09:45:32 -0400153
Robert Phillipsba375a82018-04-11 10:08:06 -0400154 draw_child(reporter, childInfo1, backendTexture, semaphores[0]);
Greg Daniela5cb7812017-06-16 09:45:32 -0400155
156#ifdef SK_VULKAN
157 if (kVulkan_GrBackend == mainInfo.backend()) {
158 // In Vulkan we need to make sure we are sending the correct VkImageLayout in with the
159 // backendImage. After the first child draw the layout gets changed to SHADER_READ, so
160 // we just manually set that here.
Robert Phillipsba375a82018-04-11 10:08:06 -0400161 GrVkImageInfo vkInfo;
162 SkAssertResult(backendTexture.getVkImageInfo(&vkInfo));
163 vkInfo.updateImageLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
Greg Daniela5cb7812017-06-16 09:45:32 -0400164 }
165#endif
166
Robert Phillipsba375a82018-04-11 10:08:06 -0400167 draw_child(reporter, childInfo2, backendTexture, semaphores[1]);
Greg Daniela5cb7812017-06-16 09:45:32 -0400168}
169
Brian Salomondcfca432017-11-15 15:48:03 -0500170DEF_GPUTEST(SurfaceSemaphores, reporter, options) {
Greg Daniela5cb7812017-06-16 09:45:32 -0400171#if defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_MAC)
172 static constexpr auto kNativeGLType = sk_gpu_test::GrContextFactory::kGL_ContextType;
173#else
174 static constexpr auto kNativeGLType = sk_gpu_test::GrContextFactory::kGLES_ContextType;
175#endif
176
177 for (int typeInt = 0; typeInt < sk_gpu_test::GrContextFactory::kContextTypeCnt; ++typeInt) {
Greg Daniel51316782017-08-02 15:10:09 +0000178 for (auto flushContext : { false, true }) {
179 sk_gpu_test::GrContextFactory::ContextType contextType =
180 (sk_gpu_test::GrContextFactory::ContextType) typeInt;
181 // Use "native" instead of explicitly trying OpenGL and OpenGL ES. Do not use GLES on
182 // desktop since tests do not account for not fixing http://skbug.com/2809
183 if (contextType == sk_gpu_test::GrContextFactory::kGL_ContextType ||
184 contextType == sk_gpu_test::GrContextFactory::kGLES_ContextType) {
185 if (contextType != kNativeGLType) {
186 continue;
187 }
188 }
Brian Salomondcfca432017-11-15 15:48:03 -0500189 sk_gpu_test::GrContextFactory factory(options);
190 sk_gpu_test::ContextInfo ctxInfo = factory.getContextInfo(
Greg Daniel51316782017-08-02 15:10:09 +0000191 contextType, sk_gpu_test::GrContextFactory::ContextOverrides::kDisableNVPR);
192 if (!sk_gpu_test::GrContextFactory::IsRenderingContext(contextType)) {
Greg Daniela5cb7812017-06-16 09:45:32 -0400193 continue;
194 }
Greg Daniel51316782017-08-02 15:10:09 +0000195 skiatest::ReporterContext ctx(
196 reporter, SkString(sk_gpu_test::GrContextFactory::ContextTypeName(contextType)));
197 if (ctxInfo.grContext()) {
Brian Salomondcfca432017-11-15 15:48:03 -0500198 sk_gpu_test::ContextInfo child1 =
199 factory.getSharedContextInfo(ctxInfo.grContext(), 0);
200 sk_gpu_test::ContextInfo child2 =
201 factory.getSharedContextInfo(ctxInfo.grContext(), 1);
Greg Daniel51316782017-08-02 15:10:09 +0000202 if (!child1.grContext() || !child2.grContext()) {
203 continue;
204 }
Yuqian Licc8eb602017-08-01 17:43:30 +0000205
Greg Daniel51316782017-08-02 15:10:09 +0000206 surface_semaphore_test(reporter, ctxInfo, child1, child2, flushContext);
207 }
Greg Daniela5cb7812017-06-16 09:45:32 -0400208 }
209 }
210}
211
Greg Danieldba7e7c2017-07-20 15:47:30 -0400212DEF_GPUTEST_FOR_RENDERING_CONTEXTS(EmptySurfaceSemaphoreTest, reporter, ctxInfo) {
213 GrContext* ctx = ctxInfo.grContext();
Brian Salomonc7fe0f72018-05-11 10:14:21 -0400214 if (!ctx->contextPriv().caps()->fenceSyncSupport()) {
Greg Danieldba7e7c2017-07-20 15:47:30 -0400215 return;
216 }
217
218 const SkImageInfo ii = SkImageInfo::Make(MAIN_W, MAIN_H, kRGBA_8888_SkColorType,
219 kPremul_SkAlphaType);
220
221 sk_sp<SkSurface> mainSurface(SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo,
222 ii, 0, kTopLeft_GrSurfaceOrigin,
223 nullptr));
224
225 // Flush surface once without semaphores to make sure there is no peneding IO for it.
226 mainSurface->flush();
227
228 GrBackendSemaphore semaphore;
Greg Daniel51316782017-08-02 15:10:09 +0000229 GrSemaphoresSubmitted submitted = mainSurface->flushAndSignalSemaphores(1, &semaphore);
230 REPORTER_ASSERT(reporter, GrSemaphoresSubmitted::kYes == submitted);
Greg Danieldba7e7c2017-07-20 15:47:30 -0400231
232 if (kOpenGL_GrBackend == ctxInfo.backend()) {
Robert Phillipsf35fd8d2018-01-22 10:48:15 -0500233 GrGLGpu* gpu = static_cast<GrGLGpu*>(ctx->contextPriv().getGpu());
Greg Danieldba7e7c2017-07-20 15:47:30 -0400234 const GrGLInterface* interface = gpu->glInterface();
235 GrGLsync sync = semaphore.glSync();
236 REPORTER_ASSERT(reporter, sync);
237 bool result;
238 GR_GL_CALL_RET(interface, result, IsSync(sync));
239 REPORTER_ASSERT(reporter, result);
240 }
241
242#ifdef SK_VULKAN
243 if (kVulkan_GrBackend == ctxInfo.backend()) {
Robert Phillipsf35fd8d2018-01-22 10:48:15 -0500244 GrVkGpu* gpu = static_cast<GrVkGpu*>(ctx->contextPriv().getGpu());
Greg Danieldba7e7c2017-07-20 15:47:30 -0400245 const GrVkInterface* interface = gpu->vkInterface();
246 VkDevice device = gpu->device();
247 VkQueue queue = gpu->queue();
248 VkCommandPool cmdPool = gpu->cmdPool();
249 VkCommandBuffer cmdBuffer;
250
251 // Create Command Buffer
252 const VkCommandBufferAllocateInfo cmdInfo = {
253 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType
254 nullptr, // pNext
255 cmdPool, // commandPool
256 VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level
257 1 // bufferCount
258 };
259
260 VkResult err = GR_VK_CALL(interface, AllocateCommandBuffers(device, &cmdInfo, &cmdBuffer));
261 if (err) {
262 return;
263 }
264
265 VkCommandBufferBeginInfo cmdBufferBeginInfo;
266 memset(&cmdBufferBeginInfo, 0, sizeof(VkCommandBufferBeginInfo));
267 cmdBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
268 cmdBufferBeginInfo.pNext = nullptr;
269 cmdBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
270 cmdBufferBeginInfo.pInheritanceInfo = nullptr;
271
272 GR_VK_CALL_ERRCHECK(interface, BeginCommandBuffer(cmdBuffer, &cmdBufferBeginInfo));
273 GR_VK_CALL_ERRCHECK(interface, EndCommandBuffer(cmdBuffer));
274
275 VkFenceCreateInfo fenceInfo;
276 VkFence fence;
277
278 memset(&fenceInfo, 0, sizeof(VkFenceCreateInfo));
279 fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
280 err = GR_VK_CALL(interface, CreateFence(device, &fenceInfo, nullptr, &fence));
281 SkASSERT(!err);
282
283 VkPipelineStageFlags waitStages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
284 VkSubmitInfo submitInfo;
285 memset(&submitInfo, 0, sizeof(VkSubmitInfo));
286 submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
287 submitInfo.pNext = nullptr;
288 submitInfo.waitSemaphoreCount = 1;
289 VkSemaphore vkSem = semaphore.vkSemaphore();
290 submitInfo.pWaitSemaphores = &vkSem;
291 submitInfo.pWaitDstStageMask = &waitStages;
292 submitInfo.commandBufferCount = 1;
293 submitInfo.pCommandBuffers = &cmdBuffer;
294 submitInfo.signalSemaphoreCount = 0;
295 submitInfo.pSignalSemaphores = nullptr;
296 GR_VK_CALL_ERRCHECK(interface, QueueSubmit(queue, 1, &submitInfo, fence));
297
298 err = GR_VK_CALL(interface, WaitForFences(device, 1, &fence, true, 3000000000));
299
300 REPORTER_ASSERT(reporter, err != VK_TIMEOUT);
301
302 GR_VK_CALL(interface, DestroyFence(device, fence, nullptr));
303 GR_VK_CALL(interface, DestroySemaphore(device, vkSem, nullptr));
304 // If the above test fails the wait semaphore will never be signaled which can cause the
305 // device to hang when tearing down (even if just tearing down GL). So we Fail here to
306 // kill things.
307 if (err == VK_TIMEOUT) {
Ben Wagnerb4aab9a2017-08-16 10:53:04 -0400308 SK_ABORT("Waiting on semaphore indefinitely");
Greg Danieldba7e7c2017-07-20 15:47:30 -0400309 }
310 }
311#endif
312}