1 //
2 // Copyright 2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 // angle_test_instantiate.h: Adds support for filtering parameterized
8 // tests by platform, so we skip unsupported configs.
9
10 #ifndef ANGLE_TEST_INSTANTIATE_H_
11 #define ANGLE_TEST_INSTANTIATE_H_
12
13 #include <gtest/gtest.h>
14
15 #include "common/platform_helpers.h"
16
17 namespace angle
18 {
19 struct SystemInfo;
20 struct PlatformParameters;
21
22 // Operating systems
23 bool IsOzone();
24
25 // CPU architectures
26 bool IsARM64();
27
28 // Android devices
29 bool IsNexus5X();
30 bool IsNexus9();
31 bool IsPixelXL();
32 bool IsPixel2();
33 bool IsPixel2XL();
34 bool IsPixel4();
35 bool IsPixel4XL();
36 bool IsPixel6();
37 bool IsGalaxyS22();
38 bool IsNVIDIAShield();
39
40 // Android versions
41 bool IsAndroid14OrNewer();
42
43 // GPU vendors.
44 bool IsIntel();
45 bool IsAMD();
46 bool IsAppleGPU();
47 bool IsARM();
48 bool IsNVIDIA();
49 bool IsQualcomm();
50
51 // GPU devices.
52 bool IsSwiftshaderDevice();
53 bool IsIntelUHD630Mobile();
54
55 bool HasMesa();
56
57 bool IsPlatformAvailable(const PlatformParameters ¶m);
58
59 // This functions is used to filter which tests should be registered,
60 // T must be or inherit from angle::PlatformParameters.
61 template <typename T>
FilterTestParams(const T * params,size_t numParams)62 std::vector<T> FilterTestParams(const T *params, size_t numParams)
63 {
64 std::vector<T> filtered;
65
66 for (size_t i = 0; i < numParams; i++)
67 {
68 if (IsPlatformAvailable(params[i]))
69 {
70 filtered.push_back(params[i]);
71 }
72 }
73
74 return filtered;
75 }
76
77 template <typename T>
FilterTestParams(const std::vector<T> & params)78 std::vector<T> FilterTestParams(const std::vector<T> ¶ms)
79 {
80 return FilterTestParams(params.data(), params.size());
81 }
82
83 // Used to generate valid test names out of testing::PrintToStringParamName used in combined tests.
84 struct CombinedPrintToStringParamName
85 {
86 template <class ParamType>
operatorCombinedPrintToStringParamName87 std::string operator()(const testing::TestParamInfo<ParamType> &info) const
88 {
89 std::string name = testing::PrintToStringParamName()(info);
90 std::string sanitized;
91 for (const char c : name)
92 {
93 if (c == ',')
94 {
95 sanitized += '_';
96 }
97 else if (isalnum(c) || c == '_')
98 {
99 sanitized += c;
100 }
101 }
102 return sanitized;
103 }
104 };
105
106 #define ANGLE_INSTANTIATE_TEST_PLATFORMS(testName, ...) \
107 testing::ValuesIn(::angle::FilterTestParams(testName##__VA_ARGS__##params, \
108 ArraySize(testName##__VA_ARGS__##params)))
109
110 // Instantiate the test once for each extra argument. The types of all the
111 // arguments must match, and getRenderer must be implemented for that type.
112 #define ANGLE_INSTANTIATE_TEST(testName, first, ...) \
113 const std::remove_reference<decltype(first)>::type testName##params[] = {first, \
114 ##__VA_ARGS__}; \
115 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
116 testing::PrintToStringParamName())
117
118 #define ANGLE_INSTANTIATE_TEST_ARRAY(testName, valuesin) \
119 INSTANTIATE_TEST_SUITE_P(, testName, testing::ValuesIn(::angle::FilterTestParams(valuesin)), \
120 testing::PrintToStringParamName())
121
122 #if !defined(ANGLE_TEST_ENABLE_SYSTEM_EGL)
123 # define ANGLE_TEST_PLATFORMS_ES1_SYSTEM_EGL
124 # define ANGLE_TEST_PLATFORMS_ES2_SYSTEM_EGL
125 # define ANGLE_TEST_PLATFORMS_ES3_SYSTEM_EGL
126 # define ANGLE_TEST_PLATFORMS_ES31_SYSTEM_EGL
127 # define ANGLE_TEST_PLATFORMS_ES32_SYSTEM_EGL
128 #else
129 # define ANGLE_TEST_PLATFORMS_ES1_SYSTEM_EGL ES1_EGL(),
130 # define ANGLE_TEST_PLATFORMS_ES2_SYSTEM_EGL ES2_EGL(),
131 # define ANGLE_TEST_PLATFORMS_ES3_SYSTEM_EGL ES3_EGL(),
132 # define ANGLE_TEST_PLATFORMS_ES31_SYSTEM_EGL ES31_EGL(),
133 # define ANGLE_TEST_PLATFORMS_ES32_SYSTEM_EGL ES32_EGL(),
134 #endif
135
136 #define ANGLE_ALL_TEST_PLATFORMS_ES1 \
137 ANGLE_TEST_PLATFORMS_ES1_SYSTEM_EGL \
138 ES1_D3D11(), ES1_OPENGL(), ES1_OPENGLES(), ES1_VULKAN(), ES1_VULKAN_SWIFTSHADER(), \
139 ES1_VULKAN().enable(Feature::AsyncCommandQueue), \
140 ES1_VULKAN().enable(Feature::EnableParallelCompileAndLink)
141
142 #define ANGLE_ALL_TEST_PLATFORMS_ES2 \
143 ANGLE_TEST_PLATFORMS_ES2_SYSTEM_EGL \
144 ES2_D3D9(), ES2_D3D11(), ES2_OPENGL(), ES2_OPENGLES(), ES2_VULKAN(), ES2_VULKAN_SWIFTSHADER(), \
145 ES2_METAL(), ES2_VULKAN().enable(Feature::AsyncCommandQueue), \
146 ES2_VULKAN_SWIFTSHADER().enable(Feature::EnableParallelCompileAndLink), \
147 ES2_VULKAN_SWIFTSHADER() \
148 .enable(Feature::EnableParallelCompileAndLink) \
149 .enable(Feature::AsyncCommandQueue)
150
151 #define ANGLE_ALL_TEST_PLATFORMS_ES3 \
152 ANGLE_TEST_PLATFORMS_ES3_SYSTEM_EGL \
153 ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES(), ES3_VULKAN(), ES3_VULKAN_SWIFTSHADER(), \
154 ES3_METAL(), ES3_VULKAN().enable(Feature::AsyncCommandQueue), \
155 ES3_VULKAN().enable(Feature::EnableParallelCompileAndLink), \
156 ES3_VULKAN_SWIFTSHADER() \
157 .enable(Feature::EnableParallelCompileAndLink) \
158 .enable(Feature::AsyncCommandQueue)
159
160 #define ANGLE_ALL_TEST_PLATFORMS_ES31 \
161 ANGLE_TEST_PLATFORMS_ES31_SYSTEM_EGL \
162 ES31_D3D11(), ES31_OPENGL(), ES31_OPENGLES(), ES31_VULKAN(), ES31_VULKAN_SWIFTSHADER(), \
163 ES31_VULKAN().enable(Feature::AsyncCommandQueue), \
164 ES31_VULKAN_SWIFTSHADER() \
165 .enable(Feature::EnableParallelCompileAndLink) \
166 .enable(Feature::AsyncCommandQueue)
167
168 #define ANGLE_ALL_TEST_PLATFORMS_ES32 \
169 ANGLE_TEST_PLATFORMS_ES32_SYSTEM_EGL \
170 ES32_VULKAN(), ES32_VULKAN().enable(Feature::AsyncCommandQueue), \
171 ES32_VULKAN() \
172 .enable(Feature::AsyncCommandQueue) \
173 .enable(Feature::EnableParallelCompileAndLink)
174
175 #define ANGLE_ALL_TEST_PLATFORMS_GL32_CORE GL32_CORE_VULKAN(), GL32_CORE_VULKAN_SWIFTSHADER()
176
177 #define ANGLE_ALL_TEST_PLATFORMS_NULL ES2_NULL(), ES3_NULL(), ES31_NULL()
178
179 // Instantiate the test once for each GLES1 platform
180 #define ANGLE_INSTANTIATE_TEST_ES1(testName) \
181 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES1}; \
182 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
183 testing::PrintToStringParamName())
184
185 // Instantiate the test once for each GLES2 platform
186 #define ANGLE_INSTANTIATE_TEST_ES2(testName) \
187 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES2}; \
188 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
189 testing::PrintToStringParamName())
190
191 #define ANGLE_INSTANTIATE_TEST_ES2_AND(testName, ...) \
192 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES2, __VA_ARGS__}; \
193 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
194 testing::PrintToStringParamName())
195
196 // Instantiate the test once for each GLES3 platform
197 #define ANGLE_INSTANTIATE_TEST_ES3(testName) \
198 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES3}; \
199 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
200 testing::PrintToStringParamName())
201
202 #define ANGLE_INSTANTIATE_TEST_ES3_AND(testName, ...) \
203 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES3, __VA_ARGS__}; \
204 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
205 testing::PrintToStringParamName())
206
207 // Instantiate the test once for each GLES31 platform
208 #define ANGLE_INSTANTIATE_TEST_ES31(testName) \
209 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES31}; \
210 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
211 testing::PrintToStringParamName())
212
213 #define ANGLE_INSTANTIATE_TEST_ES31_AND(testName, ...) \
214 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES31, __VA_ARGS__}; \
215 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
216 testing::PrintToStringParamName())
217
218 // Instantiate the test once for each GLES32 platform
219 #define ANGLE_INSTANTIATE_TEST_ES32(testName) \
220 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES32}; \
221 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
222 testing::PrintToStringParamName())
223
224 #define ANGLE_INSTANTIATE_TEST_ES32_AND(testName, ...) \
225 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES32, __VA_ARGS__}; \
226 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
227 testing::PrintToStringParamName())
228
229 // Instantiate the test once for each desktop GL 3.2 core platform
230 #define ANGLE_INSTANTIATE_TEST_GL32_CORE(testName) \
231 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_GL32_CORE}; \
232 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
233 testing::PrintToStringParamName())
234
235 #define ANGLE_INSTANTIATE_TEST_GL32_CORE_AND(testName, ...) \
236 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_GL32_CORE, \
237 __VA_ARGS__}; \
238 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
239 testing::PrintToStringParamName())
240
241 // Multiple ES Version macros
242 #define ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(testName) \
243 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES2, \
244 ANGLE_ALL_TEST_PLATFORMS_ES3}; \
245 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
246 testing::PrintToStringParamName())
247
248 #define ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(testName, ...) \
249 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES2, \
250 ANGLE_ALL_TEST_PLATFORMS_ES3, __VA_ARGS__}; \
251 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
252 testing::PrintToStringParamName())
253
254 #define ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND_ES31(testName) \
255 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES2, \
256 ANGLE_ALL_TEST_PLATFORMS_ES3, \
257 ANGLE_ALL_TEST_PLATFORMS_ES31}; \
258 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
259 testing::PrintToStringParamName())
260
261 #define ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND_ES31_AND(testName, ...) \
262 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES2, \
263 ANGLE_ALL_TEST_PLATFORMS_ES3, \
264 ANGLE_ALL_TEST_PLATFORMS_ES31, __VA_ARGS__}; \
265 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
266 testing::PrintToStringParamName())
267
268 #define ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND_ES31_AND_NULL(testName) \
269 const PlatformParameters testName##params[] = { \
270 ANGLE_ALL_TEST_PLATFORMS_ES2, ANGLE_ALL_TEST_PLATFORMS_ES3, ANGLE_ALL_TEST_PLATFORMS_ES31, \
271 ANGLE_ALL_TEST_PLATFORMS_NULL}; \
272 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
273 testing::PrintToStringParamName())
274
275 #define ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND_ES31_AND_NULL_AND(testName, ...) \
276 const PlatformParameters testName##params[] = { \
277 ANGLE_ALL_TEST_PLATFORMS_ES2, ANGLE_ALL_TEST_PLATFORMS_ES3, ANGLE_ALL_TEST_PLATFORMS_ES31, \
278 ANGLE_ALL_TEST_PLATFORMS_NULL, __VA_ARGS__}; \
279 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
280 testing::PrintToStringParamName())
281
282 #define ANGLE_INSTANTIATE_TEST_ES3_AND_ES31(testName) \
283 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES3, \
284 ANGLE_ALL_TEST_PLATFORMS_ES31}; \
285 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
286 testing::PrintToStringParamName())
287
288 #define ANGLE_INSTANTIATE_TEST_ES3_AND_ES31_AND(testName, ...) \
289 const PlatformParameters testName##params[] = {ANGLE_ALL_TEST_PLATFORMS_ES3, \
290 ANGLE_ALL_TEST_PLATFORMS_ES31, __VA_ARGS__}; \
291 INSTANTIATE_TEST_SUITE_P(, testName, ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
292 testing::PrintToStringParamName())
293
294 // Instantiate the test for a combination of N parameters and the
295 // enumeration of platforms in the extra args, similar to
296 // ANGLE_INSTANTIATE_TEST. The macros are defined only for the Ns
297 // currently in use, and can be expanded as necessary.
298 #define ANGLE_INSTANTIATE_TEST_COMBINE_1(testName, print, combine1, first, ...) \
299 const std::remove_reference<decltype(first)>::type testName##params[] = {first, \
300 ##__VA_ARGS__}; \
301 INSTANTIATE_TEST_SUITE_P( \
302 , testName, testing::Combine(ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), combine1), print)
303 #define ANGLE_INSTANTIATE_TEST_COMBINE_3(testName, print, combine1, combine2, combine3, first, \
304 ...) \
305 const std::remove_reference<decltype(first)>::type testName##params[] = {first, \
306 ##__VA_ARGS__}; \
307 INSTANTIATE_TEST_SUITE_P(, testName, \
308 testing::Combine(ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
309 combine1, combine2, combine3), \
310 print)
311 #define ANGLE_INSTANTIATE_TEST_COMBINE_4(testName, print, combine1, combine2, combine3, combine4, \
312 first, ...) \
313 const std::remove_reference<decltype(first)>::type testName##params[] = {first, \
314 ##__VA_ARGS__}; \
315 INSTANTIATE_TEST_SUITE_P(, testName, \
316 testing::Combine(ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
317 combine1, combine2, combine3, combine4), \
318 print)
319 #define ANGLE_INSTANTIATE_TEST_COMBINE_5(testName, print, combine1, combine2, combine3, combine4, \
320 combine5, first, ...) \
321 const std::remove_reference<decltype(first)>::type testName##params[] = {first, \
322 ##__VA_ARGS__}; \
323 INSTANTIATE_TEST_SUITE_P(, testName, \
324 testing::Combine(ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
325 combine1, combine2, combine3, combine4, combine5), \
326 print)
327 #define ANGLE_INSTANTIATE_TEST_COMBINE_6(testName, print, combine1, combine2, combine3, combine4, \
328 combine5, combine6, first, ...) \
329 const std::remove_reference<decltype(first)>::type testName##params[] = {first, \
330 ##__VA_ARGS__}; \
331 INSTANTIATE_TEST_SUITE_P( \
332 , testName, \
333 testing::Combine(ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), combine1, combine2, combine3, \
334 combine4, combine5, combine6), \
335 print)
336
337 // Checks if a config is expected to be supported by checking a system-based allow list.
338 bool IsConfigAllowlisted(const SystemInfo &systemInfo, const PlatformParameters ¶m);
339
340 // Determines if a config is supported by trying to initialize it. Does
341 // not require SystemInfo.
342 bool IsConfigSupported(const PlatformParameters ¶m);
343
344 // Returns shared test system information. Can be used globally in the
345 // tests.
346 SystemInfo *GetTestSystemInfo();
347
348 // Returns a list of all enabled test platform names. For use in
349 // configuration enumeration.
350 std::vector<std::string> GetAvailableTestPlatformNames();
351
352 // Active config (e.g. ES2_Vulkan).
353 void SetSelectedConfig(const char *selectedConfig);
354 bool IsConfigSelected();
355
356 // Check whether texture swizzle is natively supported on Metal device.
357 bool IsMetalTextureSwizzleAvailable();
358
359 // Check whether TEXTURE_3D target is supported for compressed formats on Metal device.
360 bool IsMetalCompressedTexture3DAvailable();
361
362 extern bool gEnableANGLEPerTestCaptureLabel;
363
364 // For use with ANGLE_INSTANTIATE_TEST_ARRAY
365 template <typename ParamsT>
366 using ModifierFunc = std::function<ParamsT(const ParamsT &)>;
367
368 template <typename ParamsT>
CombineWithFuncs(const std::vector<ParamsT> & in,const std::vector<ModifierFunc<ParamsT>> & modifiers)369 std::vector<ParamsT> CombineWithFuncs(const std::vector<ParamsT> &in,
370 const std::vector<ModifierFunc<ParamsT>> &modifiers)
371 {
372 std::vector<ParamsT> out;
373 for (const ParamsT ¶msIn : in)
374 {
375 for (ModifierFunc<ParamsT> modifier : modifiers)
376 {
377 out.push_back(modifier(paramsIn));
378 }
379 }
380 return out;
381 }
382
383 template <typename ParamT, typename RangeT, typename ModifierT>
CombineWithValues(const std::vector<ParamT> & in,RangeT begin,RangeT end,ParamT combine (const ParamT &,ModifierT))384 std::vector<ParamT> CombineWithValues(const std::vector<ParamT> &in,
385 RangeT begin,
386 RangeT end,
387 ParamT combine(const ParamT &, ModifierT))
388 {
389 std::vector<ParamT> out;
390 for (const ParamT ¶msIn : in)
391 {
392 for (auto iter = begin; iter != end; ++iter)
393 {
394 out.push_back(combine(paramsIn, *iter));
395 }
396 }
397 return out;
398 }
399
400 template <typename ParamT, typename ModifierT>
CombineWithValues(const std::vector<ParamT> & in,const std::initializer_list<ModifierT> & modifiers,ParamT combine (const ParamT &,ModifierT))401 std::vector<ParamT> CombineWithValues(const std::vector<ParamT> &in,
402 const std::initializer_list<ModifierT> &modifiers,
403 ParamT combine(const ParamT &, ModifierT))
404 {
405 return CombineWithValues(in, modifiers.begin(), modifiers.end(), combine);
406 }
407
408 template <typename ParamT, typename ModifiersT, typename ModifierT>
CombineWithValues(const std::vector<ParamT> & in,const ModifiersT & modifiers,ParamT combine (const ParamT &,ModifierT))409 std::vector<ParamT> CombineWithValues(const std::vector<ParamT> &in,
410 const ModifiersT &modifiers,
411 ParamT combine(const ParamT &, ModifierT))
412 {
413 return CombineWithValues(in, std::begin(modifiers), std::end(modifiers), combine);
414 }
415
416 template <typename ParamT, typename FilterFunc>
FilterWithFunc(const std::vector<ParamT> & in,FilterFunc filter)417 std::vector<ParamT> FilterWithFunc(const std::vector<ParamT> &in, FilterFunc filter)
418 {
419 std::vector<ParamT> out;
420 for (const ParamT ¶m : in)
421 {
422 if (filter(param))
423 {
424 out.push_back(param);
425 }
426 }
427 return out;
428 }
429 } // namespace angle
430
431 #define ANGLE_SKIP_TEST_IF(COND) \
432 do \
433 { \
434 if (COND) \
435 { \
436 GTEST_SKIP() << "Test skipped: " #COND "."; \
437 return; \
438 } \
439 } while (0)
440
441 #endif // ANGLE_TEST_INSTANTIATE_H_
442