• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
8 #include "include/core/SkAlphaType.h"
9 #include "include/core/SkBitmap.h"
10 #include "include/core/SkCanvas.h"
11 #include "include/core/SkColor.h"
12 #include "include/core/SkColorSpace.h"
13 #include "include/core/SkColorType.h"
14 #include "include/core/SkImage.h"
15 #include "include/core/SkImageInfo.h"
16 #include "include/core/SkPaint.h"
17 #include "include/core/SkRect.h"
18 #include "include/core/SkRefCnt.h"
19 #include "include/core/SkString.h"
20 #include "include/core/SkSurface.h"
21 #include "include/core/SkTypes.h"
22 #include "include/gpu/GpuTypes.h"
23 #include "include/gpu/GrBackendSemaphore.h"
24 #include "include/gpu/GrBackendSurface.h"
25 #include "include/gpu/GrDirectContext.h"
26 #include "include/gpu/GrTypes.h"
27 #include "include/private/base/SkTemplates.h"
28 #include "src/gpu/ganesh/GrCaps.h"
29 #include "src/gpu/ganesh/GrDirectContextPriv.h"
30 #include "tests/CtsEnforcement.h"
31 #include "tests/Test.h"
32 #include "tools/gpu/TestContext.h"
33 
34 #include <string>
35 #include <cstdint>
36 #include <initializer_list>
37 
38 #ifdef SK_GL
39 #include "include/gpu/gl/GrGLFunctions.h"
40 #include "include/gpu/gl/GrGLInterface.h"
41 #include "include/gpu/gl/GrGLTypes.h"
42 #include "src/gpu/ganesh/gl/GrGLGpu.h"
43 #include "src/gpu/ganesh/gl/GrGLUtil.h"
44 #endif
45 
46 #ifdef SK_VULKAN
47 #include "src/gpu/ganesh/vk/GrVkCommandPool.h"
48 #include "src/gpu/ganesh/vk/GrVkGpu.h"
49 #include "src/gpu/ganesh/vk/GrVkUtil.h"
50 
51 #include <vulkan/vulkan_core.h>
52 
53 namespace skgpu { struct VulkanInterface; }
54 
55 #ifdef VK_USE_PLATFORM_WIN32_KHR
56 // windows wants to define this as CreateSemaphoreA or CreateSemaphoreW
57 #undef CreateSemaphore
58 #endif
59 #endif
60 
61 using namespace skia_private;
62 
63 struct GrContextOptions;
64 
65 static const int MAIN_W = 8, MAIN_H = 16;
66 static const int CHILD_W = 16, CHILD_H = 16;
67 
check_pixels(skiatest::Reporter * reporter,const SkBitmap & bitmap)68 void check_pixels(skiatest::Reporter* reporter, const SkBitmap& bitmap) {
69     const uint32_t* canvasPixels = static_cast<const uint32_t*>(bitmap.getPixels());
70 
71     bool failureFound = false;
72     SkPMColor expectedPixel;
73     for (int cy = 0; cy < CHILD_H && !failureFound; ++cy) {
74         for (int cx = 0; cx < CHILD_W && !failureFound; ++cx) {
75             SkPMColor canvasPixel = canvasPixels[cy * CHILD_W + cx];
76             if (cy < CHILD_H / 2) {
77                 if (cx < CHILD_W / 2) {
78                     expectedPixel = 0xFF0000FF; // Red
79                 } else {
80                     expectedPixel = 0xFFFF0000; // Blue
81                 }
82             } else {
83                 expectedPixel = 0xFF00FF00; // Green
84             }
85             if (expectedPixel != canvasPixel) {
86                 failureFound = true;
87                 ERRORF(reporter, "Wrong color at %d, %d. Got 0x%08x when we expected 0x%08x",
88                        cx, cy, canvasPixel, expectedPixel);
89             }
90         }
91     }
92 }
93 
draw_child(skiatest::Reporter * reporter,const sk_gpu_test::ContextInfo & childInfo,const GrBackendTexture & backendTexture,const GrBackendSemaphore & semaphore)94 void draw_child(skiatest::Reporter* reporter,
95                 const sk_gpu_test::ContextInfo& childInfo,
96                 const GrBackendTexture& backendTexture,
97                 const GrBackendSemaphore& semaphore) {
98 
99     childInfo.testContext()->makeCurrent();
100 
101     const SkImageInfo childII = SkImageInfo::Make(CHILD_W, CHILD_H, kRGBA_8888_SkColorType,
102                                                   kPremul_SkAlphaType);
103 
104     auto childDContext = childInfo.directContext();
105     sk_sp<SkSurface> childSurface(SkSurface::MakeRenderTarget(
106             childDContext, skgpu::Budgeted::kNo, childII, 0, kTopLeft_GrSurfaceOrigin, nullptr));
107 
108     sk_sp<SkImage> childImage = SkImage::MakeFromTexture(childDContext,
109                                                          backendTexture,
110                                                          kTopLeft_GrSurfaceOrigin,
111                                                          kRGBA_8888_SkColorType,
112                                                          kPremul_SkAlphaType,
113                                                          nullptr,
114                                                          nullptr,
115                                                          nullptr);
116 
117     SkCanvas* childCanvas = childSurface->getCanvas();
118     childCanvas->clear(SK_ColorRED);
119 
120     childSurface->wait(1, &semaphore);
121 
122     childCanvas->drawImage(childImage, CHILD_W/2, 0);
123 
124     SkPaint paint;
125     paint.setColor(SK_ColorGREEN);
126     SkIRect rect = SkIRect::MakeLTRB(0, CHILD_H/2, CHILD_W, CHILD_H);
127     childCanvas->drawIRect(rect, paint);
128 
129     // read pixels
130     SkBitmap bitmap;
131     bitmap.allocPixels(childII);
132     childSurface->readPixels(bitmap, 0, 0);
133 
134     check_pixels(reporter, bitmap);
135 }
136 
137 enum class FlushType { kSurface, kImage, kContext };
138 
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)139 void surface_semaphore_test(skiatest::Reporter* reporter,
140                             const sk_gpu_test::ContextInfo& mainInfo,
141                             const sk_gpu_test::ContextInfo& childInfo1,
142                             const sk_gpu_test::ContextInfo& childInfo2,
143                             FlushType flushType) {
144     auto mainCtx = mainInfo.directContext();
145     if (!mainCtx->priv().caps()->semaphoreSupport()) {
146         return;
147     }
148 
149     const SkImageInfo ii = SkImageInfo::Make(MAIN_W, MAIN_H, kRGBA_8888_SkColorType,
150                                              kPremul_SkAlphaType);
151 
152     sk_sp<SkSurface> mainSurface(SkSurface::MakeRenderTarget(
153             mainCtx, skgpu::Budgeted::kNo, ii, 0, kTopLeft_GrSurfaceOrigin, nullptr));
154     SkCanvas* mainCanvas = mainSurface->getCanvas();
155     auto blueSurface = mainSurface->makeSurface(ii);
156     blueSurface->getCanvas()->clear(SK_ColorBLUE);
157     auto blueImage = blueSurface->makeImageSnapshot();
158     blueSurface.reset();
159     mainCanvas->drawImage(blueImage, 0, 0);
160 
161     AutoTArray<GrBackendSemaphore> semaphores(2);
162 #ifdef SK_VULKAN
163     if (GrBackendApi::kVulkan == mainInfo.backend()) {
164         // Initialize the secondary semaphore instead of having Ganesh create one internally
165         GrVkGpu* gpu = static_cast<GrVkGpu*>(mainCtx->priv().getGpu());
166         VkDevice device = gpu->device();
167 
168         VkSemaphore vkSem;
169 
170         VkSemaphoreCreateInfo createInfo;
171         createInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
172         createInfo.pNext = nullptr;
173         createInfo.flags = 0;
174         GR_VK_CALL_ERRCHECK(gpu, CreateSemaphore(device, &createInfo, nullptr, &vkSem));
175 
176         semaphores[1].initVulkan(vkSem);
177     }
178 #endif
179 
180     GrFlushInfo info;
181     info.fNumSemaphores = 2;
182     info.fSignalSemaphores = semaphores.get();
183     switch (flushType) {
184         case FlushType::kSurface:
185             mainSurface->flush(SkSurface::BackendSurfaceAccess::kNoAccess, info);
186             break;
187         case FlushType::kImage:
188             blueImage->flush(mainCtx, info);
189             break;
190         case FlushType::kContext:
191             mainCtx->flush(info);
192             break;
193     }
194     mainCtx->submit();
195 
196     GrBackendTexture backendTexture = mainSurface->getBackendTexture(
197             SkSurface::BackendHandleAccess::kFlushRead_BackendHandleAccess);
198 
199     draw_child(reporter, childInfo1, backendTexture, semaphores[0]);
200 
201 #ifdef SK_VULKAN
202     if (GrBackendApi::kVulkan == mainInfo.backend()) {
203         // In Vulkan we need to make sure we are sending the correct VkImageLayout in with the
204         // backendImage. After the first child draw the layout gets changed to SHADER_READ, so
205         // we just manually set that here.
206         backendTexture.setVkImageLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
207     }
208 #endif
209 
210     draw_child(reporter, childInfo2, backendTexture, semaphores[1]);
211 }
212 
213 #ifdef SK_GL
DEF_GANESH_TEST(SurfaceSemaphores,reporter,options,CtsEnforcement::kApiLevel_T)214 DEF_GANESH_TEST(SurfaceSemaphores, reporter, options, CtsEnforcement::kApiLevel_T) {
215 #if defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_MAC)
216     static constexpr auto kNativeGLType = sk_gpu_test::GrContextFactory::kGL_ContextType;
217 #else
218     static constexpr auto kNativeGLType = sk_gpu_test::GrContextFactory::kGLES_ContextType;
219 #endif
220 
221     for (int typeInt = 0; typeInt < sk_gpu_test::GrContextFactory::kContextTypeCnt; ++typeInt) {
222         for (auto flushType : {FlushType::kSurface, FlushType::kImage, FlushType::kContext}) {
223             sk_gpu_test::GrContextFactory::ContextType contextType =
224                     (sk_gpu_test::GrContextFactory::ContextType) typeInt;
225             // Use "native" instead of explicitly trying OpenGL and OpenGL ES. Do not use GLES on
226             // desktop since tests do not account for not fixing http://skbug.com/2809
227             if (contextType == sk_gpu_test::GrContextFactory::kGL_ContextType ||
228                 contextType == sk_gpu_test::GrContextFactory::kGLES_ContextType) {
229                 if (contextType != kNativeGLType) {
230                     continue;
231                 }
232             }
233             sk_gpu_test::GrContextFactory factory(options);
234             sk_gpu_test::ContextInfo ctxInfo = factory.getContextInfo(contextType);
235             if (!sk_gpu_test::GrContextFactory::IsRenderingContext(contextType)) {
236                 continue;
237             }
238             skiatest::ReporterContext ctx(
239                    reporter, SkString(sk_gpu_test::GrContextFactory::ContextTypeName(contextType)));
240             if (ctxInfo.directContext()) {
241                 sk_gpu_test::ContextInfo child1 =
242                         factory.getSharedContextInfo(ctxInfo.directContext(), 0);
243                 sk_gpu_test::ContextInfo child2 =
244                         factory.getSharedContextInfo(ctxInfo.directContext(), 1);
245                 if (!child1.directContext() || !child2.directContext()) {
246                     continue;
247                 }
248 
249                 surface_semaphore_test(reporter, ctxInfo, child1, child2, flushType);
250             }
251         }
252     }
253 }
254 #endif
255 
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(EmptySurfaceSemaphoreTest,reporter,ctxInfo,CtsEnforcement::kApiLevel_T)256 DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(EmptySurfaceSemaphoreTest,
257                                        reporter,
258                                        ctxInfo,
259                                        CtsEnforcement::kApiLevel_T) {
260     auto ctx = ctxInfo.directContext();
261     if (!ctx->priv().caps()->semaphoreSupport()) {
262         return;
263     }
264 
265     const SkImageInfo ii = SkImageInfo::Make(MAIN_W, MAIN_H, kRGBA_8888_SkColorType,
266                                              kPremul_SkAlphaType);
267 
268     sk_sp<SkSurface> mainSurface(SkSurface::MakeRenderTarget(
269             ctx, skgpu::Budgeted::kNo, ii, 0, kTopLeft_GrSurfaceOrigin, nullptr));
270 
271     // Flush surface once without semaphores to make sure there is no peneding IO for it.
272     mainSurface->flushAndSubmit();
273 
274     GrBackendSemaphore semaphore;
275     GrFlushInfo flushInfo;
276     flushInfo.fNumSemaphores = 1;
277     flushInfo.fSignalSemaphores = &semaphore;
278     GrSemaphoresSubmitted submitted =
279             mainSurface->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo);
280     REPORTER_ASSERT(reporter, GrSemaphoresSubmitted::kYes == submitted);
281     ctx->submit();
282 
283 #ifdef SK_GL
284     if (GrBackendApi::kOpenGL == ctxInfo.backend()) {
285         GrGLGpu* gpu = static_cast<GrGLGpu*>(ctx->priv().getGpu());
286         const GrGLInterface* interface = gpu->glInterface();
287         GrGLsync sync = semaphore.glSync();
288         REPORTER_ASSERT(reporter, sync);
289         bool result;
290         GR_GL_CALL_RET(interface, result, IsSync(sync));
291         REPORTER_ASSERT(reporter, result);
292     }
293 #endif
294 
295 #ifdef SK_VULKAN
296     if (GrBackendApi::kVulkan == ctxInfo.backend()) {
297         GrVkGpu* gpu = static_cast<GrVkGpu*>(ctx->priv().getGpu());
298         const skgpu::VulkanInterface* interface = gpu->vkInterface();
299         VkDevice device = gpu->device();
300         VkQueue queue = gpu->queue();
301         GrVkCommandPool* cmdPool = gpu->cmdPool();
302         VkCommandBuffer cmdBuffer;
303 
304         // Create Command Buffer
305         const VkCommandBufferAllocateInfo cmdInfo = {
306             VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,   // sType
307             nullptr,                                          // pNext
308             cmdPool->vkCommandPool(),                         // commandPool
309             VK_COMMAND_BUFFER_LEVEL_PRIMARY,                  // level
310             1                                                 // bufferCount
311         };
312 
313         VkResult err = GR_VK_CALL(interface, AllocateCommandBuffers(device, &cmdInfo, &cmdBuffer));
314         if (err) {
315             return;
316         }
317 
318         VkCommandBufferBeginInfo cmdBufferBeginInfo;
319         memset(&cmdBufferBeginInfo, 0, sizeof(VkCommandBufferBeginInfo));
320         cmdBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
321         cmdBufferBeginInfo.pNext = nullptr;
322         cmdBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
323         cmdBufferBeginInfo.pInheritanceInfo = nullptr;
324 
325         GR_VK_CALL_ERRCHECK(gpu, BeginCommandBuffer(cmdBuffer, &cmdBufferBeginInfo));
326         GR_VK_CALL_ERRCHECK(gpu, EndCommandBuffer(cmdBuffer));
327 
328         VkFenceCreateInfo fenceInfo;
329         VkFence fence;
330 
331         memset(&fenceInfo, 0, sizeof(VkFenceCreateInfo));
332         fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
333         err = GR_VK_CALL(interface, CreateFence(device, &fenceInfo, nullptr, &fence));
334         SkASSERT(!err);
335 
336         VkPipelineStageFlags waitStages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
337         VkSubmitInfo submitInfo;
338         memset(&submitInfo, 0, sizeof(VkSubmitInfo));
339         submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
340         submitInfo.pNext = nullptr;
341         submitInfo.waitSemaphoreCount = 1;
342         VkSemaphore vkSem = semaphore.vkSemaphore();
343         submitInfo.pWaitSemaphores = &vkSem;
344         submitInfo.pWaitDstStageMask = &waitStages;
345         submitInfo.commandBufferCount = 1;
346         submitInfo.pCommandBuffers = &cmdBuffer;
347         submitInfo.signalSemaphoreCount = 0;
348         submitInfo.pSignalSemaphores = nullptr;
349         GR_VK_CALL_ERRCHECK(gpu, QueueSubmit(queue, 1, &submitInfo, fence));
350 
351         err = GR_VK_CALL(interface, WaitForFences(device, 1, &fence, true, 3000000000));
352 
353         REPORTER_ASSERT(reporter, err != VK_TIMEOUT);
354 
355         GR_VK_CALL(interface, DestroyFence(device, fence, nullptr));
356         GR_VK_CALL(interface, DestroySemaphore(device, vkSem, nullptr));
357         // If the above test fails the wait semaphore will never be signaled which can cause the
358         // device to hang when tearing down (even if just tearing down GL). So we Fail here to
359         // kill things.
360         if (err == VK_TIMEOUT) {
361             SK_ABORT("Waiting on semaphore indefinitely");
362         }
363     }
364 #endif
365 }
366