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