Home | History | Annotate | Download | only in gl
      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 	{
    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 
    272 private:
    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  **/
    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 	{
    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  **/
    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  * * Create multiple contexts and verify that subroutine uniforms values
   1042  *   are preserved for each program stage when switching rendering context.
   1043  *
   1044  * OpenGL 4.1 or ARB_separate_shader_objects support required
   1045  * * Same as above, but use pipelines instead of monolithic program.
   1046  **/
   1047 class FunctionalTest20_21 : public deqp::TestCase
   1048 {
   1049 public:
   1050 	/* Public methods */
   1051 	FunctionalTest20_21(deqp::Context& context);
   1052 
   1053 	virtual void						 deinit();
   1054 	virtual tcu::TestNode::IterateResult iterate();
   1055 
   1056 private:
   1057 	/* Private types */
   1058 	struct subroutineUniformSet
   1059 	{
   1060 		bool operator!=(const subroutineUniformSet& arg) const;
   1061 		void set(glw::GLuint bit_field, const subroutineUniformSet subroutine_indices[2]);
   1062 
   1063 		glw::GLuint m_vertex_shader_stage;
   1064 		glw::GLuint m_tesselation_control_shader_stage;
   1065 		glw::GLuint m_tesselation_evaluation_shader_stage;
   1066 		glw::GLuint m_geometry_shader_stage;
   1067 		glw::GLuint m_fragment_shader_stage;
   1068 	};
   1069 
   1070 	/* Private methods */
   1071 	void captureCurrentSubroutineSet(subroutineUniformSet& set);
   1072 
   1073 	void getShaders(const glw::GLchar*& out_vertex_shader_code, const glw::GLchar*& out_tesselation_control_shader_code,
   1074 					const glw::GLchar*& out_tesselation_evaluation_shader_code,
   1075 					const glw::GLchar*& out_geometry_shader_code, const glw::GLchar*& out_fragment_shader_code);
   1076 
   1077 	void initSharedContexts();
   1078 
   1079 	void prepareProgram(Utils::program** programs, bool is_separable);
   1080 
   1081 	void prepareProgramPipeline(glw::GLuint& pipeline_id, Utils::program** programs);
   1082 
   1083 	bool testCase(const glw::GLuint bit_field[5]);
   1084 
   1085 	bool testProgram(Utils::program** programs, bool is_separable, const glw::GLuint test_cases[][5],
   1086 					 glw::GLuint n_test_cases);
   1087 
   1088 	void updateCurrentSubroutineSet(const subroutineUniformSet& set);
   1089 
   1090 	/* Private fields */
   1091 	static const glw::GLuint m_n_shared_contexts;
   1092 	static const glw::GLuint m_fragment_stage_index;
   1093 	static const glw::GLuint m_geometry_stage_index;
   1094 	static const glw::GLuint m_tesselation_control_stage_index;
   1095 	static const glw::GLuint m_tesselation_evaluation_stage_index;
   1096 	static const glw::GLuint m_vertex_stage_index;
   1097 
   1098 	glw::GLuint			 m_program_pipelines[5];
   1099 	glu::RenderContext*  m_shared_contexts[4];
   1100 	subroutineUniformSet m_subroutine_indices[2];
   1101 	subroutineUniformSet m_subroutine_uniform_locations;
   1102 };
   1103 
   1104 /**
   1105  *  Test whether all INVALID_OPERATION, INVALID_VALUE and INVALID_ENUM
   1106  *  errors related to subroutines usage are properly generated.
   1107  **/
   1108 class NegativeTest1 : public deqp::TestCase
   1109 {
   1110 public:
   1111 	/* Public methods */
   1112 	NegativeTest1(deqp::Context& context);
   1113 
   1114 	virtual void						 deinit();
   1115 	virtual tcu::TestNode::IterateResult iterate();
   1116 
   1117 private:
   1118 	/* Private methods */
   1119 	void initTest();
   1120 
   1121 	/* Private fields */
   1122 	bool		m_has_test_passed;
   1123 	glw::GLint  m_po_active_subroutine_uniform_locations;
   1124 	glw::GLint  m_po_active_subroutine_uniforms;
   1125 	glw::GLint  m_po_active_subroutines;
   1126 	glw::GLint  m_po_subroutine_uniform_function_index;
   1127 	glw::GLint  m_po_subroutine_uniform_function2_index;
   1128 	glw::GLuint m_po_subroutine_test1_index;
   1129 	glw::GLuint m_po_subroutine_test2_index;
   1130 	glw::GLuint m_po_subroutine_test3_index;
   1131 	glw::GLuint m_po_not_linked_id;
   1132 	glw::GLuint m_po_id;
   1133 	glw::GLuint m_vs_id;
   1134 };
   1135 
   1136 /** Make sure that subroutine uniform variables are scoped to the shader
   1137  *  execution stage the variable is declared in. Referencing subroutine
   1138  *  uniform from different stage should cause compile or link error
   1139  **/
   1140 class NegativeTest2 : public deqp::TestCase
   1141 {
   1142 public:
   1143 	/* Public methods */
   1144 	NegativeTest2(deqp::Context& context);
   1145 
   1146 	virtual void						 deinit();
   1147 	virtual tcu::TestNode::IterateResult iterate();
   1148 
   1149 private:
   1150 	/* Private type definitions */
   1151 
   1152 	/* Private methods */
   1153 	void deinitGLObjects();
   1154 	void executeTestCase(const Utils::_shader_stage& referencing_stage);
   1155 	std::string getFragmentShaderBody(const Utils::_shader_stage& referencing_stage) const;
   1156 	std::string getGeometryShaderBody(const Utils::_shader_stage& referencing_stage) const;
   1157 	std::string getSubroutineUniformName(const Utils::_shader_stage& stage) const;
   1158 	std::string getTessellationControlShaderBody(const Utils::_shader_stage& referencing_stage) const;
   1159 	std::string getTessellationEvaluationShaderBody(const Utils::_shader_stage& referencing_stage) const;
   1160 	std::string getVertexShaderBody(const Utils::_shader_stage& referencing_stage) const;
   1161 
   1162 	/* Private fields */
   1163 	glw::GLuint m_fs_id;
   1164 	glw::GLuint m_gs_id;
   1165 	bool		m_has_test_passed;
   1166 	glw::GLuint m_po_id;
   1167 	glw::GLuint m_tc_id;
   1168 	glw::GLuint m_te_id;
   1169 	glw::GLuint m_vs_id;
   1170 };
   1171 
   1172 /** Verify that "subroutine" keyword is necessary when declaring a
   1173  *  subroutine uniform and a compilation error occurs without it.
   1174  **/
   1175 class NegativeTest3 : public deqp::TestCase
   1176 {
   1177 public:
   1178 	/* Public methods */
   1179 	NegativeTest3(deqp::Context& context);
   1180 
   1181 	virtual void						 deinit();
   1182 	virtual tcu::TestNode::IterateResult iterate();
   1183 
   1184 private:
   1185 	/* Private methods */
   1186 	void executeTest(const Utils::_shader_stage& shader_stage);
   1187 	std::string getFragmentShaderBody() const;
   1188 	std::string getGeometryShaderBody() const;
   1189 	std::string getTessellationControlShaderBody() const;
   1190 	std::string getTessellationEvaluationShaderBody() const;
   1191 	std::string getVertexShaderBody() const;
   1192 
   1193 	/* Private fields */
   1194 	bool		m_has_test_passed;
   1195 	glw::GLuint m_so_id;
   1196 };
   1197 
   1198 /**
   1199  *  Verify that compile-time error is present when arguments and return type
   1200  *  do not match between the function and each associated subroutine type.
   1201  *  In particular make sure that applies when there are multiple associated
   1202  *  subroutine types and only one of them does not match.
   1203  *
   1204  **/
   1205 class NegativeTest4 : public deqp::TestCase
   1206 {
   1207 public:
   1208 	/* Public methods */
   1209 	NegativeTest4(deqp::Context& context);
   1210 
   1211 	virtual void						 deinit();
   1212 	virtual tcu::TestNode::IterateResult iterate();
   1213 
   1214 private:
   1215 	/* Private type declarations */
   1216 	enum _test_case
   1217 	{
   1218 		TEST_CASE_FIRST,
   1219 
   1220 		TEST_CASE_INCOMPATIBLE_RETURN_TYPE = TEST_CASE_FIRST,
   1221 		TEST_CASE_INCOMPATIBLE_ARGUMENT_LIST,
   1222 
   1223 		/* Always last */
   1224 		TEST_CASE_COUNT
   1225 	};
   1226 
   1227 	/* Private methods */
   1228 	std::string getShaderBody(const Utils::_shader_stage& shader_stage, const unsigned int& n_subroutine_types,
   1229 							  const _test_case& test_case) const;
   1230 
   1231 	/* Private fields */
   1232 	bool	   m_has_test_passed;
   1233 	glw::GLint m_so_id;
   1234 };
   1235 
   1236 /** Verify that link or compile error occurs when trying to link a program
   1237  *  with no subroutine for subroutine uniform variable.
   1238  **/
   1239 class NegativeTest5 : public deqp::TestCase
   1240 {
   1241 public:
   1242 	/* Public methods */
   1243 	NegativeTest5(deqp::Context& context);
   1244 
   1245 	virtual void						 deinit();
   1246 	virtual tcu::TestNode::IterateResult iterate();
   1247 
   1248 private:
   1249 	/* Private type definitions */
   1250 	/* Private methods */
   1251 	void deinitIteration();
   1252 	void executeIteration(const Utils::_shader_stage& shader_stage);
   1253 	std::string getFragmentShaderBody(bool include_invalid_subroutine_uniform_declaration) const;
   1254 	std::string getGeometryShaderBody(bool include_invalid_subroutine_uniform_declaration) const;
   1255 	std::string getTessellationControlShaderBody(bool include_invalid_subroutine_uniform_declaration) const;
   1256 	std::string getTessellationEvaluationShaderBody(bool include_invalid_subroutine_uniform_declaration) const;
   1257 	std::string getVertexShaderBody(bool include_invalid_subroutine_uniform_declaration) const;
   1258 
   1259 	/* Private fields */
   1260 	glw::GLuint m_fs_id;
   1261 	glw::GLuint m_gs_id;
   1262 	bool		m_has_test_passed;
   1263 	glw::GLuint m_po_id;
   1264 	glw::GLuint m_tc_id;
   1265 	glw::GLuint m_te_id;
   1266 	glw::GLuint m_vs_id;
   1267 };
   1268 
   1269 /** Check that link or compile error occurs if any shader in a program
   1270  *  includes two or more functions with the same name and at least one of
   1271  *  which is associated with a subroutine type.
   1272  **/
   1273 class NegativeTest6 : public deqp::TestCase
   1274 {
   1275 public:
   1276 	/* Public methods */
   1277 	NegativeTest6(deqp::Context& context);
   1278 
   1279 	virtual void						 deinit();
   1280 	virtual tcu::TestNode::IterateResult iterate();
   1281 
   1282 private:
   1283 	/* Private type definitions */
   1284 	/* Private methods */
   1285 	void deinitIteration();
   1286 	void executeIteration(const Utils::_shader_stage& shader_stage);
   1287 	std::string getFragmentShaderBody(bool include_invalid_declaration) const;
   1288 	std::string getGeometryShaderBody(bool include_invalid_declaration) const;
   1289 	std::string getTessellationControlShaderBody(bool include_invalid_declaration) const;
   1290 	std::string getTessellationEvaluationShaderBody(bool include_invalid_declaration) const;
   1291 	std::string getVertexShaderBody(bool include_invalid_declaration) const;
   1292 
   1293 	/* Private fields */
   1294 	glw::GLuint m_fs_id;
   1295 	glw::GLuint m_gs_id;
   1296 	bool		m_has_test_passed;
   1297 	glw::GLuint m_po_id;
   1298 	glw::GLuint m_tc_id;
   1299 	glw::GLuint m_te_id;
   1300 	glw::GLuint m_vs_id;
   1301 };
   1302 
   1303 /**
   1304  * * Verify that program fails to link if there is any possible combination
   1305  *   of subroutine uniform values that would result in recursion.
   1306  **/
   1307 class NegativeTest7 : public deqp::TestCase
   1308 {
   1309 public:
   1310 	NegativeTest7(deqp::Context& contex);
   1311 
   1312 	virtual void						 deinit();
   1313 	virtual tcu::TestNode::IterateResult iterate();
   1314 
   1315 private:
   1316 	/* Private methods */
   1317 	bool test(const glw::GLchar* vertex_shader_code, const glw::GLchar* name_of_recursive_routine);
   1318 
   1319 	/* Private fields */
   1320 	glw::GLuint m_program_id;
   1321 	glw::GLuint m_vertex_shader_id;
   1322 };
   1323 
   1324 /** Test that either compile or link error occurs when function declared
   1325  *  with subroutine does not include a body.
   1326  **/
   1327 class NegativeTest8 : public deqp::TestCase
   1328 {
   1329 public:
   1330 	/* Public methods */
   1331 	NegativeTest8(deqp::Context& context);
   1332 
   1333 	virtual void						 deinit();
   1334 	virtual tcu::TestNode::IterateResult iterate();
   1335 
   1336 private:
   1337 	/* Private type definitions */
   1338 	/* Private methods */
   1339 	void deinitIteration();
   1340 	void executeIteration(const Utils::_shader_stage& shader_stage);
   1341 	std::string getFragmentShaderBody(bool include_invalid_declaration) const;
   1342 	std::string getGeometryShaderBody(bool include_invalid_declaration) const;
   1343 	std::string getTessellationControlShaderBody(bool include_invalid_declaration) const;
   1344 	std::string getTessellationEvaluationShaderBody(bool include_invalid_declaration) const;
   1345 	std::string getVertexShaderBody(bool include_invalid_declaration) const;
   1346 
   1347 	/* Private fields */
   1348 	glw::GLuint m_fs_id;
   1349 	glw::GLuint m_gs_id;
   1350 	bool		m_has_test_passed;
   1351 	glw::GLuint m_po_id;
   1352 	glw::GLuint m_tc_id;
   1353 	glw::GLuint m_te_id;
   1354 	glw::GLuint m_vs_id;
   1355 };
   1356 
   1357 /**
   1358  *   Make sure that it is not possible to assign float/int to subroutine
   1359  *   uniform and that subroutine uniform values cannot be compared.
   1360  *
   1361  **/
   1362 class NegativeTest9 : public deqp::TestCase
   1363 {
   1364 public:
   1365 	/* Public methods */
   1366 	NegativeTest9(deqp::Context& context);
   1367 
   1368 	virtual void						 deinit();
   1369 	virtual tcu::TestNode::IterateResult iterate();
   1370 
   1371 private:
   1372 	/* Private type definitions */
   1373 	enum _test_case
   1374 	{
   1375 		TEST_CASE_FIRST,
   1376 
   1377 		TEST_CASE_INVALID_FLOAT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT = TEST_CASE_FIRST,
   1378 		TEST_CASE_INVALID_INT_TO_SUBROUTINE_UNIFORM_ASSIGNMENT,
   1379 		TEST_CASE_INVALID_SUBROUTINE_UNIFORM_VALUE_COMPARISON,
   1380 
   1381 		/* Always last */
   1382 		TEST_CASE_COUNT
   1383 	};
   1384 
   1385 	/* Private methods */
   1386 	std::string getTestCaseString(const _test_case& test_case);
   1387 	std::string getVertexShader(const _test_case& test_case);
   1388 
   1389 	/* Private fields */
   1390 	bool		m_has_test_passed;
   1391 	glw::GLuint m_po_id;
   1392 	glw::GLuint m_vs_id;
   1393 };
   1394 
   1395 /**
   1396  * Check that an overloaded function cannot be declared with subroutine and
   1397  * a program will fail to compile or link if any shader or stage contains
   1398  * two or more  functions with the same name if the name is associated with
   1399  * a subroutine type.
   1400  *
   1401  **/
   1402 class NegativeTest10 : public deqp::TestCase
   1403 {
   1404 public:
   1405 	/* Public methods */
   1406 	NegativeTest10(deqp::Context& context);
   1407 
   1408 	virtual void						 deinit();
   1409 	virtual tcu::TestNode::IterateResult iterate();
   1410 
   1411 private:
   1412 	/* Private type definitions */
   1413 	struct _test_case
   1414 	{
   1415 		std::string name;
   1416 
   1417 		std::string fs_body;
   1418 		std::string gs_body;
   1419 		std::string tc_body;
   1420 		std::string te_body;
   1421 		std::string vs_body;
   1422 	};
   1423 
   1424 	typedef std::vector<_test_case>		_test_cases;
   1425 	typedef _test_cases::const_iterator _test_cases_const_iterator;
   1426 
   1427 	/* Private methods */
   1428 	std::string getFragmentShader(bool include_duplicate_function);
   1429 	std::string getGeometryShader(bool include_duplicate_function);
   1430 	std::string getTessellationControlShader(bool include_duplicate_function);
   1431 	std::string getTessellationEvaluationShader(bool include_duplicate_function);
   1432 	std::string getVertexShader(bool include_duplicate_function);
   1433 	void initTestCases();
   1434 
   1435 	/* Private fields */
   1436 	bool		m_has_test_passed;
   1437 	glw::GLuint m_fs_id;
   1438 	glw::GLuint m_gs_id;
   1439 	glw::GLuint m_po_id;
   1440 	glw::GLuint m_tc_id;
   1441 	glw::GLuint m_te_id;
   1442 	_test_cases m_test_cases;
   1443 	glw::GLuint m_vs_id;
   1444 };
   1445 
   1446 /**
   1447  *   Try to use subroutine uniform in invalid way in sampling, atomic and
   1448  *   image functions. Verify that compile or link time error occurs.
   1449  *
   1450  **/
   1451 class NegativeTest11 : public deqp::TestCase
   1452 {
   1453 public:
   1454 	/* Public methods */
   1455 	NegativeTest11(deqp::Context& context);
   1456 
   1457 	virtual void						 deinit();
   1458 	virtual tcu::TestNode::IterateResult iterate();
   1459 
   1460 private:
   1461 	/* Private type definitions */
   1462 	enum _test_case
   1463 	{
   1464 		TEST_CASE_FIRST,
   1465 
   1466 		TEST_CASE_INVALID_TEXTURE_SAMPLING_ATTEMPT = TEST_CASE_FIRST,
   1467 		TEST_CASE_INVALID_ATOMIC_COUNTER_USAGE_ATTEMPT,
   1468 		TEST_CASE_INVALID_IMAGE_FUNCTION_USAGE_ATTEMPT,
   1469 
   1470 		/* Always last */
   1471 		TEST_CASE_COUNT
   1472 	};
   1473 
   1474 	/* Private methods */
   1475 	std::string getTestCaseString(const _test_case& test_case);
   1476 	std::string getVertexShader(const _test_case& test_case);
   1477 
   1478 	/* Private fields */
   1479 	bool		m_has_test_passed;
   1480 	glw::GLuint m_po_id;
   1481 	glw::GLuint m_vs_id;
   1482 };
   1483 
   1484 /**
   1485  *  Verify that it is not allowed to use subroutine type for local/global
   1486  *  variables, constructors or argument/return type.
   1487  *
   1488  **/
   1489 class NegativeTest12 : public deqp::TestCase
   1490 {
   1491 public:
   1492 	/* Public methods */
   1493 	NegativeTest12(deqp::Context& context);
   1494 
   1495 	virtual void						 deinit();
   1496 	virtual tcu::TestNode::IterateResult iterate();
   1497 
   1498 private:
   1499 	/* Private type definitions */
   1500 	enum _test_case
   1501 	{
   1502 		TEST_CASE_FIRST,
   1503 
   1504 		TEST_CASE_INVALID_LOCAL_SUBROUTINE_VARIABLE = TEST_CASE_FIRST,
   1505 		TEST_CASE_INVALID_GLOBAL_SUBROUTINE_VARIABLE,
   1506 		TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR,
   1507 		TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_ARGUMENT,
   1508 		TEST_CASE_SUBROUTINE_USED_AS_CONSTRUCTOR_RETURN_TYPE,
   1509 
   1510 		/* Always last */
   1511 		TEST_CASE_COUNT
   1512 	};
   1513 
   1514 	/* Private methods */
   1515 	std::string getTestCaseString(const _test_case& test_case);
   1516 	std::string getVertexShader(const _test_case& test_case);
   1517 
   1518 	/* Private fields */
   1519 	bool		m_has_test_passed;
   1520 	glw::GLuint m_po_id;
   1521 	glw::GLuint m_vs_id;
   1522 };
   1523 } /* ShaderSubroutine */
   1524 
   1525 /** Group class for Shader Subroutine conformance tests */
   1526 class ShaderSubroutineTests : public deqp::TestCaseGroup
   1527 {
   1528 public:
   1529 	/* Public methods */
   1530 	ShaderSubroutineTests(deqp::Context& context);
   1531 	virtual ~ShaderSubroutineTests()
   1532 	{
   1533 	}
   1534 
   1535 	virtual void init(void);
   1536 
   1537 private:
   1538 	/* Private methods */
   1539 	ShaderSubroutineTests(const ShaderSubroutineTests&);
   1540 	ShaderSubroutineTests& operator=(const ShaderSubroutineTests&);
   1541 };
   1542 
   1543 } /* gl4cts namespace */
   1544 
   1545 #endif // _GL4CSHADERSUBROUTINETESTS_HPP
   1546