1#ifndef _GL4CSHADERSUBROUTINETESTS_HPP
2#define _GL4CSHADERSUBROUTINETESTS_HPP
3/*-------------------------------------------------------------------------
4 * OpenGL Conformance Test Suite
5 * -----------------------------
6 *
7 * Copyright (c) 2014-2016 The Khronos Group Inc.
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 *      http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 */ /*!
22 * \file
23 * \brief
24 */ /*-------------------------------------------------------------------*/
25
26/**
27 * \file  gl4cShaderSubroutineTests.hpp
28 * \brief Declares test classes for "Shader Subroutine" functionality.
29 */ /*-------------------------------------------------------------------*/
30
31#include "glcTestCase.hpp"
32#include "glwDefs.hpp"
33#include <queue>
34
35#include "tcuTestLog.hpp"
36
37namespace gl4cts
38{
39namespace ShaderSubroutine
40{
41class Utils
42{
43public:
44	/* Public type definitions */
45
46	struct buffer
47	{
48		buffer(deqp::Context& context);
49		~buffer();
50
51		void bindRange(glw::GLenum target, glw::GLuint index, glw::GLintptr offset, glw::GLsizeiptr size);
52
53		void generate();
54
55		void update(glw::GLenum target, glw::GLsizeiptr size, glw::GLvoid* data, glw::GLenum usage);
56
57		glw::GLuint m_id;
58
59	private:
60		deqp::Context& m_context;
61	};
62
63	struct framebuffer
64	{
65		framebuffer(deqp::Context& context);
66		~framebuffer();
67
68		void attachTexture(glw::GLenum attachment, glw::GLuint texture_id, glw::GLuint width, glw::GLuint height);
69
70		void bind();
71		void clear(glw::GLenum mask);
72
73		void clearColor(glw::GLfloat red, glw::GLfloat green, glw::GLfloat blue, glw::GLfloat alpha);
74		void generate();
75
76		glw::GLuint m_id;
77
78	private:
79		deqp::Context& m_context;
80	};
81
82	/** Store information about program object
83	 *
84	 **/
85	struct program
86	{
87		program(deqp::Context& context);
88		~program();
89
90		void build(const glw::GLchar* compute_shader_code, const glw::GLchar* fragment_shader_code,
91				   const glw::GLchar* geometry_shader_code, const glw::GLchar* tesselation_control_shader_code,
92				   const glw::GLchar* tesselation_evaluation_shader_code, const glw::GLchar* vertex_shader_code,
93				   const glw::GLchar* const* varying_names, glw::GLuint n_varying_names, bool is_separable = false);
94
95		void compile(glw::GLuint shader_id, const glw::GLchar* shader_code) const;
96
97		bool isProgramBinarySupported() const;
98
99		void createFromBinary(const std::vector<glw::GLubyte>& binary, glw::GLenum binary_format);
100
101		void getBinary(std::vector<glw::GLubyte>& binary, glw::GLenum& binary_format) const;
102
103		glw::GLuint getSubroutineIndex(const glw::GLchar* subroutine_name, glw::GLenum shader_stage) const;
104
105		glw::GLint getSubroutineUniformLocation(const glw::GLchar* uniform_name, glw::GLenum shader_stage) const;
106
107		glw::GLint getUniformLocation(const glw::GLchar* uniform_name) const;
108		void link() const;
109		void remove();
110		void use() const;
111
112		static const glw::GLenum ARB_COMPUTE_SHADER;
113
114		glw::GLuint m_compute_shader_id;
115		glw::GLuint m_fragment_shader_id;
116		glw::GLuint m_geometry_shader_id;
117		glw::GLuint m_program_object_id;
118		glw::GLuint m_tesselation_control_shader_id;
119		glw::GLuint m_tesselation_evaluation_shader_id;
120		glw::GLuint m_vertex_shader_id;
121
122	private:
123		deqp::Context& m_context;
124	};
125
126	struct texture
127	{
128		texture(deqp::Context& context);
129		~texture();
130
131		void bind();
132
133		void create(glw::GLuint width, glw::GLuint height, glw::GLenum internal_format);
134
135		void get(glw::GLenum format, glw::GLenum type, glw::GLvoid* out_data);
136
137		void update(glw::GLuint width, glw::GLuint height, glw::GLenum format, glw::GLenum type, glw::GLvoid* data);
138
139		glw::GLuint m_id;
140
141	private:
142		deqp::Context& m_context;
143	};
144
145	struct vertexArray
146	{
147		vertexArray(deqp::Context& Context);
148		~vertexArray();
149
150		void generate();
151		void bind();
152
153		glw::GLuint m_id;
154
155	private:
156		deqp::Context& m_context;
157	};
158
159	/** Storage for 4 element vector of T
160	 *
161	 **/
162	template <typename T>
163	struct vec4
164	{
165		vec4()
166		{
167		}
168
169		vec4(T x, T y, T z, T w) : m_x(x), m_y(y), m_z(z), m_w(w)
170		{
171		}
172
173		bool operator==(const vec4& val) const
174		{
175			bool result = true;
176
177			result = result && compare(m_x, val.m_x);
178			result = result && compare(m_y, val.m_y);
179			result = result && compare(m_z, val.m_z);
180			result = result && compare(m_w, val.m_w);
181
182			return result;
183		}
184
185		void log(tcu::MessageBuilder& message) const
186		{
187			message << "[ " << m_x << ", " << m_y << ", " << m_z << ", " << m_w << " ]";
188		}
189
190		T m_x;
191		T m_y;
192		T m_z;
193		T m_w;
194	};
195
196	enum _shader_stage
197	{
198		SHADER_STAGE_FIRST,
199
200		SHADER_STAGE_VERTEX = SHADER_STAGE_FIRST,
201		SHADER_STAGE_TESSELLATION_CONTROL,
202		SHADER_STAGE_TESSELLATION_EVALUATION,
203		SHADER_STAGE_GEOMETRY,
204		SHADER_STAGE_FRAGMENT,
205
206		SHADER_STAGE_COUNT
207	};
208
209	enum _variable_type
210	{
211		VARIABLE_TYPE_BOOL,
212		VARIABLE_TYPE_BVEC2,
213		VARIABLE_TYPE_BVEC3,
214		VARIABLE_TYPE_BVEC4,
215		VARIABLE_TYPE_DOUBLE,
216		VARIABLE_TYPE_DVEC2,
217		VARIABLE_TYPE_DVEC3,
218		VARIABLE_TYPE_DVEC4,
219		VARIABLE_TYPE_FLOAT,
220		VARIABLE_TYPE_INT,
221		VARIABLE_TYPE_IVEC2,
222		VARIABLE_TYPE_IVEC3,
223		VARIABLE_TYPE_IVEC4,
224		VARIABLE_TYPE_MAT2,
225		VARIABLE_TYPE_MAT2X3,
226		VARIABLE_TYPE_MAT2X4,
227		VARIABLE_TYPE_MAT3,
228		VARIABLE_TYPE_MAT3X2,
229		VARIABLE_TYPE_MAT3X4,
230		VARIABLE_TYPE_MAT4,
231		VARIABLE_TYPE_MAT4X2,
232		VARIABLE_TYPE_MAT4X3,
233		VARIABLE_TYPE_UINT,
234		VARIABLE_TYPE_UVEC2,
235		VARIABLE_TYPE_UVEC3,
236		VARIABLE_TYPE_UVEC4,
237		VARIABLE_TYPE_VEC2,
238		VARIABLE_TYPE_VEC3,
239		VARIABLE_TYPE_VEC4,
240
241		/* Always last */
242		VARIABLE_TYPE_UNKNOWN
243	};
244
245	/* Public methods */
246	static bool buildProgram(const glw::Functions& gl, const std::string& vs_body, const std::string& tc_body,
247							 const std::string& te_body, const std::string& gs_body, const std::string& fs_body,
248							 const glw::GLchar** xfb_varyings, const unsigned int& n_xfb_varyings,
249							 glw::GLuint* out_vs_id, glw::GLuint* out_tc_id, glw::GLuint* out_te_id,
250							 glw::GLuint* out_gs_id, glw::GLuint* out_fs_id, glw::GLuint* out_po_id);
251
252	static _variable_type getBaseVariableType(const _variable_type& variable_type);
253
254	static unsigned int getComponentSizeForVariableType(const _variable_type& variable_type);
255
256	static glw::GLenum getGLenumForShaderStage(const _shader_stage& shader_stage);
257
258	static unsigned int getNumberOfComponentsForVariableType(const _variable_type& variable_type);
259
260	static std::string getShaderStageString(const _shader_stage& shader_stage);
261
262	static std::string getShaderStageStringFromGLEnum(const glw::GLenum shader_stage_glenum);
263
264	static _variable_type getVariableTypeFromProperties(const _variable_type& base_variable_type,
265														const unsigned int&   n_components);
266
267	static std::string getVariableTypeGLSLString(const _variable_type& variable_type);
268
269	static const glw::GLchar* programInterfaceToStr(glw::GLenum program_interface);
270	static const glw::GLchar* pnameToStr(glw::GLenum pname);
271
272private:
273	/* Private methods */
274	template <typename T>
275	static bool compare(const T& left, const T& right)
276	{
277		return left == right;
278	}
279
280	static bool compare(const glw::GLfloat& left, const glw::GLfloat& right);
281};
282
283/** Verify that Get* commands accept MAX_SUBROUTINES and
284 *  MAX_SUBROUTINE_UNIFORM_LOCATIONS tokens and that the returned values
285 *  are not lower than required by the specification.
286 **/
287class APITest1 : public deqp::TestCase
288{
289public:
290	/* Public methods */
291	APITest1(deqp::Context& context);
292
293	virtual tcu::TestNode::IterateResult iterate();
294
295private:
296	/* Private type definitions */
297	/* Private methods */
298
299	/* Private fields */
300	bool m_has_test_passed;
301};
302
303/** Check if <bufsize> and <length> parameters behave correctly in
304 *  GetActiveSubroutineName and GetActiveSubroutineUniformName functions.
305 **/
306class APITest2 : public deqp::TestCase
307{
308public:
309	/* Public methods */
310	APITest2(deqp::Context& context);
311
312	virtual void						 deinit();
313	virtual tcu::TestNode::IterateResult iterate();
314
315private:
316	/* Private type definitions */
317
318	/* Private methods */
319	std::string getVertexShaderBody();
320	void		initTest();
321	void		verifyGLGetActiveSubroutineNameFunctionality();
322	void		verifyGLGetActiveSubroutineUniformNameFunctionality();
323
324	/* Private fields */
325	glw::GLchar* m_buffer;
326	bool		 m_has_test_passed;
327	glw::GLuint  m_po_id;
328	const char*  m_subroutine_name1;
329	const char*  m_subroutine_name2;
330	const char*  m_subroutine_uniform_name;
331	glw::GLuint  m_vs_id;
332};
333
334/** * Create program with 2 subroutines taking one parameter and 1 subroutine
335 *    uniform. Select the first subroutine and make a draw. Verify the result
336 *    and draw again with second subroutine selected then verify result again.
337 *    Repeat for following subroutines return and argument types: bool, float,
338 *    int, uint, double, *vec*, *mat*.
339 *
340 *  * Same as above, but with return and argument types as arrays.
341 *
342 ***/
343class FunctionalTest1_2 : public deqp::TestCase
344{
345public:
346	/* Public methods */
347	FunctionalTest1_2(deqp::Context& context);
348
349	virtual void						 deinit();
350	virtual tcu::TestNode::IterateResult iterate();
351
352private:
353	/* Private type definitions */
354	struct _test_case
355	{
356		unsigned int		  array_size;
357		Utils::_variable_type variable_type;
358	};
359
360	typedef std::vector<_test_case>		_test_cases;
361	typedef _test_cases::const_iterator _test_cases_const_iterator;
362
363	/* Private methods */
364	void deinitTestIteration();
365	bool executeTestIteration(const _test_case& test_case);
366
367	std::string getVertexShaderBody(const Utils::_variable_type& variable_type, unsigned int array_size);
368
369	void initTest();
370
371	bool verifyXFBData(const void* xfb_data, const Utils::_variable_type& variable_type);
372
373	/* Private fields */
374	bool		m_has_test_passed;
375	glw::GLuint m_po_id;
376	glw::GLuint m_po_getter0_subroutine_index;
377	glw::GLuint m_po_getter1_subroutine_index;
378	glw::GLint  m_po_subroutine_uniform_index;
379	_test_cases m_test_cases;
380	glw::GLuint m_xfb_bo_id;
381	glw::GLuint m_vao_id;
382	glw::GLuint m_vs_id;
383};
384
385/** * Create a program with 4 subroutines and 2 subroutine uniforms and query
386 *    it using: GetProgramStageiv, GetActiveSubroutineUniformiv,
387 *    GetActiveSubroutineUniformName, GetActiveSubroutineName,
388 *    GetUniformSubroutineuiv, GetSubroutineIndex and
389 *    GetSubroutineUniformLocation. Verify the results and use them to select
390 *    subroutines, then make a draw and select different set of subroutines.
391 *    Draw again and verify the results.
392 *
393 *  OpenGL 4.3 or ARB_program_interface_query support required
394 *  * Same as above, but query the program using calls introduced in
395 *    ARB_program_interface_query extension.
396 **/
397class FunctionalTest3_4 : public deqp::TestCase
398{
399public:
400	/* Public methods */
401	FunctionalTest3_4(deqp::Context& context);
402
403	virtual tcu::TestNode::IterateResult iterate();
404
405private:
406	/* Private types */
407	/** Connect pname with expected value. Used to check Get* API.
408	 *
409	 **/
410	struct inspectionDetails
411	{
412		glw::GLenum pname;
413		glw::GLint  expected_value;
414	};
415
416	/* Private types */
417	/** Connect program_interface, pname and expected value. Used to check GetProgramInterface.
418	 *
419	 **/
420	struct inspectionDetailsForProgramInterface
421	{
422		glw::GLenum program_interface;
423		glw::GLenum pname;
424		glw::GLint  expected_value;
425	};
426
427	/* Private methods */
428	bool checkProgramStageiv(glw::GLuint program_id, glw::GLenum pname, glw::GLint expected) const;
429
430	bool checkProgramResourceiv(glw::GLuint program_id, glw::GLenum program_interface, glw::GLenum prop,
431								const glw::GLchar* resource_name, glw::GLint expected) const;
432
433	bool checkProgramInterfaceiv(glw::GLuint program_id, glw::GLenum program_interface, glw::GLenum pname,
434								 glw::GLint expected) const;
435
436	bool checkActiveSubroutineUniformiv(glw::GLuint program_id, glw::GLuint index, glw::GLenum pname,
437										glw::GLint expected) const;
438
439	glw::GLuint getProgramResourceIndex(glw::GLuint program_id, glw::GLenum program_interface,
440										const glw::GLchar* resource_name) const;
441
442	glw::GLuint getSubroutineIndex(glw::GLuint program_id, const glw::GLchar* subroutine_name,
443								   bool use_program_query) const;
444
445	glw::GLint getSubroutineUniformLocation(glw::GLuint program_id, const glw::GLchar* uniform_name,
446											bool use_program_query) const;
447
448	bool inspectProgramStageiv(glw::GLuint program_id) const;
449	bool inspectProgramInterfaceiv(glw::GLuint program_id) const;
450
451	bool inspectProgramResourceiv(glw::GLuint program_id, const glw::GLchar** subroutine_names,
452								  const glw::GLchar** uniform_names) const;
453
454	bool inspectActiveSubroutineUniformiv(glw::GLuint program_id, const glw::GLchar** uniform_names) const;
455
456	bool inspectActiveSubroutineUniformName(glw::GLuint program_id, const glw::GLchar** uniform_names) const;
457
458	bool inspectActiveSubroutineName(glw::GLuint program_id, const glw::GLchar** subroutine_names) const;
459
460	bool inspectSubroutineBinding(glw::GLuint program_id, const glw::GLchar** subroutine_names,
461								  const glw::GLchar** uniform_names, bool use_program_query) const;
462
463	bool testDraw(glw::GLuint program_id, const glw::GLchar* first_routine_name, const glw::GLchar* second_routine_name,
464				  const glw::GLchar** uniform_names, const Utils::vec4<glw::GLfloat> data[5],
465				  bool use_program_query) const;
466
467	/* Private fields */
468	glw::GLint m_n_active_subroutine_uniforms;
469	glw::GLint m_n_active_subroutine_uniform_locations;
470	glw::GLint m_n_active_subroutines;
471	glw::GLint m_n_active_subroutine_uniform_name_length;
472	glw::GLint m_n_active_subroutine_name_length;
473	glw::GLint m_n_active_subroutine_uniform_size;
474};
475
476/**
477 * * Create a program with 8 subroutines and 4 subroutine uniforms. Each
478 *   subroutine uniform should have different signature that should match 2
479 *   subroutines. Go through all possible combinations of subroutine uniforms
480 *   values and for each combination verify that it works as expected.
481 **/
482class FunctionalTest5 : public deqp::TestCase
483{
484public:
485	/* Public methods */
486	FunctionalTest5(deqp::Context& context);
487
488	virtual tcu::TestNode::IterateResult iterate();
489
490private:
491	/* Private methods */
492	void logError(const glw::GLchar* subroutine_names[4][2], const glw::GLuint subroutine_combination[4],
493				  const Utils::vec4<glw::GLfloat> input_data[3], const Utils::vec4<glw::GLfloat>& first_routine_result,
494				  const Utils::vec4<glw::GLfloat>& second_routine_result,
495				  const Utils::vec4<glw::GLfloat>& third_routine_result,
496				  const Utils::vec4<glw::GLuint>&  fourth_routine_result,
497				  const Utils::vec4<glw::GLfloat>& first_routine_expected_result,
498				  const Utils::vec4<glw::GLfloat>& second_routine_expected_result,
499				  const Utils::vec4<glw::GLfloat>& third_routine_expected_result,
500				  const Utils::vec4<glw::GLuint>&  fourth_routine_expected_result) const;
501
502	void testDraw(const glw::GLuint subroutine_combination[4], const Utils::vec4<glw::GLfloat> input_data[3],
503				  Utils::vec4<glw::GLfloat>& out_first_routine_result,
504				  Utils::vec4<glw::GLfloat>& out_second_routine_result,
505				  Utils::vec4<glw::GLfloat>& out_third_routine_result,
506				  Utils::vec4<glw::GLuint>&  out_fourth_routine_result) const;
507
508	bool verify(const Utils::vec4<glw::GLfloat>& first_routine_result,
509				const Utils::vec4<glw::GLfloat>& second_routine_result,
510				const Utils::vec4<glw::GLfloat>& third_routine_result,
511				const Utils::vec4<glw::GLuint>&  fourth_routine_result,
512				const Utils::vec4<glw::GLfloat>& first_routine_expected_result,
513				const Utils::vec4<glw::GLfloat>& second_routine_expected_result,
514				const Utils::vec4<glw::GLfloat>& third_routine_expected_result,
515				const Utils::vec4<glw::GLuint>&  fourth_routine_expected_result) const;
516
517	/* Private fields */
518	glw::GLuint m_subroutine_uniform_locations[4][1];
519	glw::GLuint m_subroutine_indices[4][2];
520	glw::GLuint m_uniform_locations[3];
521};
522
523/**
524 * * Create a program with a subroutine and a subroutine uniform. Verify that
525 *   subroutine can be called directly with a static use of subroutine's
526 *   function name, as is done with non-subroutine function declarations and
527 *   calls.
528 **/
529class FunctionalTest6 : public deqp::TestCase
530{
531public:
532	/* Public methods */
533	FunctionalTest6(deqp::Context& context);
534
535	virtual tcu::TestNode::IterateResult iterate();
536};
537
538/**
539 * * Create a program with 2 subroutines and an array of 4 subroutine
540 *   uniforms. Go through all possible combinations of subroutine uniforms
541 *   values and for each combination verify that it works as expected by
542 *   performing draw or dispatch call. Also verify that length() function
543 *   works correctly when used on array of subroutine uniforms.
544 *
545 * * Verify that program which uses uniforms, constant expressions and
546 *   dynamically uniform loop index to access subroutine uniform array
547 *   compiles and works as expected.
548 **/
549class FunctionalTest7_8 : public deqp::TestCase
550{
551public:
552	/* Public methods */
553	FunctionalTest7_8(deqp::Context& context);
554
555	virtual tcu::TestNode::IterateResult iterate();
556
557private:
558	/* Private methods */
559	void calculate(glw::GLuint function, const Utils::vec4<glw::GLfloat>& left, const Utils::vec4<glw::GLfloat>& right,
560				   Utils::vec4<glw::GLfloat>& out) const;
561
562	void calculate(const glw::GLuint combination[4], const Utils::vec4<glw::GLfloat>& left,
563				   const Utils::vec4<glw::GLfloat>& right, const Utils::vec4<glw::GLuint>& indices,
564				   Utils::vec4<glw::GLfloat>& out_combined, Utils::vec4<glw::GLfloat>& out_combined_inversed,
565				   Utils::vec4<glw::GLfloat>& out_constant, Utils::vec4<glw::GLfloat>& out_constant_inversed,
566				   Utils::vec4<glw::GLfloat>& out_dynamic, Utils::vec4<glw::GLfloat>& out_dynamic_inversed,
567				   Utils::vec4<glw::GLfloat>& out_loop) const;
568
569	void logError(const glw::GLuint combination[4], const Utils::vec4<glw::GLfloat>& left,
570				  const Utils::vec4<glw::GLfloat>& right, const Utils::vec4<glw::GLuint>& indices,
571				  const Utils::vec4<glw::GLfloat> vec4_expected[7], const Utils::vec4<glw::GLfloat> vec4_result[7],
572				  glw::GLuint array_length, bool result[7]) const;
573
574	bool testDraw(const glw::GLuint combination[4], const Utils::vec4<glw::GLfloat>& left,
575				  const Utils::vec4<glw::GLfloat>& right, const Utils::vec4<glw::GLuint>& indices) const;
576
577	/* Private fields */
578	glw::GLuint m_subroutine_uniform_locations[4];
579	glw::GLuint m_subroutine_indices[2];
580	glw::GLuint m_uniform_locations[3];
581};
582
583/**
584 *  Make sure that program with one function associated with 3 different
585 *  subroutine types and 3 subroutine uniforms using that function compiles
586 *  and works as expected.
587 *
588 **/
589class FunctionalTest9 : public deqp::TestCase
590{
591public:
592	/* Public methods */
593	FunctionalTest9(deqp::Context& context);
594
595	virtual void						 deinit();
596	virtual tcu::TestNode::IterateResult iterate();
597
598private:
599	/* Private methods */
600	std::string getVertexShaderBody() const;
601	void		initTest();
602	void verifyXFBData(const glw::GLvoid* data_ptr);
603
604	/* Private fields */
605	bool			   m_has_test_passed;
606	const unsigned int m_n_points_to_draw;
607	glw::GLuint		   m_po_id;
608	glw::GLuint		   m_vao_id;
609	glw::GLuint		   m_vs_id;
610	glw::GLuint		   m_xfb_bo_id;
611};
612
613/**
614 * OpenGL 4.3 or ARB_arrays_of_arrays support required
615 * * Create a program that uses array of arrays for subroutine uniform type
616 *   and verify that it works as expected.
617 **/
618class FunctionalTest10 : public deqp::TestCase
619{
620public:
621	FunctionalTest10(deqp::Context& context);
622
623	virtual tcu::TestNode::IterateResult iterate();
624
625private:
626	/* Private methods */
627	glw::GLint testDraw(const glw::GLuint routine_indices[16]) const;
628
629	/* Private fields */
630	glw::GLuint m_subroutine_uniform_locations[16];
631	glw::GLuint m_subroutine_indices[2];
632};
633
634/**
635 * * Verify that following operations work correctly when performed inside
636 *   subroutine body: setting global variable, texture sampling, writing
637 *   to fragment shader outputs, using discard function (fragment shader
638 *   only), calling other functions and subroutines.
639 **/
640class FunctionalTest11 : public deqp::TestCase
641{
642public:
643	/* Public methods */
644	FunctionalTest11(deqp::Context& context);
645
646	virtual tcu::TestNode::IterateResult iterate();
647
648private:
649	/* Private types */
650	struct testConfiguration
651	{
652		testConfiguration(const glw::GLchar* description, const glw::GLubyte expected_color[4],
653						  glw::GLuint discard_fragment, glw::GLuint set_global_colors, glw::GLuint sample_texture,
654						  glw::GLuint compare, glw::GLuint test, glw::GLuint first_sampler, glw::GLuint second_sampler)
655		{
656			m_description = description;
657
658			m_expected_color[0] = expected_color[0];
659			m_expected_color[1] = expected_color[1];
660			m_expected_color[2] = expected_color[2];
661			m_expected_color[3] = expected_color[3];
662
663			m_routines[0] = discard_fragment;
664			m_routines[1] = set_global_colors;
665			m_routines[2] = sample_texture;
666			m_routines[3] = compare;
667			m_routines[4] = test;
668
669			m_samplers[0] = first_sampler;
670			m_samplers[1] = second_sampler;
671		}
672
673		const glw::GLchar* m_description;
674		glw::GLubyte	   m_expected_color[4];
675		glw::GLuint		   m_routines[5];
676		glw::GLuint		   m_samplers[2];
677	};
678
679	/* Private methods */
680	void fillTexture(Utils::texture& texture, const glw::GLubyte color[4]) const;
681
682	bool testDraw(const glw::GLuint routine_configuration[5], const glw::GLuint sampler_configuration[2],
683				  const glw::GLubyte expected_color[4], Utils::texture& color_texture) const;
684
685	/* Private fields */
686	/* Constants */
687	static const glw::GLuint m_texture_height;
688	static const glw::GLuint m_texture_width;
689
690	/* Locations and indices */
691	glw::GLuint m_subroutine_uniform_locations[5];
692	glw::GLuint m_subroutine_indices[5][2];
693	glw::GLuint m_uniform_locations[2];
694	glw::GLuint m_source_textures[2];
695};
696
697/**
698 * OpenGL 4.3 or ARB_shader_storage_buffer_object, ARB_atomic_counters
699 * and ARB_shader_image_load_store support required
700 * * Same as above, but check writing/reading from storage buffer, performing
701 *   operations on atomic counters and writing/reading from an image. This
702 *   should be tested in a program stage which supports operations of these
703 *   kind.
704 **/
705class FunctionalTest12 : public deqp::TestCase
706{
707public:
708	FunctionalTest12(deqp::Context& context);
709
710	virtual tcu::TestNode::IterateResult iterate();
711
712private:
713	/* Private methods */
714	void fillTexture(Utils::texture& texture, const glw::GLuint color[4]) const;
715
716	bool verifyTexture(Utils::texture& texture, const glw::GLuint color[4]) const;
717
718	bool testAtomic();
719
720	bool testAtomicDraw(glw::GLuint subourinte_index, const glw::GLuint expected_results[3]) const;
721
722	bool testImage();
723
724	bool testImageDraw(glw::GLuint subroutine_index, Utils::texture& left, Utils::texture& right,
725					   const glw::GLuint expected_left_color[4], const glw::GLuint expected_right_color[4]) const;
726
727	bool testSSBO();
728
729	bool testSSBODraw(glw::GLuint subourinte_index, const glw::GLuint expected_results[4]) const;
730
731	/* Private fields */
732	/* Constatnts */
733	static const glw::GLuint m_texture_height;
734	static const glw::GLuint m_texture_width;
735
736	/* Locations */
737	glw::GLuint m_left_image;
738	glw::GLuint m_right_image;
739};
740
741/**
742 *  Verify that subroutines work correctly when used in separate shader
743 *  objects.
744 *
745 **/
746class FunctionalTest13 : public deqp::TestCase
747{
748public:
749	/* Public methods */
750	FunctionalTest13(deqp::Context& context);
751
752	virtual void						 deinit();
753	virtual tcu::TestNode::IterateResult iterate();
754
755private:
756	/* Private methods */
757	std::string getFragmentShaderBody(unsigned int n_id);
758	std::string getGeometryShaderBody(unsigned int n_id);
759	std::string getTessellationControlShaderBody(unsigned int n_id);
760	std::string getTessellationEvaluationShaderBody(unsigned int n_id);
761	std::string getVertexShaderBody(unsigned int n_id);
762	void initTest();
763
764	void verifyReadBuffer(unsigned int n_fs_id, unsigned int n_fs_subroutine, unsigned int n_gs_id,
765						  unsigned int n_gs_subroutine, unsigned int n_tc_id, unsigned int n_tc_subroutine,
766						  unsigned int n_te_id, unsigned int n_te_subroutine, unsigned int n_vs_id,
767						  unsigned int n_vs_subroutine);
768
769	/* Private fields */
770	glw::GLuint		   m_fbo_id;
771	glw::GLuint		   m_fs_po_ids[2];
772	glw::GLuint		   m_gs_po_ids[2];
773	glw::GLuint		   m_pipeline_id;
774	unsigned char*	 m_read_buffer;
775	glw::GLuint		   m_tc_po_ids[2];
776	glw::GLuint		   m_te_po_ids[2];
777	const unsigned int m_to_height;
778	glw::GLuint		   m_to_id;
779	const unsigned int m_to_width;
780	glw::GLuint		   m_vao_id;
781	glw::GLuint		   m_vs_po_ids[2];
782
783	bool m_has_test_passed;
784};
785
786/**
787 * * Create program with subroutines that use structures as parameters and
788 *   make sure it works correctly.
789 *
790 * OpenGL 4.1 or ARB_get_program_binary support required
791 * * Create a program with 4 subroutines and 2 subroutine uniforms. Query
792 *   names and indices of all active subroutines and query names and
793 *   locations of all active subroutine uniforms. Call GetProgramBinary on
794 *   this program and delete it. Create new program from the binary using
795 *   ProgramBinary. Verify that all active subroutine names and indices in
796 *   this program match ones from the original program. Also verify that
797 *   all active subroutine uniform names and locations match ones from
798 *   original program. Make a draw, expect random but valid set of selected
799 *   subroutines, then select arbitrary set of subroutines, make a draw and
800 *   verify the results.
801 **/
802class FunctionalTest14_15 : public deqp::TestCase
803{
804public:
805	FunctionalTest14_15(deqp::Context& context);
806
807	virtual tcu::TestNode::IterateResult iterate();
808
809private:
810	/* Private methods */
811	bool testDefaultSubroutineSet(const Utils::vec4<glw::GLuint>& uni_input,
812								  const Utils::vec4<glw::GLuint>  expected_routine_1_result[2],
813								  const Utils::vec4<glw::GLuint>  expected_routine_2_result[2]) const;
814
815	bool testDraw(glw::GLuint routine_configuration, const Utils::vec4<glw::GLuint>& uni_input,
816				  const Utils::vec4<glw::GLuint>& expected_routine_1_result,
817				  const Utils::vec4<glw::GLuint>& expected_routine_2_result) const;
818
819	bool testIndicesAndLocations() const;
820
821	/* Private fields */
822	/* Locations and indices */
823	glw::GLuint m_subroutine_uniform_locations[2];
824	glw::GLuint m_subroutine_indices[2][2];
825	glw::GLuint m_uniform_location;
826	glw::GLuint m_initial_subroutine_uniform_locations[2];
827	glw::GLuint m_initial_subroutine_indices[2][2];
828};
829
830/**
831 * Check that when the active program for a shader stage is re-linked or
832 * changed by a call to UseProgram, BindProgramPipeline, or
833 * UseProgramStages, subroutine uniforms for that stage are reset to
834 * arbitrarily chosen default functions with compatible subroutine types.
835 *
836 **/
837class FunctionalTest16 : public deqp::TestCase
838{
839public:
840	/* Public methods */
841	FunctionalTest16(deqp::Context& context);
842
843	virtual void						 deinit();
844	virtual tcu::TestNode::IterateResult iterate();
845
846private:
847	/* Private type definitions */
848	/* Defines a specific use case that should be checked during particular
849	 * test iteration.
850	 */
851	enum _test_case
852	{
853		TEST_CASE_FIRST,
854
855		TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_OBJECT = TEST_CASE_FIRST,
856		TEST_CASE_SWITCH_TO_DIFFERENT_PROGRAM_PIPELINE_OBJECT,
857		TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_FRAGMENT_STAGE,
858		TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_GEOMETRY_STAGE,
859		TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_TESS_CONTROL_STAGE,
860		TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_TESS_EVALUATION_STAGE,
861		TEST_CASE_SWITCH_TO_DIFFERENT_PIPELINE_VERTEX_STAGE,
862
863		/* Always last */
864		TEST_CASE_COUNT
865	};
866
867	/** Defines a number of different subroutine-specific properties
868	 *  for a single shader stage.
869	 **/
870	struct _shader_stage
871	{
872		glw::GLuint default_subroutine1_value;
873		glw::GLuint default_subroutine2_value;
874		glw::GLuint default_subroutine3_value;
875		glw::GLuint default_subroutine4_value;
876		glw::GLint  subroutine1_uniform_location;
877		glw::GLint  subroutine2_uniform_location;
878		glw::GLint  subroutine3_uniform_location;
879		glw::GLint  subroutine4_uniform_location;
880		glw::GLuint function1_index;
881		glw::GLuint function2_index;
882		glw::GLuint function3_index;
883		glw::GLuint function4_index;
884
885		glw::GLenum gl_stage;
886	};
887
888	/** Describes subroutine-specific properties for a program object */
889	struct _program
890	{
891		_shader_stage fragment;
892		_shader_stage geometry;
893		_shader_stage tess_control;
894		_shader_stage tess_evaluation;
895		_shader_stage vertex;
896	};
897
898	/** Describes modes that verify*() functions can run in */
899	enum _subroutine_uniform_value_verification
900	{
901		SUBROUTINE_UNIFORMS_SET_TO_DEFAULT_VALUES,
902		SUBROUTINE_UNIFORMS_SET_TO_NONDEFAULT_VALUES,
903		SUBROUTINE_UNIFORMS_SET_TO_VALID_VALUES,
904	};
905
906	/* Private methods */
907	std::string getShaderBody(const Utils::_shader_stage& shader_stage, const unsigned int& n_id) const;
908
909	void getShaderStages(bool retrieve_program_object_shader_ids, const unsigned int& n_id,
910						 const _shader_stage** out_shader_stages) const;
911
912	void initTest();
913
914	void verifySubroutineUniformValues(const _test_case& test_case, const unsigned int& n_id,
915									   const _subroutine_uniform_value_verification& verification);
916
917	void verifySubroutineUniformValuesForShaderStage(const _shader_stage&						   shader_stage,
918													 const _subroutine_uniform_value_verification& verification);
919
920	/* Private fields */
921	bool m_are_pipeline_objects_supported;
922	bool m_has_test_passed;
923
924	glw::GLuint m_fs_ids[2];
925	glw::GLuint m_gs_ids[2];
926	glw::GLuint m_po_ids[2];
927	glw::GLuint m_tc_ids[2];
928	glw::GLuint m_te_ids[2];
929	glw::GLuint m_vs_ids[2];
930
931	glw::GLuint m_fs_po_ids[2];
932	glw::GLuint m_gs_po_ids[2];
933	glw::GLuint m_pipeline_object_ids[2];
934	glw::GLuint m_tc_po_ids[2];
935	glw::GLuint m_te_po_ids[2];
936	glw::GLuint m_vs_po_ids[2];
937
938	_shader_stage m_fs_po_descriptors[2];
939	_shader_stage m_gs_po_descriptors[2];
940	_shader_stage m_tc_po_descriptors[2];
941	_shader_stage m_te_po_descriptors[2];
942	_shader_stage m_vs_po_descriptors[2];
943
944	_program m_po_descriptors[2];
945};
946
947/**
948 *  Create a program which uses the same subroutine and subroutine uniform
949 *  names for every stage. Types of subroutines should be different in each
950 *  stage. Make sure that such program compiles and works as expected.
951 **/
952class FunctionalTest17 : public deqp::TestCase
953{
954public:
955	/* Public methods */
956	FunctionalTest17(deqp::Context& context);
957
958	virtual void						 deinit();
959	virtual tcu::TestNode::IterateResult iterate();
960
961private:
962	/* Private methods */
963	std::string getFragmentShaderBody() const;
964	std::string getGeometryShaderBody() const;
965	std::string getTessellationControlShaderBody() const;
966	std::string getTessellationEvaluationShaderBody() const;
967	std::string getVertexShaderBody() const;
968	void		initTest();
969	void		verifyRenderedData();
970
971	/* Private fields */
972	glw::GLuint		   m_fbo_id;
973	glw::GLuint		   m_fs_id;
974	glw::GLuint		   m_gs_id;
975	bool			   m_has_test_passed;
976	glw::GLuint		   m_po_id;
977	glw::GLuint		   m_tc_id;
978	glw::GLuint		   m_te_id;
979	float*			   m_to_data;
980	const unsigned int m_to_height;
981	glw::GLuint		   m_to_id;
982	const unsigned int m_to_width;
983	glw::GLuint		   m_vao_id;
984	glw::GLuint		   m_vs_id;
985};
986
987/**
988 *  Make sure that calling a subroutine with argument value returned by
989 *  another subroutine works correctly.
990 *
991 *  Verify that subroutines and subroutine uniforms work as expected when
992 *  they are used in connection with control flow functions
993 *  (if/else/case/while/for/break/continue).
994 *
995 **/
996class FunctionalTest18_19 : public deqp::TestCase
997{
998public:
999	/* Public methods */
1000	FunctionalTest18_19(deqp::Context& context);
1001
1002	virtual void						 deinit();
1003	virtual tcu::TestNode::IterateResult iterate();
1004
1005private:
1006	/* Private type definitions */
1007	typedef tcu::Vec4 (*PFNVEC4OPERATORPROC)(tcu::Vec4);
1008
1009	/* Private methods */
1010	void executeTest(glw::GLuint bool_operator1_subroutine_location, glw::GLuint bool_operator2_subroutine_location,
1011					 glw::GLuint vec4_operator1_subroutine_location, glw::GLuint vec4_operator2_subroutine_location);
1012
1013	std::string getVertexShaderBody() const;
1014
1015	void initTest();
1016	void verifyXFBData(const glw::GLvoid* data, glw::GLuint bool_operator1_subroutine_location,
1017					   glw::GLuint bool_operator2_subroutine_location, glw::GLuint vec4_operator1_subroutine_location,
1018					   glw::GLuint vec4_operator2_subroutine_location);
1019
1020	static tcu::Vec4 vec4operator_div2(tcu::Vec4 data);
1021	static tcu::Vec4 vec4operator_mul4(tcu::Vec4 data);
1022
1023	/* Private fields */
1024	bool			   m_has_test_passed;
1025	const unsigned int m_n_points_to_draw;
1026	glw::GLuint		   m_po_id;
1027	glw::GLuint		   m_po_subroutine_divide_by_two_location;
1028	glw::GLuint		   m_po_subroutine_multiply_by_four_location;
1029	glw::GLuint		   m_po_subroutine_returns_false_location;
1030	glw::GLuint		   m_po_subroutine_returns_true_location;
1031	glw::GLint		   m_po_subroutine_uniform_bool_operator1;
1032	glw::GLint		   m_po_subroutine_uniform_bool_operator2;
1033	glw::GLint		   m_po_subroutine_uniform_vec4_processor1;
1034	glw::GLint		   m_po_subroutine_uniform_vec4_processor2;
1035	glw::GLuint		   m_xfb_bo_id;
1036	glw::GLuint		   m_vao_id;
1037	glw::GLuint		   m_vs_id;
1038};
1039
1040/**
1041 *  Test whether all INVALID_OPERATION, INVALID_VALUE and INVALID_ENUM
1042 *  errors related to subroutines usage are properly generated.
1043 **/
1044class NegativeTest1 : public deqp::TestCase
1045{
1046public:
1047	/* Public methods */
1048	NegativeTest1(deqp::Context& context);
1049
1050	virtual void						 deinit();
1051	virtual tcu::TestNode::IterateResult iterate();
1052
1053private:
1054	/* Private methods */
1055	void initTest();
1056
1057	/* Private fields */
1058	bool		m_has_test_passed;
1059	glw::GLint  m_po_active_subroutine_uniform_locations;
1060	glw::GLint  m_po_active_subroutine_uniforms;
1061	glw::GLint  m_po_active_subroutines;
1062	glw::GLint  m_po_subroutine_uniform_function_index;
1063	glw::GLint  m_po_subroutine_uniform_function2_index;
1064	glw::GLuint m_po_subroutine_test1_index;
1065	glw::GLuint m_po_subroutine_test2_index;
1066	glw::GLuint m_po_subroutine_test3_index;
1067	glw::GLuint m_po_not_linked_id;
1068	glw::GLuint m_po_id;
1069	glw::GLuint m_vs_id;
1070};
1071
1072/** Make sure that subroutine uniform variables are scoped to the shader
1073 *  execution stage the variable is declared in. Referencing subroutine
1074 *  uniform from different stage should cause compile or link error
1075 **/
1076class NegativeTest2 : public deqp::TestCase
1077{
1078public:
1079	/* Public methods */
1080	NegativeTest2(deqp::Context& context);
1081
1082	virtual void						 deinit();
1083	virtual tcu::TestNode::IterateResult iterate();
1084
1085private:
1086	/* Private type definitions */
1087
1088	/* Private methods */
1089	void deinitGLObjects();
1090	void executeTestCase(const Utils::_shader_stage& referencing_stage);
1091	std::string getFragmentShaderBody(const Utils::_shader_stage& referencing_stage) const;
1092	std::string getGeometryShaderBody(const Utils::_shader_stage& referencing_stage) const;
1093	std::string getSubroutineUniformName(const Utils::_shader_stage& stage) const;
1094	std::string getTessellationControlShaderBody(const Utils::_shader_stage& referencing_stage) const;
1095	std::string getTessellationEvaluationShaderBody(const Utils::_shader_stage& referencing_stage) const;
1096	std::string getVertexShaderBody(const Utils::_shader_stage& referencing_stage) const;
1097
1098	/* Private fields */
1099	glw::GLuint m_fs_id;
1100	glw::GLuint m_gs_id;
1101	bool		m_has_test_passed;
1102	glw::GLuint m_po_id;
1103	glw::GLuint m_tc_id;
1104	glw::GLuint m_te_id;
1105	glw::GLuint m_vs_id;
1106};
1107
1108/** Verify that "subroutine" keyword is necessary when declaring a
1109 *  subroutine uniform and a compilation error occurs without it.
1110 **/
1111class NegativeTest3 : public deqp::TestCase
1112{
1113public:
1114	/* Public methods */
1115	NegativeTest3(deqp::Context& context);
1116
1117	virtual void						 deinit();
1118	virtual tcu::TestNode::IterateResult iterate();
1119
1120private:
1121	/* Private methods */
1122	void executeTest(const Utils::_shader_stage& shader_stage);
1123	std::string getFragmentShaderBody() const;
1124	std::string getGeometryShaderBody() const;
1125	std::string getTessellationControlShaderBody() const;
1126	std::string getTessellationEvaluationShaderBody() const;
1127	std::string getVertexShaderBody() const;
1128
1129	/* Private fields */
1130	bool		m_has_test_passed;
1131	glw::GLuint m_so_id;
1132};
1133
1134/**
1135 *  Verify that compile-time error is present when arguments and return type
1136 *  do not match between the function and each associated subroutine type.
1137 *  In particular make sure that applies when there are multiple associated
1138 *  subroutine types and only one of them does not match.
1139 *
1140 **/
1141class NegativeTest4 : public deqp::TestCase
1142{
1143public:
1144	/* Public methods */
1145	NegativeTest4(deqp::Context& context);
1146
1147	virtual void						 deinit();
1148	virtual tcu::TestNode::IterateResult iterate();
1149
1150private:
1151	/* Private type declarations */
1152	enum _test_case
1153	{
1154		TEST_CASE_FIRST,
1155
1156		TEST_CASE_INCOMPATIBLE_RETURN_TYPE = TEST_CASE_FIRST,
1157		TEST_CASE_INCOMPATIBLE_ARGUMENT_LIST,
1158
1159		/* Always last */
1160		TEST_CASE_COUNT
1161	};
1162
1163	/* Private methods */
1164	std::string getShaderBody(const Utils::_shader_stage& shader_stage, const unsigned int& n_subroutine_types,
1165							  const _test_case& test_case) const;
1166
1167	/* Private fields */
1168	bool	   m_has_test_passed;
1169	glw::GLint m_so_id;
1170};
1171
1172/** Verify that link or compile error occurs when trying to link a program
1173 *  with no subroutine for subroutine uniform variable.
1174 **/
1175class NegativeTest5 : public deqp::TestCase
1176{
1177public:
1178	/* Public methods */
1179	NegativeTest5(deqp::Context& context);
1180
1181	virtual void						 deinit();
1182	virtual tcu::TestNode::IterateResult iterate();
1183
1184private:
1185	/* Private type definitions */
1186	/* Private methods */
1187	void deinitIteration();
1188	void executeIteration(const Utils::_shader_stage& shader_stage);
1189	std::string getFragmentShaderBody(bool include_invalid_subroutine_uniform_declaration) const;
1190	std::string getGeometryShaderBody(bool include_invalid_subroutine_uniform_declaration) const;
1191	std::string getTessellationControlShaderBody(bool include_invalid_subroutine_uniform_declaration) const;
1192	std::string getTessellationEvaluationShaderBody(bool include_invalid_subroutine_uniform_declaration) const;
1193	std::string getVertexShaderBody(bool include_invalid_subroutine_uniform_declaration) const;
1194
1195	/* Private fields */
1196	glw::GLuint m_fs_id;
1197	glw::GLuint m_gs_id;
1198	bool		m_has_test_passed;
1199	glw::GLuint m_po_id;
1200	glw::GLuint m_tc_id;
1201	glw::GLuint m_te_id;
1202	glw::GLuint m_vs_id;
1203};
1204
1205/** Check that link or compile error occurs if any shader in a program
1206 *  includes two or more functions with the same name and at least one of
1207 *  which is associated with a subroutine type.
1208 **/
1209class NegativeTest6 : public deqp::TestCase
1210{
1211public:
1212	/* Public methods */
1213	NegativeTest6(deqp::Context& context);
1214
1215	virtual void						 deinit();
1216	virtual tcu::TestNode::IterateResult iterate();
1217
1218private:
1219	/* Private type definitions */
1220	/* Private methods */
1221	void deinitIteration();
1222	void executeIteration(const Utils::_shader_stage& shader_stage);
1223	std::string getFragmentShaderBody(bool include_invalid_declaration) const;
1224	std::string getGeometryShaderBody(bool include_invalid_declaration) const;
1225	std::string getTessellationControlShaderBody(bool include_invalid_declaration) const;
1226	std::string getTessellationEvaluationShaderBody(bool include_invalid_declaration) const;
1227	std::string getVertexShaderBody(bool include_invalid_declaration) const;
1228
1229	/* Private fields */
1230	glw::GLuint m_fs_id;
1231	glw::GLuint m_gs_id;
1232	bool		m_has_test_passed;
1233	glw::GLuint m_po_id;
1234	glw::GLuint m_tc_id;
1235	glw::GLuint m_te_id;
1236	glw::GLuint m_vs_id;
1237};
1238
1239/**
1240 * * Verify that program fails to link if there is any possible combination
1241 *   of subroutine uniform values that would result in recursion.
1242 **/
1243class NegativeTest7 : public deqp::TestCase
1244{
1245public:
1246	NegativeTest7(deqp::Context& contex);
1247
1248	virtual void						 deinit();
1249	virtual tcu::TestNode::IterateResult iterate();
1250
1251private:
1252	/* Private methods */
1253	bool test(const glw::GLchar* vertex_shader_code, const glw::GLchar* name_of_recursive_routine);
1254
1255	/* Private fields */
1256	glw::GLuint m_program_id;
1257	glw::GLuint m_vertex_shader_id;
1258};
1259
1260/** Test that either compile or link error occurs when function declared
1261 *  with subroutine does not include a body.
1262 **/
1263class NegativeTest8 : public deqp::TestCase
1264{
1265public:
1266	/* Public methods */
1267	NegativeTest8(deqp::Context& context);
1268
1269	virtual void						 deinit();
1270	virtual tcu::TestNode::IterateResult iterate();
1271
1272private:
1273	/* Private type definitions */
1274	/* Private methods */
1275	void deinitIteration();
1276	void executeIteration(const Utils::_shader_stage& shader_stage);
1277	std::string getFragmentShaderBody(bool include_invalid_declaration) const;
1278	std::string getGeometryShaderBody(bool include_invalid_declaration) const;
1279	std::string getTessellationControlShaderBody(bool include_invalid_declaration) const;
1280	std::string getTessellationEvaluationShaderBody(bool include_invalid_declaration) const;
1281	std::string getVertexShaderBody(bool include_invalid_declaration) const;
1282
1283	/* Private fields */
1284	glw::GLuint m_fs_id;
1285	glw::GLuint m_gs_id;
1286	bool		m_has_test_passed;
1287	glw::GLuint m_po_id;
1288	glw::GLuint m_tc_id;
1289	glw::GLuint m_te_id;
1290	glw::GLuint m_vs_id;
1291};
1292
1293/**
1294 *   Make sure that it is not possible to assign float/int to subroutine
1295 *   uniform and that subroutine uniform values cannot be compared.
1296 *
1297 **/
1298class NegativeTest9 : public deqp::TestCase
1299{
1300public:
1301	/* Public methods */
1302	NegativeTest9(deqp::Context& context);
1303
1304	virtual void						 deinit();
1305	virtual tcu::TestNode::IterateResult iterate();
1306
1307private:
1308	/* Private type definitions */
1309	enum _test_case
1310	{
1311		TEST_CASE_FIRST,
1312
1313		TEST_CASE_INVALID_FLOAT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT = TEST_CASE_FIRST,
1314		TEST_CASE_INVALID_INT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT,
1315		TEST_CASE_INVALID_SUBROUTINE_UNIFORM_VALUE_COMPARISON,
1316
1317		/* Always last */
1318		TEST_CASE_COUNT
1319	};
1320
1321	/* Private methods */
1322	std::string getTestCaseString(const _test_case& test_case);
1323	std::string getVertexShader(const _test_case& test_case);
1324
1325	/* Private fields */
1326	bool		m_has_test_passed;
1327	glw::GLuint m_po_id;
1328	glw::GLuint m_vs_id;
1329};
1330
1331/**
1332 * Check that an overloaded function cannot be declared with subroutine and
1333 * a program will fail to compile or link if any shader or stage contains
1334 * two or more  functions with the same name if the name is associated with
1335 * a subroutine type.
1336 *
1337 **/
1338class NegativeTest10 : public deqp::TestCase
1339{
1340public:
1341	/* Public methods */
1342	NegativeTest10(deqp::Context& context);
1343
1344	virtual void						 deinit();
1345	virtual tcu::TestNode::IterateResult iterate();
1346
1347private:
1348	/* Private type definitions */
1349	struct _test_case
1350	{
1351		std::string name;
1352
1353		std::string fs_body;
1354		std::string gs_body;
1355		std::string tc_body;
1356		std::string te_body;
1357		std::string vs_body;
1358	};
1359
1360	typedef std::vector<_test_case>		_test_cases;
1361	typedef _test_cases::const_iterator _test_cases_const_iterator;
1362
1363	/* Private methods */
1364	std::string getFragmentShader(bool include_duplicate_function);
1365	std::string getGeometryShader(bool include_duplicate_function);
1366	std::string getTessellationControlShader(bool include_duplicate_function);
1367	std::string getTessellationEvaluationShader(bool include_duplicate_function);
1368	std::string getVertexShader(bool include_duplicate_function);
1369	void initTestCases();
1370
1371	/* Private fields */
1372	bool		m_has_test_passed;
1373	glw::GLuint m_fs_id;
1374	glw::GLuint m_gs_id;
1375	glw::GLuint m_po_id;
1376	glw::GLuint m_tc_id;
1377	glw::GLuint m_te_id;
1378	_test_cases m_test_cases;
1379	glw::GLuint m_vs_id;
1380};
1381
1382/**
1383 *   Try to use subroutine uniform in invalid way in sampling, atomic and
1384 *   image functions. Verify that compile or link time error occurs.
1385 *
1386 **/
1387class NegativeTest11 : public deqp::TestCase
1388{
1389public:
1390	/* Public methods */
1391	NegativeTest11(deqp::Context& context);
1392
1393	virtual void						 deinit();
1394	virtual tcu::TestNode::IterateResult iterate();
1395
1396private:
1397	/* Private type definitions */
1398	enum _test_case
1399	{
1400		TEST_CASE_FIRST,
1401
1402		TEST_CASE_INVALID_TEXTURE_SAMPLING_ATTEMPT = TEST_CASE_FIRST,
1403		TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT,
1404		TEST_CASE_INVALID_IMAGE_FUNCTION_USAGE_ATTEMPT,
1405
1406		/* Always last */
1407		TEST_CASE_COUNT
1408	};
1409
1410	/* Private methods */
1411	std::string getTestCaseString(const _test_case& test_case);
1412	std::string getVertexShader(const _test_case& test_case);
1413
1414	/* Private fields */
1415	bool		m_has_test_passed;
1416	glw::GLuint m_po_id;
1417	glw::GLuint m_vs_id;
1418};
1419
1420/**
1421 *  Verify that it is not allowed to use subroutine type for local/global
1422 *  variables, constructors or argument/return type.
1423 *
1424 **/
1425class NegativeTest12 : public deqp::TestCase
1426{
1427public:
1428	/* Public methods */
1429	NegativeTest12(deqp::Context& context);
1430
1431	virtual void						 deinit();
1432	virtual tcu::TestNode::IterateResult iterate();
1433
1434private:
1435	/* Private type definitions */
1436	enum _test_case
1437	{
1438		TEST_CASE_FIRST,
1439
1440		TEST_CASE_INVALID_LOCAL_SUBROUTINE_VARIABLE = TEST_CASE_FIRST,
1441		TEST_CASE_INVALID_GLOBAL_SUBROUTINE_VARIABLE,
1442		TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR,
1443		TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_ARGUMENT,
1444		TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_RETURN_TYPE,
1445
1446		/* Always last */
1447		TEST_CASE_COUNT
1448	};
1449
1450	/* Private methods */
1451	std::string getTestCaseString(const _test_case& test_case);
1452	std::string getVertexShader(const _test_case& test_case);
1453
1454	/* Private fields */
1455	bool		m_has_test_passed;
1456	glw::GLuint m_po_id;
1457	glw::GLuint m_vs_id;
1458};
1459} /* ShaderSubroutine */
1460
1461/** Group class for Shader Subroutine conformance tests */
1462class ShaderSubroutineTests : public deqp::TestCaseGroup
1463{
1464public:
1465	/* Public methods */
1466	ShaderSubroutineTests(deqp::Context& context);
1467	virtual ~ShaderSubroutineTests()
1468	{
1469	}
1470
1471	virtual void init(void);
1472
1473private:
1474	/* Private methods */
1475	ShaderSubroutineTests(const ShaderSubroutineTests&);
1476	ShaderSubroutineTests& operator=(const ShaderSubroutineTests&);
1477};
1478
1479} /* gl4cts namespace */
1480
1481#endif // _GL4CSHADERSUBROUTINETESTS_HPP
1482