SurfaceSemaphoreTest.cpp 13 KB

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