xref: /aosp_15_r20/external/skia/tools/skqp/src/skqp_GpuTestProcs.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2022 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 
8 #include "tests/Test.h"
9 #include "tools/skqp/src/skqp.h"
10 
11 #include "include/core/SkStream.h"
12 #include "include/gpu/ganesh/GrDirectContext.h"
13 
14 #ifdef SK_VULKAN
15 #include "tools/gpu/vk/VkTestContext.h"
16 #include <mutex>
17 #endif
18 #if defined(SK_GRAPHITE)
19 #include "include/gpu/graphite/Context.h"
20 #include "tools/graphite/ContextFactory.h"
21 #endif
22 
23 using sk_gpu_test::ContextInfo;
24 using sk_gpu_test::GrContextFactory;
25 using sk_gpu_test::TestContext;
26 
27 #ifdef SK_GL
28 using sk_gpu_test::GLTestContext;
29 #endif
30 
31 namespace skiatest {
32 
IsGLContextType(skgpu::ContextType type)33 bool IsGLContextType(skgpu::ContextType type) {
34     return skgpu::ganesh::ContextTypeBackend(type) == GrBackendApi::kOpenGL;
35 }
IsVulkanContextType(skgpu::ContextType type)36 bool IsVulkanContextType(skgpu::ContextType type) {
37     return skgpu::ganesh::ContextTypeBackend(type) == GrBackendApi::kVulkan;
38 }
IsMockContextType(skgpu::ContextType type)39 bool IsMockContextType(skgpu::ContextType type) {
40     return type == skgpu::ContextType::kMock;
41 }
42 
43 // These are not supported
IsMetalContextType(skgpu::ContextType type)44 bool IsMetalContextType(skgpu::ContextType type) { return false; }
IsDirect3DContextType(skgpu::ContextType type)45 bool IsDirect3DContextType(skgpu::ContextType type) { return false; }
IsDawnContextType(skgpu::ContextType type)46 bool IsDawnContextType(skgpu::ContextType type) { return false; }
47 
vk_has_physical_devices()48 static bool vk_has_physical_devices() {
49     static bool supported = false;
50 #ifdef SK_VULKAN
51     static std::once_flag flag;
52     std::call_once(flag, []() {
53         // We could create a VkInstance and call vkEnumeratePhysicalDevices devices directly, but
54         // CreatePlatformVkTestContext is already configured to do that and will return nullptr if
55         // there are no available devices.
56         std::unique_ptr<TestContext> testCtx(sk_gpu_test::CreatePlatformVkTestContext(nullptr));
57         if (testCtx) {
58             supported = true;
59         }
60     });
61 #endif
62     return supported;
63 }
64 
65 #if defined(SK_BUILD_FOR_UNIX) || defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_MAC)
66 // Used for testing on desktop machines.
67 static constexpr auto kNativeGLType = skgpu::ContextType::kGL;
68 #else
69 static constexpr auto kNativeGLType = skgpu::ContextType::kGLES;
70 #endif
71 
72 #ifdef SK_BUILD_FOR_ANDROID
73 static_assert(kNativeGLType == skgpu::ContextType::kGLES, "CTS requires GLES");
74 #endif
75 
skip_context(skgpu::ContextType contextType)76 static bool skip_context(skgpu::ContextType contextType) {
77     // Use "native" instead of explicitly trying both OpenGL and OpenGL ES.
78     if (contextType == skgpu::ContextType::kGL || contextType == skgpu::ContextType::kGLES) {
79         if (contextType != kNativeGLType) {
80             return true;
81         }
82     }
83 
84     // The Android CDD (https://source.android.com/compatibility/12/android-12-cdd.pdf) does not
85     // require Vulkan, but if it enumerates at least one VkPhysicalDevice then it is expected that
86     // Vulkan is supported
87     if (contextType == skgpu::ContextType::kVulkan && !vk_has_physical_devices()) {
88         return true;
89     }
90     return false;
91 }
92 
RunWithGaneshTestContexts(GrContextTestFn * testFn,ContextTypeFilterFn * filter,Reporter * reporter,const GrContextOptions & options)93 void RunWithGaneshTestContexts(GrContextTestFn* testFn,
94                                ContextTypeFilterFn* filter,
95                                Reporter* reporter,
96                                const GrContextOptions& options) {
97     for (int typeInt = 0; typeInt < skgpu::kContextTypeCount; ++typeInt) {
98         skgpu::ContextType contextType = static_cast<skgpu::ContextType>(typeInt);
99         if (skip_context(contextType)) {
100             continue;
101         }
102 
103         // The logic below is intended to mirror the behavior in DMGpuTestProcs.cpp
104         if (filter && !(*filter)(contextType)) {
105             continue;
106         }
107 
108         sk_gpu_test::GrContextFactory factory(options);
109         sk_gpu_test::ContextInfo ctxInfo = factory.getContextInfo(contextType);
110 
111         ReporterContext ctx(reporter, SkString(skgpu::ContextTypeName(contextType)));
112         if (ctxInfo.directContext()) {
113             ctxInfo.testContext()->makeCurrent();
114             (*testFn)(reporter, ctxInfo);
115             // Sync so any release/finished procs get called.
116             ctxInfo.directContext()->flushAndSubmit(GrSyncCpu::kYes);
117         }
118     }
119 }
120 
121 #if defined(SK_GRAPHITE)
122 
123 namespace graphite {
124 
RunWithGraphiteTestContexts(GraphiteTestFn * test,ContextTypeFilterFn * filter,Reporter * reporter,const TestOptions & options)125 void RunWithGraphiteTestContexts(GraphiteTestFn* test,
126                                  ContextTypeFilterFn* filter,
127                                  Reporter* reporter,
128                                  const TestOptions& options) {
129     ContextFactory factory(options);
130     for (int typeInt = 0; typeInt < skgpu::kContextTypeCount; ++typeInt) {
131         skgpu::ContextType contextType = static_cast<skgpu::ContextType>(typeInt);
132         if (skip_context(contextType)) {
133             continue;
134         }
135 
136         // The logic below is intended to mirror the behavior in DMGpuTestProcs.cpp
137         if (filter && !(*filter)(contextType)) {
138             continue;
139         }
140 
141         skiatest::graphite::ContextInfo ctxInfo = factory.getContextInfo(contextType);
142         if (!ctxInfo.fContext) {
143             continue;
144         }
145 
146         ReporterContext ctx(reporter, SkString(skgpu::ContextTypeName(contextType)));
147         (*test)(reporter, ctxInfo.fContext, ctxInfo.fTestContext);
148     }
149 }
150 
151 }  // namespace graphite
152 
153 #endif  // SK_GRAPHITE
154 
155 }  // namespace skiatest
156 
printBackendInfo(const char * dstPath)157 void SkQP::printBackendInfo(const char* dstPath) {
158 #ifdef SK_ENABLE_DUMP_GPU
159     SkFILEWStream out(dstPath);
160     out.writeText("[\n");
161 
162     skgpu::ContextType contextsToDump[] = {skiatest::kNativeGLType, skgpu::ContextType::kVulkan};
163 
164     for (auto contextType : contextsToDump) {
165         std::unique_ptr<TestContext> testCtx;
166         switch (contextType) {
167 #ifdef SK_GL
168             case skgpu::ContextType::kGL:
169                 testCtx.reset(sk_gpu_test::CreatePlatformGLTestContext(kGL_GrGLStandard, nullptr));
170                 break;
171             case skgpu::ContextType::kGLES:
172                 testCtx.reset(
173                         sk_gpu_test::CreatePlatformGLTestContext(kGLES_GrGLStandard, nullptr));
174                 break;
175 #endif
176 #ifdef SK_VULKAN
177             case skgpu::ContextType::kVulkan:
178                 testCtx.reset(sk_gpu_test::CreatePlatformVkTestContext(nullptr));
179                 break;
180 #endif
181             default: {
182             }
183         }
184 
185         if (testCtx) {
186             GrContextOptions options;
187             testCtx->makeCurrent();
188             if (sk_sp<GrDirectContext> ctx = testCtx->makeContext(options)) {
189                 SkString info = ctx->dump();
190                 // remove null
191                 out.write(info.c_str(), info.size());
192                 out.writeText(",\n");
193             }
194         }
195     }
196     out.writeText("]\n");
197 #endif
198 }
199