1/*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.1 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2016 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Negative Shader Directive Tests
22 *//*--------------------------------------------------------------------*/
23
24#include "es31fNegativeShaderDirectiveTests.hpp"
25
26#include "gluShaderProgram.hpp"
27
28namespace deqp
29{
30namespace gles31
31{
32namespace Functional
33{
34namespace NegativeTestShared
35{
36namespace
37{
38
39enum ExpectResult
40{
41	EXPECT_RESULT_PASS = 0,
42	EXPECT_RESULT_FAIL,
43
44	EXPECT_RESULT_LAST
45};
46
47void verifyProgram(NegativeTestContext& ctx, glu::ProgramSources sources, ExpectResult expect)
48{
49	DE_ASSERT(expect >= EXPECT_RESULT_PASS && expect < EXPECT_RESULT_LAST);
50
51	tcu::TestLog& 				log 		= ctx.getLog();
52	const glu::ShaderProgram 	program		(ctx.getRenderContext(), sources);
53	bool						testFailed	= false;
54	std::string					message;
55
56	log << program;
57
58	if (expect == EXPECT_RESULT_PASS)
59	{
60		testFailed = !program.getProgramInfo().linkOk;
61		message = "Program did not link.";
62	}
63	else
64	{
65		testFailed = program.getProgramInfo().linkOk;
66		message = "Program was not expected to link.";
67	}
68
69	if (testFailed)
70	{
71		log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
72		ctx.fail(message);
73	}
74}
75
76void verifyShader(NegativeTestContext& ctx, glu::ShaderType shaderType, std::string shaderSource, ExpectResult expect)
77{
78	DE_ASSERT(expect >= EXPECT_RESULT_PASS && expect < EXPECT_RESULT_LAST);
79
80	tcu::TestLog& 		log			= ctx.getLog();
81	bool				testFailed	= false;
82	const char* const	source		= shaderSource.c_str();
83	const int			length		= (int) shaderSource.size();
84	glu::Shader			shader		(ctx.getRenderContext(), shaderType);
85	std::string			message;
86
87	shader.setSources(1, &source, &length);
88	shader.compile();
89
90	log << shader;
91
92	if (expect == EXPECT_RESULT_PASS)
93	{
94		testFailed = !shader.getCompileStatus();
95		message = "Shader did not compile.";
96	}
97	else
98	{
99		testFailed = shader.getCompileStatus();
100		message = "Shader was not expected to compile.";
101	}
102
103	if (testFailed)
104	{
105		log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
106		ctx.fail(message);
107	}
108}
109
110void primitive_bounding_box (NegativeTestContext& ctx)
111{
112	ctx.beginSection("GL_EXT_primitive_bounding_box features require enabling the extension in 310 es shaders.");
113	{
114		std::ostringstream source;
115		source <<	"#version 310 es\n"
116					"void main()\n"
117					"{\n"
118					"	gl_BoundingBoxEXT[0] = vec4(0.0, 0.0, 0.0, 0.0);\n"
119					"	gl_BoundingBoxEXT[1] = vec4(1.0, 1.0, 1.0, 1.0);\n"
120					"}\n";
121		verifyShader(ctx, glu::SHADERTYPE_TESSELLATION_CONTROL, source.str(), EXPECT_RESULT_FAIL);
122	}
123	ctx.endSection();
124
125	if (contextSupports(ctx.getRenderContext().getType() , glu::ApiType::es(3, 2)))
126	{
127		ctx.beginSection("gl_BoundingBox does not require the OES/EXT suffix in a 320 es shader.");
128		const std::string source =	"#version 320 es\n"
129									"layout(vertices = 3) out;\n"
130									"void main()\n"
131									"{\n"
132									"	gl_BoundingBox[0] = vec4(0.0, 0.0, 0.0, 0.0);\n"
133									"	gl_BoundingBox[1] = vec4(0.0, 0.0, 0.0, 0.0);\n"
134									"}\n";
135		verifyShader(ctx, glu::SHADERTYPE_TESSELLATION_CONTROL, source, EXPECT_RESULT_PASS);
136		ctx.endSection();
137	}
138}
139
140void blend_equation_advanced (NegativeTestContext& ctx)
141{
142	static const char* const s_qualifiers[] =
143	{
144		"blend_support_multiply",
145		"blend_support_screen",
146		"blend_support_overlay",
147		"blend_support_darken",
148		"blend_support_lighten",
149		"blend_support_colordodge",
150		"blend_support_colorburn",
151		"blend_support_hardlight",
152		"blend_support_softlight",
153		"blend_support_difference",
154		"blend_support_exclusion",
155		"blend_support_hsl_hue",
156		"blend_support_hsl_saturation",
157		"blend_support_hsl_color",
158		"blend_support_hsl_luminosity",
159	};
160
161	ctx.beginSection("GL_KHR_blend_equation_advanced features require enabling the extension in 310 es shaders.");
162	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_qualifiers); ++ndx)
163	{
164		std::ostringstream source;
165		source <<	"#version 310 es\n"
166					"layout(" << s_qualifiers[ndx] << ") out;\n"
167					"void main()\n"
168					"{\n"
169					"}\n";
170		verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, source.str(), EXPECT_RESULT_FAIL);
171	}
172	ctx.endSection();
173}
174
175void sample_variables (NegativeTestContext& ctx)
176{
177	TCU_CHECK_AND_THROW(NotSupportedError, contextSupports(ctx.getRenderContext().getType() , glu::ApiType::es(3, 2)), "Test requires a context version 3.2 or higher.");
178
179	static const char* const s_tests[] =
180	{
181		"int sampleId = gl_SampleID;",
182		"vec2 samplePos = gl_SamplePosition;",
183		"int sampleMaskIn0 = gl_SampleMaskIn[0];",
184		"int sampleMask0 = gl_SampleMask[0];",
185		"int numSamples = gl_NumSamples;",
186	};
187
188	ctx.beginSection("GL_OES_sample_variables features require enabling the extension in 310 es shaders.");
189	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_tests); ++ndx)
190	{
191		std::ostringstream source;
192		source <<	"#version 310 es\n"
193					"precision mediump float;\n"
194					"void main()\n"
195					"{\n"
196					"	" << s_tests[ndx] << "\n"
197					"}\n";
198		verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, source.str(), EXPECT_RESULT_FAIL);
199	}
200	ctx.endSection();
201}
202
203void shader_image_atomic (NegativeTestContext& ctx)
204{
205	static const char* const s_tests[] =
206	{
207		"imageAtomicAdd(u_image, ivec2(1, 1), 1u);",
208		"imageAtomicMin(u_image, ivec2(1, 1), 1u);",
209		"imageAtomicMax(u_image, ivec2(1, 1), 1u);",
210		"imageAtomicAnd(u_image, ivec2(1, 1), 1u);",
211		"imageAtomicOr(u_image, ivec2(1, 1), 1u);",
212		"imageAtomicXor(u_image, ivec2(1, 1), 1u);",
213		"imageAtomicExchange(u_image, ivec2(1, 1), 1u);",
214		"imageAtomicCompSwap(u_image, ivec2(1, 1), 1u, 1u);",
215	};
216
217	ctx.beginSection("GL_OES_shader_image_atomic features require enabling the extension in 310 es shaders.");
218	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_tests); ++ndx)
219	{
220		std::ostringstream source;
221		source <<	"#version 310 es\n"
222					"layout(binding=0, r32ui) coherent uniform highp uimage2D u_image;\n"
223					"precision mediump float;\n"
224					"void main()\n"
225					"{\n"
226					"	" << s_tests[ndx] << "\n"
227					"}\n";
228		verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, source.str(), EXPECT_RESULT_FAIL);
229	}
230	ctx.endSection();
231}
232
233void shader_multisample_interpolation (NegativeTestContext& ctx)
234{
235	static const char* const s_sampleTests[] =
236	{
237		"sample in highp float v_var;",
238		"sample out highp float v_var;"
239	};
240
241	static const char* const s_interpolateAtTests[] =
242	{
243		"interpolateAtCentroid(interpolant);",
244		"interpolateAtSample(interpolant, 1);",
245		"interpolateAtOffset(interpolant, vec2(1.0, 0.0));"
246	};
247
248	ctx.beginSection("GL_OES_shader_multisample_interpolation features require enabling the extension in 310 es shaders.");
249	ctx.beginSection("Test sample in/out qualifiers.");
250	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_sampleTests); ++ndx)
251	{
252		std::ostringstream source;
253		source <<	"#version 310 es\n"
254					"	" << s_sampleTests[ndx] << "\n"
255					"precision mediump float;\n"
256					"void main()\n"
257					"{\n"
258					"}\n";
259		verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, source.str(), EXPECT_RESULT_FAIL);
260	}
261	ctx.endSection();
262
263	ctx.beginSection("Test interpolateAt* functions.");
264	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_sampleTests); ++ndx)
265	{
266		std::ostringstream source;
267		source <<	"#version 310 es\n"
268					"in mediump float interpolant;\n"
269					"precision mediump float;\n"
270					"void main()\n"
271					"{\n"
272					"	" << s_interpolateAtTests[ndx] << "\n"
273					"}\n";
274		verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, source.str(), EXPECT_RESULT_FAIL);
275	}
276	ctx.endSection();
277	ctx.endSection();
278}
279
280void texture_storage_multisample_2d_array (NegativeTestContext& ctx)
281{
282	static const char* const s_samplerTypeTests[] =
283	{
284		"uniform mediump sampler2DMSArray u_sampler;",
285		"uniform mediump isampler2DMSArray u_sampler;",
286		"uniform mediump usampler2DMSArray u_sampler;",
287	};
288
289	ctx.beginSection("GL_OES_texture_storage_multisample_2d_array features require enabling the extension in 310 es shaders.");
290	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_samplerTypeTests); ++ndx)
291	{
292		std::ostringstream source;
293		source <<	"#version 310 es\n"
294					"	" << s_samplerTypeTests[ndx] << "\n"
295					"precision mediump float;\n"
296					"void main()\n"
297					"{\n"
298					"}\n";
299		verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, source.str(), EXPECT_RESULT_FAIL);
300	}
301	ctx.endSection();
302}
303
304void geometry_shader (NegativeTestContext& ctx)
305{
306	const std::string	simpleVtxFrag	=	"#version 310 es\n"
307											"void main()\n"
308											"{\n"
309											"}\n";
310	const std::string	geometry		=	"#version 310 es\n"
311											"layout(points, invocations = 1) in;\n"
312											"layout(points, max_vertices = 3) out;\n"
313											"precision mediump float;\n"
314											"void main()\n"
315											"{\n"
316											"	EmitVertex();\n"
317											"	EndPrimitive();\n"
318											"}\n";
319	ctx.beginSection("GL_EXT_geometry_shader features require enabling the extension in 310 es shaders.");
320	verifyProgram(ctx, glu::ProgramSources() << glu::VertexSource(simpleVtxFrag) << glu::GeometrySource(geometry) << glu::FragmentSource(simpleVtxFrag), EXPECT_RESULT_FAIL);
321	ctx.endSection();
322}
323
324void gpu_shader_5 (NegativeTestContext& ctx)
325{
326	ctx.beginSection("GL_EXT_gpu_shader5 features require enabling the extension in 310 es shaders.");
327	ctx.beginSection("Testing the precise qualifier.");
328	{
329		std::ostringstream source;
330		source <<	"#version 310 es\n"
331					"void main()\n"
332					"{\n"
333					"	int low = 0;\n"
334					"	int high = 10;\n"
335					"	precise int middle = low + ((high - low) / 2);\n"
336					"}\n";
337		verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, source.str(), EXPECT_RESULT_FAIL);
338	}
339	ctx.endSection();
340
341	ctx.beginSection("Testing fused multiply-add.");
342	{
343		std::ostringstream source;
344		source <<	"#version 310 es\n"
345					"in mediump float v_var;"
346					"void main()\n"
347					"{\n"
348					"	float fmaResult = fma(v_var, v_var, v_var);"
349					"}\n";
350		verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, source.str(), EXPECT_RESULT_FAIL);
351	}
352	ctx.endSection();
353
354	ctx.beginSection("Testing textureGatherOffsets.");
355	{
356		std::ostringstream source;
357		source <<	"#version 310 es\n"
358					"uniform mediump sampler2D u_tex;\n"
359					"void main()\n"
360					"{\n"
361					"	highp vec2 coords = vec2(0.0, 1.0);\n"
362					"	const ivec2 offsets[4] = ivec2[](ivec2(0,0), ivec2(1, 0), ivec2(0, 1), ivec2(1, 1));\n"
363					"	textureGatherOffsets(u_tex, coords, offsets);\n"
364					"}\n";
365		verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, source.str(), EXPECT_RESULT_FAIL);
366	}
367	ctx.endSection();
368
369	ctx.endSection();
370}
371
372void shader_io_blocks (NegativeTestContext& ctx)
373{
374	ctx.beginSection("GL_EXT_shader_io_blocks features require enabling the extension in 310 es shaders.");
375	{
376		std::ostringstream source;
377		source <<	"#version 310 es\n"
378					"in Data\n"
379					"{\n"
380					"	mediump vec3 a;\n"
381					"} data;\n"
382					"void main()\n"
383					"{\n"
384					"}\n";
385		verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, source.str(), EXPECT_RESULT_FAIL);
386	}
387	ctx.endSection();
388}
389
390void tessellation_shader (NegativeTestContext& ctx)
391{
392	const std::string	simpleVtxFrag	=	"#version 310 es\n"
393											"void main()\n"
394											"{\n"
395											"}\n";
396	const std::string	tessControl		=	"#version 310 es\n"
397											"layout(vertices = 3) out;\n"
398											"void main()\n"
399											"{\n"
400											"}\n";
401	const std::string	tessEvaluation	=	"#version 310 es\n"
402											"layout(triangles, equal_spacing, cw) in;\n"
403											"void main()\n"
404											"{\n"
405											"}\n";
406	ctx.beginSection("GL_EXT_tessellation_shader features require enabling the extension in 310 es shaders.");
407	glu::ProgramSources sources;
408	sources << glu::VertexSource(simpleVtxFrag)
409			<< glu::TessellationControlSource(tessControl)
410			<< glu::TessellationEvaluationSource(tessEvaluation)
411			<< glu::FragmentSource(simpleVtxFrag);
412	verifyProgram(ctx, sources, EXPECT_RESULT_FAIL);
413	ctx.endSection();
414}
415
416void texture_buffer (NegativeTestContext& ctx)
417{
418	static const char* const s_samplerBufferTypes[] =
419	{
420		"uniform mediump samplerBuffer",
421	    "uniform mediump isamplerBuffer",
422	    "uniform mediump usamplerBuffer",
423	    "layout(rgba32f) uniform mediump writeonly imageBuffer",
424	    "layout(rgba32i) uniform mediump writeonly iimageBuffer",
425	    "layout(rgba32ui) uniform mediump writeonly uimageBuffer"
426	};
427
428	ctx.beginSection("GL_EXT_texture_buffer features require enabling the extension in 310 es shaders.");
429	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_samplerBufferTypes); ++ndx)
430	{
431		std::ostringstream source;
432		source <<	"#version 310 es\n"
433					"" << s_samplerBufferTypes[ndx] << " u_buffer;\n"
434					"void main()\n"
435					"{\n"
436					"}\n";
437		verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, source.str(), EXPECT_RESULT_FAIL);
438	}
439	ctx.endSection();
440}
441
442
443void texture_cube_map_array (NegativeTestContext& ctx)
444{
445	static const char* const s_samplerCubeArrayTypes[] =
446	{
447	    "uniform mediump samplerCubeArray",
448	    "uniform mediump isamplerCubeArray",
449	    "uniform mediump usamplerCubeArray",
450	    "uniform mediump samplerCubeArrayShadow",
451	    "layout(rgba32f) uniform mediump writeonly imageCubeArray",
452	    "layout(rgba32i) uniform mediump writeonly iimageCubeArray",
453	    "layout(rgba32ui) uniform mediump writeonly uimageCubeArray"
454	};
455
456	ctx.beginSection("GL_EXT_texture_cube_map_array features require enabling the extension in 310 es shaders.");
457	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_samplerCubeArrayTypes); ++ndx)
458	{
459		std::ostringstream source;
460		source <<	"#version 310 es\n"
461					"" << s_samplerCubeArrayTypes[ndx] << " u_cube;\n"
462					"void main()\n"
463					"{\n"
464					"}\n";
465		verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, source.str(), EXPECT_RESULT_FAIL);
466	}
467	ctx.endSection();
468}
469
470} // anonymous
471
472std::vector<FunctionContainer> getNegativeShaderDirectiveTestFunctions (void)
473{
474	const FunctionContainer funcs[] =
475	{
476		{primitive_bounding_box,				"primitive_bounding_box",				"GL_EXT_primitive_bounding_box required in 310 es shaders to use AEP features. Version 320 es shaders do not require suffixes."	},
477		{blend_equation_advanced,				"blend_equation_advanced",				"GL_KHR_blend_equation_advanced is required in 310 es shaders to use AEP features"												},
478		{sample_variables,						"sample_variables",						"GL_OES_sample_variables is required in 310 es shaders to use AEP features"														},
479		{shader_image_atomic,					"shader_image_atomic",					"GL_OES_shader_image_atomic is required in 310 es shaders to use AEP features"													},
480		{shader_multisample_interpolation,		"shader_multisample_interpolation",		"GL_OES_shader_multisample_interpolation is required in 310 es shaders to use AEP features"										},
481		{texture_storage_multisample_2d_array,	"texture_storage_multisample_2d_array",	"GL_OES_texture_storage_multisample_2d_array is required in 310 es shaders to use AEP features"									},
482		{geometry_shader,						"geometry_shader",						"GL_EXT_geometry_shader is required in 310 es shaders to use AEP features"														},
483		{gpu_shader_5,							"gpu_shader_5",							"GL_EXT_gpu_shader5 is required in 310 es shaders to use AEP features"															},
484		{shader_io_blocks,						"shader_io_blocks",						"GL_EXT_shader_io_blocks is required in 310 es shaders to use AEP features"														},
485		{tessellation_shader,					"tessellation_shader",					"GL_EXT_tessellation_shader is required in 310 es shaders to use AEP features"													},
486		{texture_buffer,						"texture_buffer",						"GL_EXT_texture_buffer is required in 310 es shaders to use AEP features"														},
487		{texture_cube_map_array,				"texture_cube_map_array",				"GL_EXT_texture_cube_map_array is required in 310 es shaders to use AEP features"												},
488	};
489
490	return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
491}
492
493} // NegativeTestShared
494} // Functional
495} // gles31
496} // deqp
497