• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
37 namespace gl4cts
38 {
39 namespace ShaderSubroutine
40 {
41 class Utils
42 {
43 public:
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 	{
vec4gl4cts::ShaderSubroutine::Utils::vec4165 		vec4()
166 		{
167 		}
168 
vec4gl4cts::ShaderSubroutine::Utils::vec4169 		vec4(T x, T y, T z, T w) : m_x(x), m_y(y), m_z(z), m_w(w)
170 		{
171 		}
172 
operator ==gl4cts::ShaderSubroutine::Utils::vec4173 		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 
loggl4cts::ShaderSubroutine::Utils::vec4185 		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 
272 private:
273 	/* Private methods */
274 	template <typename T>
compare(const T & left,const T & right)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  **/
287 class APITest1 : public deqp::TestCase
288 {
289 public:
290 	/* Public methods */
291 	APITest1(deqp::Context& context);
292 
293 	virtual tcu::TestNode::IterateResult iterate();
294 
295 private:
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  **/
306 class APITest2 : public deqp::TestCase
307 {
308 public:
309 	/* Public methods */
310 	APITest2(deqp::Context& context);
311 
312 	virtual void						 deinit();
313 	virtual tcu::TestNode::IterateResult iterate();
314 
315 private:
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  ***/
343 class FunctionalTest1_2 : public deqp::TestCase
344 {
345 public:
346 	/* Public methods */
347 	FunctionalTest1_2(deqp::Context& context);
348 
349 	virtual void						 deinit();
350 	virtual tcu::TestNode::IterateResult iterate();
351 
352 private:
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  **/
397 class FunctionalTest3_4 : public deqp::TestCase
398 {
399 public:
400 	/* Public methods */
401 	FunctionalTest3_4(deqp::Context& context);
402 
403 	virtual tcu::TestNode::IterateResult iterate();
404 
405 private:
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  **/
482 class FunctionalTest5 : public deqp::TestCase
483 {
484 public:
485 	/* Public methods */
486 	FunctionalTest5(deqp::Context& context);
487 
488 	virtual tcu::TestNode::IterateResult iterate();
489 
490 private:
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  **/
529 class FunctionalTest6 : public deqp::TestCase
530 {
531 public:
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  **/
549 class FunctionalTest7_8 : public deqp::TestCase
550 {
551 public:
552 	/* Public methods */
553 	FunctionalTest7_8(deqp::Context& context);
554 
555 	virtual tcu::TestNode::IterateResult iterate();
556 
557 private:
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  **/
589 class FunctionalTest9 : public deqp::TestCase
590 {
591 public:
592 	/* Public methods */
593 	FunctionalTest9(deqp::Context& context);
594 
595 	virtual void						 deinit();
596 	virtual tcu::TestNode::IterateResult iterate();
597 
598 private:
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  **/
618 class FunctionalTest10 : public deqp::TestCase
619 {
620 public:
621 	FunctionalTest10(deqp::Context& context);
622 
623 	virtual tcu::TestNode::IterateResult iterate();
624 
625 private:
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  **/
640 class FunctionalTest11 : public deqp::TestCase
641 {
642 public:
643 	/* Public methods */
644 	FunctionalTest11(deqp::Context& context);
645 
646 	virtual tcu::TestNode::IterateResult iterate();
647 
648 private:
649 	/* Private types */
650 	struct testConfiguration
651 	{
testConfigurationgl4cts::ShaderSubroutine::FunctionalTest11::testConfiguration652 		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  **/
705 class FunctionalTest12 : public deqp::TestCase
706 {
707 public:
708 	FunctionalTest12(deqp::Context& context);
709 
710 	virtual tcu::TestNode::IterateResult iterate();
711 
712 private:
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  **/
746 class FunctionalTest13 : public deqp::TestCase
747 {
748 public:
749 	/* Public methods */
750 	FunctionalTest13(deqp::Context& context);
751 
752 	virtual void						 deinit();
753 	virtual tcu::TestNode::IterateResult iterate();
754 
755 private:
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  **/
802 class FunctionalTest14_15 : public deqp::TestCase
803 {
804 public:
805 	FunctionalTest14_15(deqp::Context& context);
806 
807 	virtual tcu::TestNode::IterateResult iterate();
808 
809 private:
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  **/
837 class FunctionalTest16 : public deqp::TestCase
838 {
839 public:
840 	/* Public methods */
841 	FunctionalTest16(deqp::Context& context);
842 
843 	virtual void						 deinit();
844 	virtual tcu::TestNode::IterateResult iterate();
845 
846 private:
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  **/
952 class FunctionalTest17 : public deqp::TestCase
953 {
954 public:
955 	/* Public methods */
956 	FunctionalTest17(deqp::Context& context);
957 
958 	virtual void						 deinit();
959 	virtual tcu::TestNode::IterateResult iterate();
960 
961 private:
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  **/
996 class FunctionalTest18_19 : public deqp::TestCase
997 {
998 public:
999 	/* Public methods */
1000 	FunctionalTest18_19(deqp::Context& context);
1001 
1002 	virtual void						 deinit();
1003 	virtual tcu::TestNode::IterateResult iterate();
1004 
1005 private:
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  **/
1044 class NegativeTest1 : public deqp::TestCase
1045 {
1046 public:
1047 	/* Public methods */
1048 	NegativeTest1(deqp::Context& context);
1049 
1050 	virtual void						 deinit();
1051 	virtual tcu::TestNode::IterateResult iterate();
1052 
1053 private:
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  **/
1076 class NegativeTest2 : public deqp::TestCase
1077 {
1078 public:
1079 	/* Public methods */
1080 	NegativeTest2(deqp::Context& context);
1081 
1082 	virtual void						 deinit();
1083 	virtual tcu::TestNode::IterateResult iterate();
1084 
1085 private:
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  **/
1111 class NegativeTest3 : public deqp::TestCase
1112 {
1113 public:
1114 	/* Public methods */
1115 	NegativeTest3(deqp::Context& context);
1116 
1117 	virtual void						 deinit();
1118 	virtual tcu::TestNode::IterateResult iterate();
1119 
1120 private:
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  **/
1141 class NegativeTest4 : public deqp::TestCase
1142 {
1143 public:
1144 	/* Public methods */
1145 	NegativeTest4(deqp::Context& context);
1146 
1147 	virtual void						 deinit();
1148 	virtual tcu::TestNode::IterateResult iterate();
1149 
1150 private:
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  **/
1175 class NegativeTest5 : public deqp::TestCase
1176 {
1177 public:
1178 	/* Public methods */
1179 	NegativeTest5(deqp::Context& context);
1180 
1181 	virtual void						 deinit();
1182 	virtual tcu::TestNode::IterateResult iterate();
1183 
1184 private:
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  **/
1209 class NegativeTest6 : public deqp::TestCase
1210 {
1211 public:
1212 	/* Public methods */
1213 	NegativeTest6(deqp::Context& context);
1214 
1215 	virtual void						 deinit();
1216 	virtual tcu::TestNode::IterateResult iterate();
1217 
1218 private:
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  **/
1243 class NegativeTest7 : public deqp::TestCase
1244 {
1245 public:
1246 	NegativeTest7(deqp::Context& contex);
1247 
1248 	virtual void						 deinit();
1249 	virtual tcu::TestNode::IterateResult iterate();
1250 
1251 private:
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  **/
1263 class NegativeTest8 : public deqp::TestCase
1264 {
1265 public:
1266 	/* Public methods */
1267 	NegativeTest8(deqp::Context& context);
1268 
1269 	virtual void						 deinit();
1270 	virtual tcu::TestNode::IterateResult iterate();
1271 
1272 private:
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  **/
1298 class NegativeTest9 : public deqp::TestCase
1299 {
1300 public:
1301 	/* Public methods */
1302 	NegativeTest9(deqp::Context& context);
1303 
1304 	virtual void						 deinit();
1305 	virtual tcu::TestNode::IterateResult iterate();
1306 
1307 private:
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  **/
1338 class NegativeTest10 : public deqp::TestCase
1339 {
1340 public:
1341 	/* Public methods */
1342 	NegativeTest10(deqp::Context& context);
1343 
1344 	virtual void						 deinit();
1345 	virtual tcu::TestNode::IterateResult iterate();
1346 
1347 private:
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  **/
1387 class NegativeTest11 : public deqp::TestCase
1388 {
1389 public:
1390 	/* Public methods */
1391 	NegativeTest11(deqp::Context& context);
1392 
1393 	virtual void						 deinit();
1394 	virtual tcu::TestNode::IterateResult iterate();
1395 
1396 private:
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  **/
1425 class NegativeTest12 : public deqp::TestCase
1426 {
1427 public:
1428 	/* Public methods */
1429 	NegativeTest12(deqp::Context& context);
1430 
1431 	virtual void						 deinit();
1432 	virtual tcu::TestNode::IterateResult iterate();
1433 
1434 private:
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 */
1462 class ShaderSubroutineTests : public deqp::TestCaseGroup
1463 {
1464 public:
1465 	/* Public methods */
1466 	ShaderSubroutineTests(deqp::Context& context);
~ShaderSubroutineTests()1467 	virtual ~ShaderSubroutineTests()
1468 	{
1469 	}
1470 
1471 	virtual void init(void);
1472 
1473 private:
1474 	/* Private methods */
1475 	ShaderSubroutineTests(const ShaderSubroutineTests&);
1476 	ShaderSubroutineTests& operator=(const ShaderSubroutineTests&);
1477 };
1478 
1479 } /* gl4cts namespace */
1480 
1481 #endif // _GL4CSHADERSUBROUTINETESTS_HPP
1482