GrFinishedFlushTest.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. /*
  2. * Copyright 2019 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 "tests/Test.h"
  8. #include <chrono>
  9. #include "include/core/SkSurface.h"
  10. #include "include/gpu/GrContext.h"
  11. #include "src/gpu/GrContextPriv.h"
  12. #include "src/gpu/GrGpu.h"
  13. using namespace sk_gpu_test;
  14. static void testing_finished_proc(void* ctx) {
  15. int* count = (int*)ctx;
  16. *count += 1;
  17. }
  18. static void busy_wait_for_callback(int* count, int expectedValue, GrContext* ctx,
  19. skiatest::Reporter* reporter) {
  20. // Busy waiting should detect that the work is done.
  21. auto begin = std::chrono::steady_clock::now();
  22. auto end = begin;
  23. do {
  24. ctx->checkAsyncWorkCompletion();
  25. end = std::chrono::steady_clock::now();
  26. } while (*count != expectedValue && (end - begin) < std::chrono::seconds(1));
  27. if (*count != expectedValue) {
  28. ERRORF(reporter, "Expected count failed to reach %d within 1 second of busy waiting.",
  29. expectedValue);
  30. }
  31. }
  32. DEF_GPUTEST_FOR_RENDERING_CONTEXTS(FlushFinishedProcTest, reporter, ctxInfo) {
  33. GrContext* ctx = ctxInfo.grContext();
  34. SkImageInfo info =
  35. SkImageInfo::Make(8, 8, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
  36. sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info);
  37. SkCanvas* canvas = surface->getCanvas();
  38. canvas->clear(SK_ColorGREEN);
  39. auto image = surface->makeImageSnapshot();
  40. GrFlushInfo flushInfoSyncCpu;
  41. flushInfoSyncCpu.fFlags = kSyncCpu_GrFlushFlag;
  42. ctx->flush(flushInfoSyncCpu);
  43. int count = 0;
  44. GrFlushInfo flushInfoFinishedProc;
  45. flushInfoFinishedProc.fFinishedProc = testing_finished_proc;
  46. flushInfoFinishedProc.fFinishedContext = (void*)&count;
  47. // There is no work on the surface so flushing may immediately call the finished proc.
  48. surface->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfoFinishedProc);
  49. REPORTER_ASSERT(reporter, count == 0 || count == 1);
  50. // Busy waiting should detect that the work is done.
  51. busy_wait_for_callback(&count, 1, ctx, reporter);
  52. canvas->clear(SK_ColorRED);
  53. surface->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfoFinishedProc);
  54. bool expectAsyncCallback =
  55. ctx->backend() == GrBackendApi::kVulkan ||
  56. ((ctx->backend() == GrBackendApi::kOpenGL) && ctx->priv().caps()->fenceSyncSupport());
  57. if (expectAsyncCallback) {
  58. // On Vulkan the command buffer we just submitted may or may not have finished immediately
  59. // so the finish proc may not have been called.
  60. REPORTER_ASSERT(reporter, count == 1 || count == 2);
  61. } else {
  62. REPORTER_ASSERT(reporter, count == 2);
  63. }
  64. ctx->flush(flushInfoSyncCpu);
  65. REPORTER_ASSERT(reporter, count == 2);
  66. // Test flushing via the SkImage
  67. canvas->drawImage(image, 0, 0);
  68. image->flush(ctx, flushInfoFinishedProc);
  69. if (expectAsyncCallback) {
  70. // On Vulkan the command buffer we just submitted may or may not have finished immediately
  71. // so the finish proc may not have been called.
  72. REPORTER_ASSERT(reporter, count == 2 || count == 3);
  73. } else {
  74. REPORTER_ASSERT(reporter, count == 3);
  75. }
  76. ctx->flush(flushInfoSyncCpu);
  77. REPORTER_ASSERT(reporter, count == 3);
  78. // Test flushing via the GrContext
  79. canvas->clear(SK_ColorBLUE);
  80. ctx->flush(flushInfoFinishedProc);
  81. if (expectAsyncCallback) {
  82. // On Vulkan the command buffer we just submitted may or may not have finished immediately
  83. // so the finish proc may not have been called.
  84. REPORTER_ASSERT(reporter, count == 3 || count == 4);
  85. } else {
  86. REPORTER_ASSERT(reporter, count == 4);
  87. }
  88. ctx->flush(flushInfoSyncCpu);
  89. REPORTER_ASSERT(reporter, count == 4);
  90. // There is no work on the surface so flushing may immediately call the finished proc.
  91. ctx->flush(flushInfoFinishedProc);
  92. REPORTER_ASSERT(reporter, count == 4 || count == 5);
  93. busy_wait_for_callback(&count, 5, ctx, reporter);
  94. count = 0;
  95. int count2 = 0;
  96. canvas->clear(SK_ColorGREEN);
  97. surface->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfoFinishedProc);
  98. // There is no work to be flushed here so this will return immediately, but make sure the
  99. // finished call from this proc isn't called till the previous surface flush also is finished.
  100. flushInfoFinishedProc.fFinishedContext = (void*)&count2;
  101. ctx->flush(flushInfoFinishedProc);
  102. REPORTER_ASSERT(reporter, count <= 1 && count2 <= count);
  103. ctx->flush(flushInfoSyncCpu);
  104. REPORTER_ASSERT(reporter, count == 1);
  105. REPORTER_ASSERT(reporter, count == count2);
  106. }