xref: /aosp_15_r20/external/angle/src/tests/compiler_tests/EXT_blend_func_extended_test.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2015 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_blend_func_extended.cpp:
7 //   Test for EXT_blend_func_extended_test
8 //
9 
10 #include "tests/test_utils/ShaderExtensionTest.h"
11 
12 namespace
13 {
14 const char EXTBFEPragma[] = "#extension GL_EXT_blend_func_extended : require\n";
15 
16 const char ESSL100_SimpleShader1[] =
17     "precision mediump float;\n"
18     "void main() { \n"
19     "    gl_FragColor = vec4(1.0);\n"
20     "    gl_SecondaryFragColorEXT = vec4(gl_MaxDualSourceDrawBuffersEXT / 10);\n"
21     "}\n";
22 
23 // Shader that tests only the access to gl_MaxDualSourceDrawBuffersEXT.
24 const char ESSL100_MaxDualSourceAccessShader[] =
25     "precision mediump float;\n"
26     "void main() { gl_FragColor = vec4(gl_MaxDualSourceDrawBuffersEXT / 10); }\n";
27 
28 // Shader that writes to SecondaryFragData.
29 const char ESSL100_FragDataShader[] =
30     "#extension GL_EXT_draw_buffers : require\n"
31     "precision mediump float;\n"
32     "void main() {\n"
33     "    gl_FragData[gl_MaxDrawBuffers - 1] = vec4(1.0);\n"
34     "    gl_SecondaryFragDataEXT[gl_MaxDualSourceDrawBuffersEXT - 1] = vec4(0.1);\n"
35     "}\n";
36 
37 // Shader that writes to SecondaryFragColor and SecondaryFragData does not compile.
38 const char ESSL100_ColorAndDataWriteFailureShader1[] =
39     "precision mediump float;\n"
40     "void main() {\n"
41     "    gl_SecondaryFragColorEXT = vec4(1.0);\n"
42     "    gl_SecondaryFragDataEXT[gl_MaxDualSourceDrawBuffersEXT] = vec4(0.1);\n"
43     "}\n";
44 
45 // Shader that writes to FragColor and SecondaryFragData does not compile.
46 const char ESSL100_ColorAndDataWriteFailureShader2[] =
47     "precision mediump float;\n"
48     "void main() {\n"
49     "    gl_FragColor = vec4(1.0);\n"
50     "    gl_SecondaryFragDataEXT[gl_MaxDualSourceDrawBuffersEXT] = vec4(0.1);\n"
51     "}\n";
52 
53 // Shader that writes to FragData and SecondaryFragColor.
54 const char ESSL100_ColorAndDataWriteFailureShader3[] =
55     "#extension GL_EXT_draw_buffers : require\n"
56     "precision mediump float;\n"
57     "void main() {\n"
58     "    gl_SecondaryFragColorEXT = vec4(1.0);\n"
59     "    gl_FragData[gl_MaxDrawBuffers] = vec4(0.1);\n"
60     "}\n";
61 
62 // Dynamic indexing of SecondaryFragData is not allowed in WebGL 2.0.
63 const char ESSL100_IndexSecondaryFragDataWithNonConstantShader[] =
64     "precision mediump float;\n"
65     "void main() {\n"
66     "    for (int i = 0; i < 2; ++i) {\n"
67     "        gl_SecondaryFragDataEXT[true ? 0 : i] = vec4(0.0);\n"
68     "    }\n"
69     "}\n";
70 
71 // In GLSL version 300 es, the gl_MaxDualSourceDrawBuffersEXT is available.
72 const char ESSL300_MaxDualSourceAccessShader[] =
73     "precision mediump float;\n"
74     "layout(location = 0) out mediump vec4 fragColor;"
75     "void main() {\n"
76     "    fragColor = vec4(gl_MaxDualSourceDrawBuffersEXT / 10);\n"
77     "}\n";
78 
79 // In ES 3.0, the locations can be assigned through the API with glBindFragDataLocationIndexedEXT.
80 // It's fine to have a mix of specified and unspecified locations.
81 const char ESSL300_LocationAndUnspecifiedOutputShader[] =
82     "precision mediump float;\n"
83     "layout(location = 0) out mediump vec4 fragColor;"
84     "out mediump vec4 secondaryFragColor;"
85     "void main() {\n"
86     "    fragColor = vec4(1.0);\n"
87     "    secondaryFragColor = vec4(1.0);\n"
88     "}\n";
89 
90 // It's also fine to leave locations completely unspecified.
91 const char ESSL300_TwoUnspecifiedLocationOutputsShader[] =
92     "precision mediump float;\n"
93     "out mediump vec4 fragColor;"
94     "out mediump vec4 secondaryFragColor;"
95     "void main() {\n"
96     "    fragColor = vec4(1.0);\n"
97     "    secondaryFragColor = vec4(1.0);\n"
98     "}\n";
99 
100 // Shader that is specifies two outputs with the same location but different indexes is valid.
101 const char ESSL300_LocationIndexShader[] =
102     R"(precision mediump float;
103 layout(location = 0) out mediump vec4 fragColor;
104 layout(location = 0, index = 1) out mediump vec4 secondaryFragColor;
105 void main() {
106     fragColor = vec4(1);
107     secondaryFragColor = vec4(1);
108 })";
109 
110 // Shader that specifies index layout qualifier but not location fails to compile.
111 const char ESSL300_LocationIndexFailureShader[] =
112     R"(precision mediump float;
113 layout(index = 0) out vec4 fragColor;
114 void main() {
115     fragColor = vec4(1.0);
116 })";
117 
118 // Shader that specifies index layout qualifier multiple times fails to compile.
119 const char ESSL300_DoubleIndexFailureShader[] =
120     R"(precision mediump float;
121 layout(index = 0, location = 0, index = 1) out vec4 fragColor;
122 void main() {
123     fragColor = vec4(1.0);
124 })";
125 
126 // Shader that specifies an output with out-of-bounds location
127 // for index 0 when another output uses index 1 is invalid.
128 const char ESSL300_Index0OutOfBoundsFailureShader[] =
129     R"(precision mediump float;
130 layout(location = 1, index = 0) out mediump vec4 fragColor;
131 layout(location = 0, index = 1) out mediump vec4 secondaryFragColor;
132 void main() {
133     fragColor = vec4(1);
134     secondaryFragColor = vec4(1);
135 })";
136 
137 // Shader that specifies an output with out-of-bounds location for index 1 is invalid.
138 const char ESSL300_Index1OutOfBoundsFailureShader[] =
139     R"(precision mediump float;
140 layout(location = 1, index = 1) out mediump vec4 secondaryFragColor;
141 void main() {
142     secondaryFragColor = vec4(1);
143 })";
144 
145 // Shader that specifies two outputs with the same location
146 // but different indices and different base types is invalid.
147 const char ESSL300_IndexTypeMismatchFailureShader[] =
148     R"(precision mediump float;
149 layout(location = 0, index = 0) out mediump vec4 fragColor;
150 layout(location = 0, index = 1) out mediump ivec4 secondaryFragColor;
151 void main() {
152     fragColor = vec4(1);
153     secondaryFragColor = ivec4(1);
154 })";
155 
156 // Global index layout qualifier fails.
157 const char ESSL300_GlobalIndexFailureShader[] =
158     R"(precision mediump float;
159 layout(index = 0);
160 out vec4 fragColor;
161 void main() {
162     fragColor = vec4(1.0);
163 })";
164 
165 // Index layout qualifier on a non-output variable fails.
166 const char ESSL300_IndexOnUniformVariableFailureShader[] =
167     R"(precision mediump float;
168 layout(index = 0) uniform vec4 u;
169 out vec4 fragColor;
170 void main() {
171     fragColor = u;
172 })";
173 
174 // Index layout qualifier on a struct fails.
175 const char ESSL300_IndexOnStructFailureShader[] =
176     R"(precision mediump float;
177 layout(index = 0) struct S {
178     vec4 field;
179 };
180 out vec4 fragColor;
181 void main() {
182     fragColor = vec4(1.0);
183 })";
184 
185 // Index layout qualifier on a struct member fails.
186 const char ESSL300_IndexOnStructFieldFailureShader[] =
187     R"(precision mediump float;
188 struct S {
189     layout(index = 0) vec4 field;
190 };
191 out mediump vec4 fragColor;
192 void main() {
193     fragColor = vec4(1.0);
194 })";
195 
196 class EXTBlendFuncExtendedTest : public sh::ShaderExtensionTest
197 {
198   protected:
SetUp()199     void SetUp() override
200     {
201         sh::ShaderExtensionTest::SetUp();
202         // EXT_draw_buffers is used in some of the shaders for test purposes.
203         mResources.EXT_draw_buffers = 1;
204         mResources.NV_draw_buffers  = 2;
205     }
206 };
207 
208 // Extension flag is required to compile properly. Expect failure when it is
209 // not present.
TEST_P(EXTBlendFuncExtendedTest,CompileFailsWithoutExtension)210 TEST_P(EXTBlendFuncExtendedTest, CompileFailsWithoutExtension)
211 {
212     mResources.EXT_blend_func_extended = 0;
213     InitializeCompiler();
214     EXPECT_FALSE(TestShaderCompile(EXTBFEPragma));
215 }
216 
217 // Extension directive is required to compile properly. Expect failure when
218 // it is not present.
TEST_P(EXTBlendFuncExtendedTest,CompileFailsWithExtensionWithoutPragma)219 TEST_P(EXTBlendFuncExtendedTest, CompileFailsWithExtensionWithoutPragma)
220 {
221     mResources.EXT_blend_func_extended  = 1;
222     mResources.MaxDualSourceDrawBuffers = 1;
223     InitializeCompiler();
224     EXPECT_FALSE(TestShaderCompile(""));
225 }
226 
227 // With extension flag and extension directive, compiling succeeds.
228 // Also test that the extension directive state is reset correctly.
TEST_P(EXTBlendFuncExtendedTest,CompileSucceedsWithExtensionAndPragma)229 TEST_P(EXTBlendFuncExtendedTest, CompileSucceedsWithExtensionAndPragma)
230 {
231     mResources.EXT_blend_func_extended  = 1;
232     mResources.MaxDualSourceDrawBuffers = 1;
233     InitializeCompiler();
234     EXPECT_TRUE(TestShaderCompile(EXTBFEPragma));
235     // Test reset functionality.
236     EXPECT_FALSE(TestShaderCompile(""));
237     EXPECT_TRUE(TestShaderCompile(EXTBFEPragma));
238 }
239 
240 // The SL #version 100 shaders that are correct work similarly
241 // in both GL2 and GL3, with and without the version string.
242 INSTANTIATE_TEST_SUITE_P(CorrectESSL100Shaders,
243                          EXTBlendFuncExtendedTest,
244                          Combine(Values(SH_GLES2_SPEC, SH_GLES3_SPEC),
245                                  Values("", sh::ESSLVersion100),
246                                  Values(ESSL100_SimpleShader1,
247                                         ESSL100_MaxDualSourceAccessShader,
248                                         ESSL100_FragDataShader)));
249 
250 INSTANTIATE_TEST_SUITE_P(CorrectESSL300Shaders,
251                          EXTBlendFuncExtendedTest,
252                          Combine(Values(SH_GLES3_SPEC),
253                                  Values(sh::ESSLVersion300),
254                                  Values(ESSL300_MaxDualSourceAccessShader,
255                                         ESSL300_LocationAndUnspecifiedOutputShader,
256                                         ESSL300_TwoUnspecifiedLocationOutputsShader,
257                                         ESSL300_LocationIndexShader)));
258 
259 class EXTBlendFuncExtendedCompileFailureTest : public EXTBlendFuncExtendedTest
260 {};
261 
TEST_P(EXTBlendFuncExtendedCompileFailureTest,CompileFails)262 TEST_P(EXTBlendFuncExtendedCompileFailureTest, CompileFails)
263 {
264     // Expect compile failure due to shader error, with shader having correct pragma.
265     mResources.EXT_blend_func_extended  = 1;
266     mResources.MaxDualSourceDrawBuffers = 1;
267     InitializeCompiler();
268     EXPECT_FALSE(TestShaderCompile(EXTBFEPragma));
269 }
270 
271 // Incorrect #version 100 shaders fail.
272 INSTANTIATE_TEST_SUITE_P(IncorrectESSL100Shaders,
273                          EXTBlendFuncExtendedCompileFailureTest,
274                          Combine(Values(SH_GLES2_SPEC),
275                                  Values(sh::ESSLVersion100),
276                                  Values(ESSL100_ColorAndDataWriteFailureShader1,
277                                         ESSL100_ColorAndDataWriteFailureShader2,
278                                         ESSL100_ColorAndDataWriteFailureShader3)));
279 
280 // Correct #version 100 shaders that are incorrect in WebGL 2.0.
281 INSTANTIATE_TEST_SUITE_P(IncorrectESSL100ShadersWebGL2,
282                          EXTBlendFuncExtendedCompileFailureTest,
283                          Combine(Values(SH_WEBGL2_SPEC),
284                                  Values(sh::ESSLVersion100),
285                                  Values(ESSL100_IndexSecondaryFragDataWithNonConstantShader)));
286 
287 // Correct #version 300 es shaders fail in GLES2 context, regardless of version string.
288 INSTANTIATE_TEST_SUITE_P(CorrectESSL300Shaders,
289                          EXTBlendFuncExtendedCompileFailureTest,
290                          Combine(Values(SH_GLES2_SPEC),
291                                  Values("", sh::ESSLVersion100, sh::ESSLVersion300),
292                                  Values(ESSL300_LocationAndUnspecifiedOutputShader,
293                                         ESSL300_TwoUnspecifiedLocationOutputsShader)));
294 
295 // Correct #version 100 shaders fail when used with #version 300 es.
296 INSTANTIATE_TEST_SUITE_P(CorrectESSL100Shaders,
297                          EXTBlendFuncExtendedCompileFailureTest,
298                          Combine(Values(SH_GLES3_SPEC),
299                                  Values(sh::ESSLVersion300),
300                                  Values(ESSL100_SimpleShader1, ESSL100_FragDataShader)));
301 
302 // Incorrect #version 300 es shaders always fail.
303 INSTANTIATE_TEST_SUITE_P(IncorrectESSL300Shaders,
304                          EXTBlendFuncExtendedCompileFailureTest,
305                          Combine(Values(SH_GLES3_1_SPEC),
306                                  Values(sh::ESSLVersion300, sh::ESSLVersion310),
307                                  Values(ESSL300_LocationIndexFailureShader,
308                                         ESSL300_DoubleIndexFailureShader,
309                                         ESSL300_Index0OutOfBoundsFailureShader,
310                                         ESSL300_Index1OutOfBoundsFailureShader,
311                                         ESSL300_IndexTypeMismatchFailureShader,
312                                         ESSL300_GlobalIndexFailureShader,
313                                         ESSL300_IndexOnUniformVariableFailureShader,
314                                         ESSL300_IndexOnStructFailureShader,
315                                         ESSL300_IndexOnStructFieldFailureShader)));
316 
317 }  // namespace
318