1 //
2 // Copyright 2017 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 // EXT_YUV_target.cpp:
7 // Test for EXT_YUV_target implementation.
8 //
9
10 #include "tests/test_utils/ShaderExtensionTest.h"
11
12 namespace
13 {
14 class EXTYUVTargetTest : public sh::ShaderExtensionTest
15 {
16 public:
InitializeCompiler()17 void InitializeCompiler() { InitializeCompiler(SH_GLSL_450_CORE_OUTPUT); }
InitializeCompiler(ShShaderOutput shaderOutputType)18 void InitializeCompiler(ShShaderOutput shaderOutputType)
19 {
20 DestroyCompiler();
21
22 mCompiler = sh::ConstructCompiler(GL_FRAGMENT_SHADER, testing::get<0>(GetParam()),
23 shaderOutputType, &mResources);
24 ASSERT_TRUE(mCompiler != nullptr) << "Compiler could not be constructed.";
25 }
26 };
27
28 const char EXTYTPragma[] = "#extension GL_EXT_YUV_target : require\n";
29
30 const char ESSL300_SimpleShader[] =
31 R"(precision mediump float;
32 uniform __samplerExternal2DY2YEXT uSampler;
33 out vec4 fragColor;
34 void main() {
35 fragColor = vec4(1.0);
36 })";
37
38 // Shader that samples the texture and writes to FragColor.
39 const char ESSL300_FragColorShader[] =
40 R"(precision mediump float;
41 uniform __samplerExternal2DY2YEXT uSampler;
42 layout(yuv) out vec4 fragColor;
43 void main() {
44 fragColor = texture(uSampler, vec2(0.0));
45 })";
46
47 // Shader that samples the texture and swizzle and writes to FragColor.
48 const char ESSL300_textureSwizzleFragColorShader[] =
49 R"(precision mediump float;
50 uniform __samplerExternal2DY2YEXT uSampler;
51 layout(yuv) out vec4 fragColor;
52 void main() {
53 fragColor = vec4(texture(uSampler, vec2(0.0)).zyx, 1.0);
54 })";
55
56 // Shader that specifies yuv layout qualifier multiple times.
57 const char ESSL300_YUVQualifierMultipleTimesShader[] =
58 R"(precision mediump float;
59 layout(yuv, yuv, yuv) out vec4 fragColor;
60 void main() {
61 })";
62
63 // Shader that specifies yuv layout qualifier for not output fails to compile.
64 const char ESSL300_YUVQualifierFailureShader1[] =
65 R"(precision mediump float;
66 layout(yuv) in vec4 fragColor;
67 void main() {
68 })";
69
70 const char ESSL300_YUVQualifierFailureShader2[] =
71 R"(precision mediump float;
72 layout(yuv) uniform;
73 layout(yuv) uniform Transform {
74 mat4 M1;
75 };
76 void main() {
77 })";
78
79 // Shader that specifies yuv layout qualifier with location fails to compile.
80 const char ESSL300_LocationAndYUVFailureShader[] =
81 R"(precision mediump float;
82 layout(location = 0, yuv) out vec4 fragColor;
83 void main() {
84 })";
85
86 // Shader that specifies yuv layout qualifier with multiple color outputs fails to compile.
87 const char ESSL300_MultipleColorAndYUVOutputsFailureShader1[] =
88 R"(precision mediump float;
89 layout(yuv) out vec4 fragColor;
90 layout out vec4 fragColor1;
91 void main() {
92 })";
93
94 const char ESSL300_MultipleColorAndYUVOutputsFailureShader2[] =
95 R"(precision mediump float;
96 layout(yuv) out vec4 fragColor;
97 layout(location = 1) out vec4 fragColor1;
98 void main() {
99 })";
100
101 // Shader that specifies yuv layout qualifier with depth output fails to compile.
102 const char ESSL300_DepthAndYUVOutputsFailureShader[] =
103 R"(precision mediump float;
104 layout(yuv) out vec4 fragColor;
105 void main() {
106 gl_FragDepth = 1.0f;
107 })";
108
109 // Shader that specifies yuv layout qualifier with multiple outputs fails to compile.
110 const char ESSL300_MultipleYUVOutputsFailureShader[] =
111 R"(precision mediump float;
112 layout(yuv) out vec4 fragColor;
113 layout(yuv) out vec4 fragColor1;
114 void main() {
115 })";
116
117 // Shader that specifies yuvCscStandartEXT type and associated values.
118 const char ESSL300_YuvCscStandardEXTShader[] =
119 R"(precision mediump float;
120 yuvCscStandardEXT;
121 yuvCscStandardEXT conv;
122 yuvCscStandardEXT conv1 = itu_601;
123 yuvCscStandardEXT conv2 = itu_601_full_range;
124 yuvCscStandardEXT conv3 = itu_709;
125 const yuvCscStandardEXT conv4 = itu_709;
126
127 uniform int u;
128 out vec4 my_color;
129
130 yuvCscStandardEXT conv_standard()
131 {
132 switch(u)
133 {
134 case 1:
135 return conv1;
136 case 2:
137 return conv2;
138 case 3:
139 return conv3;
140 default:
141 return conv;
142 }
143 }
144 bool is_itu_601(inout yuvCscStandardEXT csc)
145 {
146 csc = itu_601;
147 return csc == itu_601;
148 }
149 bool is_itu_709(yuvCscStandardEXT csc)
150 {
151 return csc == itu_709;
152 }
153 void main()
154 {
155 yuvCscStandardEXT conv = conv_standard();
156 bool csc_check1 = is_itu_601(conv);
157 bool csc_check2 = is_itu_709(itu_709);
158 if (csc_check1 && csc_check2) {
159 my_color = vec4(0, 1, 0, 1);
160 }
161 })";
162
163 // Shader that specifies yuvCscStandardEXT type constructor fails to compile.
164 const char ESSL300_YuvCscStandardEXTConstructFailureShader1[] =
165 R"(precision mediump float;
166 yuvCscStandardEXT conv = yuvCscStandardEXT();
167 void main() {
168 })";
169
170 const char ESSL300_YuvCscStandardEXTConstructFailureShader2[] =
171 R"(precision mediump float;
172 yuvCscStandardEXT conv = yuvCscStandardEXT(itu_601);
173 void main() {
174 })";
175
176 // Shader that specifies yuvCscStandardEXT type conversion fails to compile.
177 const char ESSL300_YuvCscStandardEXTConversionFailureShader1[] =
178 R"(precision mediump float;
179 yuvCscStandardEXT conv = false;
180 void main() {
181 })";
182
183 const char ESSL300_YuvCscStandardEXTConversionFailureShader2[] =
184 R"(precision mediump float;
185 yuvCscStandardEXT conv = 0;
186 void main() {
187 })";
188
189 const char ESSL300_YuvCscStandardEXTConversionFailureShader3[] =
190 R"(precision mediump float;
191 yuvCscStandardEXT conv = 2.0f;
192 void main() {
193 })";
194
195 const char ESSL300_YuvCscStandardEXTConversionFailureShader4[] =
196 R"(precision mediump float;
197 yuvCscStandardEXT conv = itu_601 | itu_709;
198 void main() {
199 })";
200
201 const char ESSL300_YuvCscStandardEXTConversionFailureShader5[] =
202 R"(precision mediump float;
203 yuvCscStandardEXT conv = itu_601 & 3.0f;
204 void main() {
205 })";
206
207 // Shader that specifies yuvCscStandardEXT type qualifiers fails to compile.
208 const char ESSL300_YuvCscStandardEXTQualifiersFailureShader1[] =
209 R"(precision mediump float;
210 in yuvCscStandardEXT conv = itu_601;
211 void main() {
212 })";
213
214 const char ESSL300_YuvCscStandardEXTQualifiersFailureShader2[] =
215 R"(precision mediump float;
216 out yuvCscStandardEXT conv = itu_601;
217 void main() {
218 })";
219
220 const char ESSL300_YuvCscStandardEXTQualifiersFailureShader3[] =
221 R"(precision mediump float;
222 uniform yuvCscStandardEXT conv = itu_601;
223 void main() {
224 })";
225
226 // Shader that specifies yuv_to_rgb() and rgb_to_yuv() built-in functions.
227 const char ESSL300_BuiltInFunctionsShader[] =
228 R"(precision mediump float;
229 yuvCscStandardEXT conv = itu_601;
230
231 out vec4 my_color;
232
233 void main()
234 {
235 vec3 yuv = rgb_2_yuv(vec3(0.0f), conv);
236 vec3 rgb = yuv_2_rgb(yuv, itu_601);
237 my_color = vec4(rgb, 1.0);
238 })";
239
240 // Shader with nested yuv_to_rgb() and rgb_to_yuv() built-in functions.
241 const char ESSL300_BuiltInFunctionsNested1Shader[] =
242 R"(precision mediump float;
243 yuvCscStandardEXT conv = itu_601;
244
245 out vec4 my_color;
246
247 void main()
248 {
249 vec3 rgb = yuv_2_rgb(rgb_2_yuv(vec3(0.0f), conv), conv);
250 my_color = vec4(rgb, 1.0);
251 })";
252 const char ESSL300_BuiltInFunctionsNested2Shader[] =
253 R"(precision mediump float;
254 yuvCscStandardEXT conv = itu_601_full_range;
255
256 out vec4 my_color;
257
258 void main()
259 {
260 vec3 rgb = yuv_2_rgb(vec3(0.1) + rgb_2_yuv(vec3(0.0f), conv), conv);
261 my_color = vec4(rgb, 1.0);
262 })";
263 const char ESSL300_BuiltInFunctionsNested3Shader[] =
264 R"(precision mediump float;
265 yuvCscStandardEXT conv = itu_709;
266
267 out vec4 my_color;
268
269 vec3 f(vec3 v) { return v + vec3(0.1); }
270
271 void main()
272 {
273 vec3 rgb = yuv_2_rgb(f(rgb_2_yuv(vec3(0.0f), conv)), conv);
274 my_color = vec4(rgb, 1.0);
275 })";
276 const char ESSL300_BuiltInFunctionsNested4Shader[] =
277 R"(precision mediump float;
278 yuvCscStandardEXT conv = itu_601;
279
280 out vec4 my_color;
281
282 vec3 f(vec3 v) { return v + vec3(0.1); }
283
284 void main()
285 {
286 vec3 rgb = f(yuv_2_rgb(f(rgb_2_yuv(vec3(0.0f), conv)), conv));
287 my_color = vec4(rgb, 1.0);
288 })";
289
290 // Shader with yuv_to_rgb() and rgb_to_yuv() built-in functions with different precision.
291 const char ESSL300_BuiltInFunctionsPrecisionShader[] =
292 R"(precision mediump float;
293 yuvCscStandardEXT conv = itu_601;
294
295 out vec4 my_color;
296
297 void main()
298 {
299 lowp vec3 rgbLow = vec3(0.1);
300 mediump vec3 rgbMedium = vec3(0.2);
301 highp vec3 rgbHigh = vec3(0.3);
302
303 lowp vec3 yuvLow = vec3(0.4);
304 mediump vec3 yuvMedium = vec3(0.5);
305 highp vec3 yuvHigh = vec3(0.6);
306
307 my_color = vec4(
308 rgb_2_yuv(rgbLow, conv) - rgb_2_yuv(rgbMedium, conv) + rgb_2_yuv(rgbHigh, conv) -
309 yuv_2_rgb(yuvLow, conv) - yuv_2_rgb(yuvMedium, conv) + yuv_2_rgb(yuvHigh, conv),
310 1.0);
311 })";
312
313 const char ESSL300_OverloadRgb2Yuv[] =
314 R"(precision mediump float;
315 float rgb_2_yuv(float x) { return x + 1.0; }
316
317 in float i;
318 out float o;
319
320 void main()
321 {
322 o = rgb_2_yuv(i);
323 })";
324
325 const char ESSL300_OverloadYuv2Rgb[] =
326 R"(precision mediump float;
327 float yuv_2_rgb(float x) { return x + 1.0; }
328
329 in float i;
330 out float o;
331
332 void main()
333 {
334 o = yuv_2_rgb(i);
335 })";
336
337 // Extension flag is required to compile properly. Expect failure when it is
338 // not present.
TEST_P(EXTYUVTargetTest,CompileFailsWithoutExtension)339 TEST_P(EXTYUVTargetTest, CompileFailsWithoutExtension)
340 {
341 mResources.EXT_YUV_target = 0;
342 InitializeCompiler();
343 EXPECT_FALSE(TestShaderCompile(EXTYTPragma));
344 }
345
346 // Extension directive is required to compile properly. Expect failure when
347 // it is not present.
TEST_P(EXTYUVTargetTest,CompileFailsWithExtensionWithoutPragma)348 TEST_P(EXTYUVTargetTest, CompileFailsWithExtensionWithoutPragma)
349 {
350 mResources.EXT_YUV_target = 1;
351 InitializeCompiler();
352 EXPECT_FALSE(TestShaderCompile(""));
353 }
354
355 // With extension flag and extension directive, compiling succeeds.
356 // Also test that the extension directive state is reset correctly.
TEST_P(EXTYUVTargetTest,CompileSucceedsWithExtensionAndPragma)357 TEST_P(EXTYUVTargetTest, CompileSucceedsWithExtensionAndPragma)
358 {
359 mResources.EXT_YUV_target = 1;
360 InitializeCompiler();
361 EXPECT_TRUE(TestShaderCompile(EXTYTPragma));
362 // Test reset functionality.
363 EXPECT_FALSE(TestShaderCompile(""));
364 EXPECT_TRUE(TestShaderCompile(EXTYTPragma));
365 }
366
367 INSTANTIATE_TEST_SUITE_P(CorrectVariantsWithExtensionAndPragma,
368 EXTYUVTargetTest,
369 Combine(Values(SH_GLES3_SPEC),
370 Values(sh::ESSLVersion300),
371 Values(ESSL300_SimpleShader, ESSL300_FragColorShader)));
372
373 class EXTYUVTargetCompileSuccessTest : public EXTYUVTargetTest
374 {};
375
TEST_P(EXTYUVTargetCompileSuccessTest,CompileSucceeds)376 TEST_P(EXTYUVTargetCompileSuccessTest, CompileSucceeds)
377 {
378 // Expect compile success.
379 mResources.EXT_YUV_target = 1;
380 InitializeCompiler();
381 EXPECT_TRUE(TestShaderCompile(EXTYTPragma));
382 }
383
384 #ifdef ANGLE_ENABLE_VULKAN
385 // Test that YUV built-in emulation works on Vulkan
TEST_P(EXTYUVTargetCompileSuccessTest,CompileSucceedsWithExtensionAndPragmaOnVulkan)386 TEST_P(EXTYUVTargetCompileSuccessTest, CompileSucceedsWithExtensionAndPragmaOnVulkan)
387 {
388 mResources.EXT_YUV_target = 1;
389 mCompileOptions.validateAST = 1;
390 InitializeCompiler(SH_SPIRV_VULKAN_OUTPUT);
391 EXPECT_TRUE(TestShaderCompile(EXTYTPragma));
392 }
393 #endif
394
395 INSTANTIATE_TEST_SUITE_P(CorrectESSL300Shaders,
396 EXTYUVTargetCompileSuccessTest,
397 Combine(Values(SH_GLES3_SPEC),
398 Values(sh::ESSLVersion300),
399 Values(ESSL300_FragColorShader,
400 ESSL300_textureSwizzleFragColorShader,
401 ESSL300_YUVQualifierMultipleTimesShader,
402 ESSL300_YuvCscStandardEXTShader,
403 ESSL300_BuiltInFunctionsShader,
404 ESSL300_BuiltInFunctionsNested1Shader,
405 ESSL300_BuiltInFunctionsNested2Shader,
406 ESSL300_BuiltInFunctionsNested3Shader,
407 ESSL300_BuiltInFunctionsNested4Shader,
408 ESSL300_BuiltInFunctionsPrecisionShader)));
409
410 class EXTYUVTargetCompileFailureTest : public EXTYUVTargetTest
411 {};
412
TEST_P(EXTYUVTargetCompileFailureTest,CompileFails)413 TEST_P(EXTYUVTargetCompileFailureTest, CompileFails)
414 {
415 // Expect compile failure due to shader error, with shader having correct pragma.
416 mResources.EXT_YUV_target = 1;
417 InitializeCompiler();
418 EXPECT_FALSE(TestShaderCompile(EXTYTPragma));
419 }
420
421 INSTANTIATE_TEST_SUITE_P(IncorrectESSL300Shaders,
422 EXTYUVTargetCompileFailureTest,
423 Combine(Values(SH_GLES3_SPEC),
424 Values(sh::ESSLVersion300),
425 Values(ESSL300_YUVQualifierFailureShader1,
426 ESSL300_YUVQualifierFailureShader2,
427 ESSL300_LocationAndYUVFailureShader,
428 ESSL300_MultipleColorAndYUVOutputsFailureShader1,
429 ESSL300_MultipleColorAndYUVOutputsFailureShader2,
430 ESSL300_DepthAndYUVOutputsFailureShader,
431 ESSL300_MultipleYUVOutputsFailureShader,
432 ESSL300_YuvCscStandardEXTConstructFailureShader1,
433 ESSL300_YuvCscStandardEXTConstructFailureShader2,
434 ESSL300_YuvCscStandardEXTConversionFailureShader1,
435 ESSL300_YuvCscStandardEXTConversionFailureShader2,
436 ESSL300_YuvCscStandardEXTConversionFailureShader3,
437 ESSL300_YuvCscStandardEXTConversionFailureShader4,
438 ESSL300_YuvCscStandardEXTConversionFailureShader5,
439 ESSL300_YuvCscStandardEXTQualifiersFailureShader1,
440 ESSL300_YuvCscStandardEXTQualifiersFailureShader2,
441 ESSL300_YuvCscStandardEXTQualifiersFailureShader3)));
442
443 class EXTYUVNotEnabledTest : public EXTYUVTargetTest
444 {};
445
TEST_P(EXTYUVNotEnabledTest,CanOverloadConversions)446 TEST_P(EXTYUVNotEnabledTest, CanOverloadConversions)
447 {
448 // Expect compile success with a shader that overloads functions in the EXT_YUV_target
449 // extension.
450 mResources.EXT_YUV_target = 0;
451 InitializeCompiler();
452 EXPECT_TRUE(TestShaderCompile(""));
453 }
454
455 INSTANTIATE_TEST_SUITE_P(CoreESSL300Shaders,
456 EXTYUVNotEnabledTest,
457 Combine(Values(SH_GLES3_SPEC),
458 Values(sh::ESSLVersion300),
459 Values(ESSL300_OverloadRgb2Yuv, ESSL300_OverloadYuv2Rgb)));
460
461 } // namespace
462