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)28 ContextFactory::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()34 ContextFactory::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)47 ContextFactory::ContextFactory(const TestOptions& options)
48 : fOptions(options) {}
49
AsContextInfo(const OwnedContextInfo & owned)50 ContextInfo ContextFactory::AsContextInfo(const OwnedContextInfo& owned) {
51 return ContextInfo{owned.fTestContext.get(), owned.fContext.get()};
52 }
53
getContextInfo(skgpu::ContextType type)54 ContextInfo ContextFactory::getContextInfo(skgpu::ContextType type) {
55 if (!skgpu::IsDawnBackend(type) && fOptions.hasDawnOptions()) {
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, fOptions.fUseTintIR); \
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