blob: bc2d53ce366da6a050e3311e60e9ca8c5f61ced5 [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
Greg Daniel54bfb182018-11-20 17:12:36 -05008#include "vk/GrVkVulkan.h"
Greg Daniela5cb7812017-06-16 09:45:32 -04009
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
Ethan Nicholas8e265a72018-12-12 16:22:40 -050023#include "vk/GrVkCommandPool.h"
Greg Danieldba7e7c2017-07-20 15:47:30 -040024#include "vk/GrVkGpu.h"
Greg Daniela5cb7812017-06-16 09:45:32 -040025#include "vk/GrVkTypes.h"
Greg Danieldba7e7c2017-07-20 15:47:30 -040026#include "vk/GrVkUtil.h"
27
28#ifdef VK_USE_PLATFORM_WIN32_KHR
29// windows wants to define this as CreateSemaphoreA or CreateSemaphoreW
Greg Daniel8761e0c2017-07-20 16:36:01 -040030#undef CreateSemaphore
31#endif
Greg Daniela5cb7812017-06-16 09:45:32 -040032#endif
33
34static const int MAIN_W = 8, MAIN_H = 16;
35static const int CHILD_W = 16, CHILD_H = 16;
36
37void check_pixels(skiatest::Reporter* reporter, const SkBitmap& bitmap) {
38 const uint32_t* canvasPixels = static_cast<const uint32_t*>(bitmap.getPixels());
39
40 bool failureFound = false;
41 SkPMColor expectedPixel;
42 for (int cy = 0; cy < CHILD_H && !failureFound; ++cy) {
43 for (int cx = 0; cx < CHILD_W && !failureFound; ++cx) {
44 SkPMColor canvasPixel = canvasPixels[cy * CHILD_W + cx];
45 if (cy < CHILD_H / 2) {
46 if (cx < CHILD_W / 2) {
47 expectedPixel = 0xFF0000FF; // Red
48 } else {
49 expectedPixel = 0xFFFF0000; // Blue
50 }
51 } else {
52 expectedPixel = 0xFF00FF00; // Green
53 }
54 if (expectedPixel != canvasPixel) {
55 failureFound = true;
56 ERRORF(reporter, "Wrong color at %d, %d. Got 0x%08x when we expected 0x%08x",
57 cx, cy, canvasPixel, expectedPixel);
58 }
59 }
60 }
61}
62
63void draw_child(skiatest::Reporter* reporter,
64 const sk_gpu_test::ContextInfo& childInfo,
Robert Phillipsba375a82018-04-11 10:08:06 -040065 const GrBackendTexture& backendTexture,
Greg Daniela5cb7812017-06-16 09:45:32 -040066 const GrBackendSemaphore& semaphore) {
Greg Daniela5cb7812017-06-16 09:45:32 -040067
68 childInfo.testContext()->makeCurrent();
69
70 const SkImageInfo childII = SkImageInfo::Make(CHILD_W, CHILD_H, kRGBA_8888_SkColorType,
71 kPremul_SkAlphaType);
72
73 GrContext* childCtx = childInfo.grContext();
74 sk_sp<SkSurface> childSurface(SkSurface::MakeRenderTarget(childCtx, SkBudgeted::kNo,
75 childII, 0, kTopLeft_GrSurfaceOrigin,
76 nullptr));
77
78 sk_sp<SkImage> childImage = SkImage::MakeFromTexture(childCtx,
79 backendTexture,
80 kTopLeft_GrSurfaceOrigin,
Greg Danielf5d87582017-12-18 14:48:15 -050081 kRGBA_8888_SkColorType,
Greg Daniela5cb7812017-06-16 09:45:32 -040082 kPremul_SkAlphaType,
Greg Danielf5d87582017-12-18 14:48:15 -050083 nullptr,
84 nullptr,
Greg Daniela5cb7812017-06-16 09:45:32 -040085 nullptr);
86
87 SkCanvas* childCanvas = childSurface->getCanvas();
88 childCanvas->clear(SK_ColorRED);
89
90 childSurface->wait(1, &semaphore);
91
92 childCanvas->drawImage(childImage, CHILD_W/2, 0);
93
94 SkPaint paint;
95 paint.setColor(SK_ColorGREEN);
96 SkIRect rect = SkIRect::MakeLTRB(0, CHILD_H/2, CHILD_W, CHILD_H);
97 childCanvas->drawIRect(rect, paint);
98
99 // read pixels
100 SkBitmap bitmap;
101 bitmap.allocPixels(childII);
Mike Reedf1942192017-07-21 14:24:29 -0400102 childSurface->readPixels(bitmap, 0, 0);
Greg Daniela5cb7812017-06-16 09:45:32 -0400103
104 check_pixels(reporter, bitmap);
105}
106
107void surface_semaphore_test(skiatest::Reporter* reporter,
108 const sk_gpu_test::ContextInfo& mainInfo,
109 const sk_gpu_test::ContextInfo& childInfo1,
Greg Daniel51316782017-08-02 15:10:09 +0000110 const sk_gpu_test::ContextInfo& childInfo2,
111 bool flushContext) {
Greg Daniela5cb7812017-06-16 09:45:32 -0400112 GrContext* mainCtx = mainInfo.grContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500113 if (!mainCtx->priv().caps()->fenceSyncSupport()) {
Greg Daniela5cb7812017-06-16 09:45:32 -0400114 return;
115 }
116
117 const SkImageInfo ii = SkImageInfo::Make(MAIN_W, MAIN_H, kRGBA_8888_SkColorType,
118 kPremul_SkAlphaType);
119
120 sk_sp<SkSurface> mainSurface(SkSurface::MakeRenderTarget(mainCtx, SkBudgeted::kNo,
121 ii, 0, kTopLeft_GrSurfaceOrigin,
122 nullptr));
123 SkCanvas* mainCanvas = mainSurface->getCanvas();
124 mainCanvas->clear(SK_ColorBLUE);
125
126 SkAutoTArray<GrBackendSemaphore> semaphores(2);
Greg Daniel8761e0c2017-07-20 16:36:01 -0400127#ifdef SK_VULKAN
Greg Danielbdf12ad2018-10-12 09:31:11 -0400128 if (GrBackendApi::kVulkan == mainInfo.backend()) {
Greg Daniel8761e0c2017-07-20 16:36:01 -0400129 // Initialize the secondary semaphore instead of having Ganesh create one internally
Robert Phillips9da87e02019-02-04 13:26:26 -0500130 GrVkGpu* gpu = static_cast<GrVkGpu*>(mainCtx->priv().getGpu());
Greg Daniel8761e0c2017-07-20 16:36:01 -0400131 const GrVkInterface* interface = gpu->vkInterface();
132 VkDevice device = gpu->device();
133
134 VkSemaphore vkSem;
135
136 VkSemaphoreCreateInfo createInfo;
137 createInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
138 createInfo.pNext = nullptr;
139 createInfo.flags = 0;
140 GR_VK_CALL_ERRCHECK(interface, CreateSemaphore(device, &createInfo, nullptr, &vkSem));
141
142 semaphores[1].initVulkan(vkSem);
143 }
144#endif
Greg Daniela5cb7812017-06-16 09:45:32 -0400145
Greg Daniele6bfb7d2019-04-17 15:26:11 -0400146 GrFlushInfo info;
147 info.fNumSemaphores = 2;
148 info.fSignalSemaphores = semaphores.get();
Greg Daniel51316782017-08-02 15:10:09 +0000149 if (flushContext) {
Greg Daniele6bfb7d2019-04-17 15:26:11 -0400150 mainCtx->flush(info);
Greg Daniel51316782017-08-02 15:10:09 +0000151 } else {
Greg Daniele6bfb7d2019-04-17 15:26:11 -0400152 mainSurface->flush(SkSurface::BackendSurfaceAccess::kNoAccess, info);
Greg Daniel51316782017-08-02 15:10:09 +0000153 }
Greg Daniela5cb7812017-06-16 09:45:32 -0400154
155 sk_sp<SkImage> mainImage = mainSurface->makeImageSnapshot();
Robert Phillipsba375a82018-04-11 10:08:06 -0400156 GrBackendTexture backendTexture = mainImage->getBackendTexture(false);
Greg Daniela5cb7812017-06-16 09:45:32 -0400157
Robert Phillipsba375a82018-04-11 10:08:06 -0400158 draw_child(reporter, childInfo1, backendTexture, semaphores[0]);
Greg Daniela5cb7812017-06-16 09:45:32 -0400159
160#ifdef SK_VULKAN
Greg Danielbdf12ad2018-10-12 09:31:11 -0400161 if (GrBackendApi::kVulkan == mainInfo.backend()) {
Greg Daniela5cb7812017-06-16 09:45:32 -0400162 // In Vulkan we need to make sure we are sending the correct VkImageLayout in with the
163 // backendImage. After the first child draw the layout gets changed to SHADER_READ, so
164 // we just manually set that here.
Robert Phillipsba375a82018-04-11 10:08:06 -0400165 GrVkImageInfo vkInfo;
166 SkAssertResult(backendTexture.getVkImageInfo(&vkInfo));
167 vkInfo.updateImageLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
Greg Daniela5cb7812017-06-16 09:45:32 -0400168 }
169#endif
170
Robert Phillipsba375a82018-04-11 10:08:06 -0400171 draw_child(reporter, childInfo2, backendTexture, semaphores[1]);
Greg Daniela5cb7812017-06-16 09:45:32 -0400172}
173
Brian Salomondcfca432017-11-15 15:48:03 -0500174DEF_GPUTEST(SurfaceSemaphores, reporter, options) {
Greg Daniela5cb7812017-06-16 09:45:32 -0400175#if defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_MAC)
176 static constexpr auto kNativeGLType = sk_gpu_test::GrContextFactory::kGL_ContextType;
177#else
178 static constexpr auto kNativeGLType = sk_gpu_test::GrContextFactory::kGLES_ContextType;
179#endif
180
181 for (int typeInt = 0; typeInt < sk_gpu_test::GrContextFactory::kContextTypeCnt; ++typeInt) {
Greg Daniel51316782017-08-02 15:10:09 +0000182 for (auto flushContext : { false, true }) {
183 sk_gpu_test::GrContextFactory::ContextType contextType =
184 (sk_gpu_test::GrContextFactory::ContextType) typeInt;
185 // Use "native" instead of explicitly trying OpenGL and OpenGL ES. Do not use GLES on
186 // desktop since tests do not account for not fixing http://skbug.com/2809
187 if (contextType == sk_gpu_test::GrContextFactory::kGL_ContextType ||
188 contextType == sk_gpu_test::GrContextFactory::kGLES_ContextType) {
189 if (contextType != kNativeGLType) {
190 continue;
191 }
192 }
Brian Salomondcfca432017-11-15 15:48:03 -0500193 sk_gpu_test::GrContextFactory factory(options);
194 sk_gpu_test::ContextInfo ctxInfo = factory.getContextInfo(
Greg Daniel51316782017-08-02 15:10:09 +0000195 contextType, sk_gpu_test::GrContextFactory::ContextOverrides::kDisableNVPR);
196 if (!sk_gpu_test::GrContextFactory::IsRenderingContext(contextType)) {
Greg Daniela5cb7812017-06-16 09:45:32 -0400197 continue;
198 }
Greg Daniel51316782017-08-02 15:10:09 +0000199 skiatest::ReporterContext ctx(
200 reporter, SkString(sk_gpu_test::GrContextFactory::ContextTypeName(contextType)));
201 if (ctxInfo.grContext()) {
Brian Salomondcfca432017-11-15 15:48:03 -0500202 sk_gpu_test::ContextInfo child1 =
203 factory.getSharedContextInfo(ctxInfo.grContext(), 0);
204 sk_gpu_test::ContextInfo child2 =
205 factory.getSharedContextInfo(ctxInfo.grContext(), 1);
Greg Daniel51316782017-08-02 15:10:09 +0000206 if (!child1.grContext() || !child2.grContext()) {
207 continue;
208 }
Yuqian Licc8eb602017-08-01 17:43:30 +0000209
Greg Daniel51316782017-08-02 15:10:09 +0000210 surface_semaphore_test(reporter, ctxInfo, child1, child2, flushContext);
211 }
Greg Daniela5cb7812017-06-16 09:45:32 -0400212 }
213 }
214}
215
Greg Danieldba7e7c2017-07-20 15:47:30 -0400216DEF_GPUTEST_FOR_RENDERING_CONTEXTS(EmptySurfaceSemaphoreTest, reporter, ctxInfo) {
217 GrContext* ctx = ctxInfo.grContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500218 if (!ctx->priv().caps()->fenceSyncSupport()) {
Greg Danieldba7e7c2017-07-20 15:47:30 -0400219 return;
220 }
221
222 const SkImageInfo ii = SkImageInfo::Make(MAIN_W, MAIN_H, kRGBA_8888_SkColorType,
223 kPremul_SkAlphaType);
224
225 sk_sp<SkSurface> mainSurface(SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo,
226 ii, 0, kTopLeft_GrSurfaceOrigin,
227 nullptr));
228
229 // Flush surface once without semaphores to make sure there is no peneding IO for it.
230 mainSurface->flush();
231
232 GrBackendSemaphore semaphore;
Greg Daniel51316782017-08-02 15:10:09 +0000233 GrSemaphoresSubmitted submitted = mainSurface->flushAndSignalSemaphores(1, &semaphore);
234 REPORTER_ASSERT(reporter, GrSemaphoresSubmitted::kYes == submitted);
Greg Danieldba7e7c2017-07-20 15:47:30 -0400235
Greg Danielbdf12ad2018-10-12 09:31:11 -0400236 if (GrBackendApi::kOpenGL == ctxInfo.backend()) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500237 GrGLGpu* gpu = static_cast<GrGLGpu*>(ctx->priv().getGpu());
Greg Danieldba7e7c2017-07-20 15:47:30 -0400238 const GrGLInterface* interface = gpu->glInterface();
239 GrGLsync sync = semaphore.glSync();
240 REPORTER_ASSERT(reporter, sync);
241 bool result;
242 GR_GL_CALL_RET(interface, result, IsSync(sync));
243 REPORTER_ASSERT(reporter, result);
244 }
245
246#ifdef SK_VULKAN
Greg Danielbdf12ad2018-10-12 09:31:11 -0400247 if (GrBackendApi::kVulkan == ctxInfo.backend()) {
Robert Phillips9da87e02019-02-04 13:26:26 -0500248 GrVkGpu* gpu = static_cast<GrVkGpu*>(ctx->priv().getGpu());
Greg Danieldba7e7c2017-07-20 15:47:30 -0400249 const GrVkInterface* interface = gpu->vkInterface();
250 VkDevice device = gpu->device();
251 VkQueue queue = gpu->queue();
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500252 GrVkCommandPool* cmdPool = gpu->cmdPool();
Greg Danieldba7e7c2017-07-20 15:47:30 -0400253 VkCommandBuffer cmdBuffer;
254
255 // Create Command Buffer
256 const VkCommandBufferAllocateInfo cmdInfo = {
257 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType
258 nullptr, // pNext
Ethan Nicholas8e265a72018-12-12 16:22:40 -0500259 cmdPool->vkCommandPool(), // commandPool
Greg Danieldba7e7c2017-07-20 15:47:30 -0400260 VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level
261 1 // bufferCount
262 };
263
264 VkResult err = GR_VK_CALL(interface, AllocateCommandBuffers(device, &cmdInfo, &cmdBuffer));
265 if (err) {
266 return;
267 }
268
269 VkCommandBufferBeginInfo cmdBufferBeginInfo;
270 memset(&cmdBufferBeginInfo, 0, sizeof(VkCommandBufferBeginInfo));
271 cmdBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
272 cmdBufferBeginInfo.pNext = nullptr;
273 cmdBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
274 cmdBufferBeginInfo.pInheritanceInfo = nullptr;
275
276 GR_VK_CALL_ERRCHECK(interface, BeginCommandBuffer(cmdBuffer, &cmdBufferBeginInfo));
277 GR_VK_CALL_ERRCHECK(interface, EndCommandBuffer(cmdBuffer));
278
279 VkFenceCreateInfo fenceInfo;
280 VkFence fence;
281
282 memset(&fenceInfo, 0, sizeof(VkFenceCreateInfo));
283 fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
284 err = GR_VK_CALL(interface, CreateFence(device, &fenceInfo, nullptr, &fence));
285 SkASSERT(!err);
286
287 VkPipelineStageFlags waitStages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
288 VkSubmitInfo submitInfo;
289 memset(&submitInfo, 0, sizeof(VkSubmitInfo));
290 submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
291 submitInfo.pNext = nullptr;
292 submitInfo.waitSemaphoreCount = 1;
293 VkSemaphore vkSem = semaphore.vkSemaphore();
294 submitInfo.pWaitSemaphores = &vkSem;
295 submitInfo.pWaitDstStageMask = &waitStages;
296 submitInfo.commandBufferCount = 1;
297 submitInfo.pCommandBuffers = &cmdBuffer;
298 submitInfo.signalSemaphoreCount = 0;
299 submitInfo.pSignalSemaphores = nullptr;
300 GR_VK_CALL_ERRCHECK(interface, QueueSubmit(queue, 1, &submitInfo, fence));
301
302 err = GR_VK_CALL(interface, WaitForFences(device, 1, &fence, true, 3000000000));
303
304 REPORTER_ASSERT(reporter, err != VK_TIMEOUT);
305
306 GR_VK_CALL(interface, DestroyFence(device, fence, nullptr));
307 GR_VK_CALL(interface, DestroySemaphore(device, vkSem, nullptr));
308 // If the above test fails the wait semaphore will never be signaled which can cause the
309 // device to hang when tearing down (even if just tearing down GL). So we Fail here to
310 // kill things.
311 if (err == VK_TIMEOUT) {
Ben Wagnerb4aab9a2017-08-16 10:53:04 -0400312 SK_ABORT("Waiting on semaphore indefinitely");
Greg Danieldba7e7c2017-07-20 15:47:30 -0400313 }
314 }
315#endif
316}