1 /* 2 * Copyright 2021 Google LLC 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 "tools/graphite/ContextFactory.h" 9 10 #include "include/gpu/graphite/Context.h" 11 #include "src/gpu/graphite/Caps.h" 12 #include "src/gpu/graphite/ContextPriv.h" 13 14 #ifdef SK_DAWN 15 #include "tools/graphite/dawn/GraphiteDawnTestContext.h" 16 #endif 17 #ifdef SK_METAL 18 #include "tools/graphite/mtl/GraphiteMtlTestContext.h" 19 #endif 20 #ifdef SK_VULKAN 21 #include "tools/graphite/vk/GraphiteVulkanTestContext.h" 22 #endif 23 24 namespace skiatest::graphite { 25 26 ContextFactory::OwnedContextInfo::OwnedContextInfo() = default; 27 OwnedContextInfo(skgpu::ContextType type,std::unique_ptr<GraphiteTestContext> testContext,std::unique_ptr<skgpu::graphite::Context> context)28ContextFactory::OwnedContextInfo::OwnedContextInfo( 29 skgpu::ContextType type, 30 std::unique_ptr<GraphiteTestContext> testContext, 31 std::unique_ptr<skgpu::graphite::Context> context) 32 : fType(type), fTestContext(std::move(testContext)), fContext(std::move(context)) {} 33 ~OwnedContextInfo()34ContextFactory::OwnedContextInfo::~OwnedContextInfo() { 35 // If we created a non-syncing Context then we have to wait for GPU work to finish before 36 // destroying the Context. 37 if (fContext && !fContext->priv().caps()->allowCpuSync() && fContext->hasUnfinishedGpuWork()) { 38 fTestContext->syncedSubmit(fContext.get()); 39 SkASSERT(!fContext->hasUnfinishedGpuWork()); 40 } 41 } 42 43 ContextFactory::OwnedContextInfo::OwnedContextInfo(OwnedContextInfo&&) = default; 44 ContextFactory::OwnedContextInfo& ContextFactory::OwnedContextInfo::operator=(OwnedContextInfo&&) = 45 default; 46 ContextFactory(const TestOptions & options)47ContextFactory::ContextFactory(const TestOptions& options) 48 : fOptions(options) {} 49 AsContextInfo(const OwnedContextInfo & owned)50ContextInfo ContextFactory::AsContextInfo(const OwnedContextInfo& owned) { 51 return ContextInfo{owned.fTestContext.get(), owned.fContext.get()}; 52 } 53 getContextInfo(skgpu::ContextType type)54ContextInfo ContextFactory::getContextInfo(skgpu::ContextType type) { 55 if (!skgpu::IsDawnBackend(type) && fOptions.fNeverYieldToWebGPU) { 56 return {}; 57 } 58 59 // Look for an existing ContextInfo that we can re-use. 60 for (const OwnedContextInfo& ctxInfo : fContexts) { 61 if (ctxInfo.fType == type) { 62 return AsContextInfo(ctxInfo); 63 } 64 } 65 66 // Create a new ContextInfo from this context type. 67 std::unique_ptr<GraphiteTestContext> testCtx; 68 69 switch (type) { 70 case skgpu::ContextType::kMetal: { 71 #ifdef SK_METAL 72 testCtx = graphite::MtlTestContext::Make(); 73 #endif 74 } break; 75 case skgpu::ContextType::kVulkan: { 76 #ifdef SK_VULKAN 77 testCtx = graphite::VulkanTestContext::Make(); 78 #endif 79 } break; 80 #ifdef SK_DAWN 81 82 #define CASE(TYPE) \ 83 case skgpu::ContextType::kDawn_##TYPE: \ 84 testCtx = graphite::DawnTestContext::Make(wgpu::BackendType::TYPE); \ 85 break; 86 #else 87 #define CASE(TYPE) \ 88 case skgpu::ContextType::kDawn_##TYPE: \ 89 break; 90 #endif // SK_DAWN 91 CASE(D3D11) 92 CASE(D3D12) 93 CASE(Metal) 94 CASE(Vulkan) 95 CASE(OpenGL) 96 CASE(OpenGLES) 97 #undef CASE 98 99 default: 100 break; 101 } 102 103 if (!testCtx) { 104 return ContextInfo{}; 105 } 106 107 std::unique_ptr<skgpu::graphite::Context> context = testCtx->makeContext(fOptions); 108 if (!context) { 109 return ContextInfo{}; 110 } 111 112 fContexts.push_back({type, std::move(testCtx), std::move(context)}); 113 return AsContextInfo(fContexts.back()); 114 } 115 116 } // namespace skiatest::graphite 117