1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2019 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "tests/Test.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include <chrono> 11cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h" 12cb93a386Sopenharmony_ci#include "include/core/SkSurface.h" 13cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h" 14cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h" 15cb93a386Sopenharmony_ci#include "src/gpu/GrGpu.h" 16cb93a386Sopenharmony_ci 17cb93a386Sopenharmony_ciusing namespace sk_gpu_test; 18cb93a386Sopenharmony_ci 19cb93a386Sopenharmony_cistatic void testing_finished_proc(void* ctx) { 20cb93a386Sopenharmony_ci int* count = (int*)ctx; 21cb93a386Sopenharmony_ci *count += 1; 22cb93a386Sopenharmony_ci} 23cb93a386Sopenharmony_ci 24cb93a386Sopenharmony_cistatic void busy_wait_for_callback(int* count, int expectedValue, GrDirectContext* dContext, 25cb93a386Sopenharmony_ci skiatest::Reporter* reporter) { 26cb93a386Sopenharmony_ci // Busy waiting should detect that the work is done. 27cb93a386Sopenharmony_ci auto begin = std::chrono::steady_clock::now(); 28cb93a386Sopenharmony_ci auto end = begin; 29cb93a386Sopenharmony_ci do { 30cb93a386Sopenharmony_ci dContext->checkAsyncWorkCompletion(); 31cb93a386Sopenharmony_ci end = std::chrono::steady_clock::now(); 32cb93a386Sopenharmony_ci } while (*count != expectedValue && (end - begin) < std::chrono::seconds(1)); 33cb93a386Sopenharmony_ci if (*count != expectedValue) { 34cb93a386Sopenharmony_ci ERRORF(reporter, "Expected count failed to reach %d within 1 second of busy waiting.", 35cb93a386Sopenharmony_ci expectedValue); 36cb93a386Sopenharmony_ci } 37cb93a386Sopenharmony_ci} 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_ciDEF_GPUTEST_FOR_RENDERING_CONTEXTS(FlushFinishedProcTest, reporter, ctxInfo) { 40cb93a386Sopenharmony_ci auto dContext = ctxInfo.directContext(); 41cb93a386Sopenharmony_ci 42cb93a386Sopenharmony_ci SkImageInfo info = 43cb93a386Sopenharmony_ci SkImageInfo::Make(8, 8, kRGBA_8888_SkColorType, kPremul_SkAlphaType); 44cb93a386Sopenharmony_ci sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(dContext, SkBudgeted::kNo, info); 45cb93a386Sopenharmony_ci SkCanvas* canvas = surface->getCanvas(); 46cb93a386Sopenharmony_ci 47cb93a386Sopenharmony_ci canvas->clear(SK_ColorGREEN); 48cb93a386Sopenharmony_ci auto image = surface->makeImageSnapshot(); 49cb93a386Sopenharmony_ci 50cb93a386Sopenharmony_ci dContext->flush(); 51cb93a386Sopenharmony_ci dContext->submit(true); 52cb93a386Sopenharmony_ci 53cb93a386Sopenharmony_ci int count = 0; 54cb93a386Sopenharmony_ci 55cb93a386Sopenharmony_ci GrFlushInfo flushInfoFinishedProc; 56cb93a386Sopenharmony_ci flushInfoFinishedProc.fFinishedProc = testing_finished_proc; 57cb93a386Sopenharmony_ci flushInfoFinishedProc.fFinishedContext = (void*)&count; 58cb93a386Sopenharmony_ci // There is no work on the surface so flushing may immediately call the finished proc. 59cb93a386Sopenharmony_ci surface->flush(flushInfoFinishedProc); 60cb93a386Sopenharmony_ci dContext->submit(); 61cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, count == 0 || count == 1); 62cb93a386Sopenharmony_ci // Busy waiting should detect that the work is done. 63cb93a386Sopenharmony_ci busy_wait_for_callback(&count, 1, dContext, reporter); 64cb93a386Sopenharmony_ci 65cb93a386Sopenharmony_ci canvas->clear(SK_ColorRED); 66cb93a386Sopenharmony_ci 67cb93a386Sopenharmony_ci surface->flush(flushInfoFinishedProc); 68cb93a386Sopenharmony_ci dContext->submit(); 69cb93a386Sopenharmony_ci 70cb93a386Sopenharmony_ci bool fenceSupport = dContext->priv().caps()->fenceSyncSupport(); 71cb93a386Sopenharmony_ci bool expectAsyncCallback = 72cb93a386Sopenharmony_ci dContext->backend() == GrBackendApi::kVulkan || 73cb93a386Sopenharmony_ci ((dContext->backend() == GrBackendApi::kOpenGL) && fenceSupport) || 74cb93a386Sopenharmony_ci ((dContext->backend() == GrBackendApi::kMetal) && fenceSupport) || 75cb93a386Sopenharmony_ci dContext->backend() == GrBackendApi::kDawn || 76cb93a386Sopenharmony_ci dContext->backend() == GrBackendApi::kDirect3D; 77cb93a386Sopenharmony_ci if (expectAsyncCallback) { 78cb93a386Sopenharmony_ci // On Vulkan the command buffer we just submitted may or may not have finished immediately 79cb93a386Sopenharmony_ci // so the finish proc may not have been called. 80cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, count == 1 || count == 2); 81cb93a386Sopenharmony_ci } else { 82cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, count == 2); 83cb93a386Sopenharmony_ci } 84cb93a386Sopenharmony_ci dContext->flush(); 85cb93a386Sopenharmony_ci dContext->submit(true); 86cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, count == 2); 87cb93a386Sopenharmony_ci 88cb93a386Sopenharmony_ci // Test flushing via the SkImage 89cb93a386Sopenharmony_ci canvas->drawImage(image, 0, 0); 90cb93a386Sopenharmony_ci image->flush(dContext, flushInfoFinishedProc); 91cb93a386Sopenharmony_ci dContext->submit(); 92cb93a386Sopenharmony_ci if (expectAsyncCallback) { 93cb93a386Sopenharmony_ci // On Vulkan the command buffer we just submitted may or may not have finished immediately 94cb93a386Sopenharmony_ci // so the finish proc may not have been called. 95cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, count == 2 || count == 3); 96cb93a386Sopenharmony_ci } else { 97cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, count == 3); 98cb93a386Sopenharmony_ci } 99cb93a386Sopenharmony_ci dContext->flush(); 100cb93a386Sopenharmony_ci dContext->submit(true); 101cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, count == 3); 102cb93a386Sopenharmony_ci 103cb93a386Sopenharmony_ci // Test flushing via the GrDirectContext 104cb93a386Sopenharmony_ci canvas->clear(SK_ColorBLUE); 105cb93a386Sopenharmony_ci dContext->flush(flushInfoFinishedProc); 106cb93a386Sopenharmony_ci dContext->submit(); 107cb93a386Sopenharmony_ci if (expectAsyncCallback) { 108cb93a386Sopenharmony_ci // On Vulkan the command buffer we just submitted may or may not have finished immediately 109cb93a386Sopenharmony_ci // so the finish proc may not have been called. 110cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, count == 3 || count == 4); 111cb93a386Sopenharmony_ci } else { 112cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, count == 4); 113cb93a386Sopenharmony_ci } 114cb93a386Sopenharmony_ci dContext->flush(); 115cb93a386Sopenharmony_ci dContext->submit(true); 116cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, count == 4); 117cb93a386Sopenharmony_ci 118cb93a386Sopenharmony_ci // There is no work on the surface so flushing may immediately call the finished proc. 119cb93a386Sopenharmony_ci dContext->flush(flushInfoFinishedProc); 120cb93a386Sopenharmony_ci dContext->submit(); 121cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, count == 4 || count == 5); 122cb93a386Sopenharmony_ci busy_wait_for_callback(&count, 5, dContext, reporter); 123cb93a386Sopenharmony_ci 124cb93a386Sopenharmony_ci count = 0; 125cb93a386Sopenharmony_ci int count2 = 0; 126cb93a386Sopenharmony_ci canvas->clear(SK_ColorGREEN); 127cb93a386Sopenharmony_ci surface->flush(flushInfoFinishedProc); 128cb93a386Sopenharmony_ci dContext->submit(); 129cb93a386Sopenharmony_ci // There is no work to be flushed here so this will return immediately, but make sure the 130cb93a386Sopenharmony_ci // finished call from this proc isn't called till the previous surface flush also is finished. 131cb93a386Sopenharmony_ci flushInfoFinishedProc.fFinishedContext = (void*)&count2; 132cb93a386Sopenharmony_ci dContext->flush(flushInfoFinishedProc); 133cb93a386Sopenharmony_ci dContext->submit(); 134cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, count <= 1 && count2 <= count); 135cb93a386Sopenharmony_ci 136cb93a386Sopenharmony_ci dContext->flush(); 137cb93a386Sopenharmony_ci dContext->submit(true); 138cb93a386Sopenharmony_ci 139cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, count == 1); 140cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, count == count2); 141cb93a386Sopenharmony_ci} 142cb93a386Sopenharmony_ci 143