Home | History | Annotate | Download | only in common
      1 /*-------------------------------------------------------------------------
      2  * OpenGL Conformance Test Suite
      3  * -----------------------------
      4  *
      5  * Copyright (c) 2017 The Khronos Group Inc.
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  *
     19  */ /*!
     20  * \file  glcMultipleContextsTests.cpp
     21  * \brief
     22  */ /*-------------------------------------------------------------------*/
     23 
     24 #include "glcMultipleContextsTests.hpp"
     25 #include "deSharedPtr.hpp"
     26 #include "gl4cShaderSubroutineTests.hpp"
     27 #include "gluContextInfo.hpp"
     28 #include "glwEnums.hpp"
     29 #include "glwFunctions.hpp"
     30 #include "tcuMatrix.hpp"
     31 #include <cmath>
     32 #include <cstring>
     33 #include <deMath.h>
     34 
     35 using namespace glw;
     36 using namespace gl4cts::ShaderSubroutine;
     37 
     38 namespace glcts
     39 {
     40 
     41 /**
     42  * * Create multiple contexts and verify that subroutine uniforms values
     43  *   are preserved for each program stage when switching rendering context.
     44  *
     45  * OpenGL 4.1 or ARB_separate_shader_objects support required
     46  * * Same as above, but use pipelines instead of monolithic program.
     47  **/
     48 class UniformPreservationTest : public tcu::TestCase
     49 {
     50 public:
     51 	/* Public methods */
     52 	UniformPreservationTest(tcu::TestContext& testCtx, glu::ApiType apiType);
     53 
     54 	virtual void						 deinit();
     55 	virtual tcu::TestNode::IterateResult iterate();
     56 
     57 private:
     58 	/* Private types */
     59 	struct subroutineUniformSet
     60 	{
     61 		bool operator!=(const subroutineUniformSet& arg) const;
     62 		void set(glw::GLuint bit_field, const subroutineUniformSet subroutine_indices[2]);
     63 
     64 		glw::GLuint m_vertex_shader_stage;
     65 		glw::GLuint m_tesselation_control_shader_stage;
     66 		glw::GLuint m_tesselation_evaluation_shader_stage;
     67 		glw::GLuint m_geometry_shader_stage;
     68 		glw::GLuint m_fragment_shader_stage;
     69 	};
     70 
     71 	/* Private methods */
     72 	void captureCurrentSubroutineSet(subroutineUniformSet& set);
     73 
     74 	void getShaders(const glw::GLchar*& out_vertex_shader_code, const glw::GLchar*& out_tesselation_control_shader_code,
     75 					const glw::GLchar*& out_tesselation_evaluation_shader_code,
     76 					const glw::GLchar*& out_geometry_shader_code, const glw::GLchar*& out_fragment_shader_code);
     77 
     78 	void initSharedContexts();
     79 
     80 	void prepareProgram(Utils::program** programs, bool is_separable);
     81 
     82 	void prepareProgramPipeline(glw::GLuint& pipeline_id, Utils::program** programs);
     83 
     84 	bool testCase(const glw::GLuint bit_field[5]);
     85 
     86 	bool testProgram(Utils::program** programs, bool is_separable, const glw::GLuint test_cases[][5],
     87 					 glw::GLuint n_test_cases);
     88 
     89 	void updateCurrentSubroutineSet(const subroutineUniformSet& set);
     90 
     91 	/* Private fields */
     92 	static const glw::GLuint m_n_shared_contexts;
     93 	static const glw::GLuint m_fragment_stage_index;
     94 	static const glw::GLuint m_geometry_stage_index;
     95 	static const glw::GLuint m_tesselation_control_stage_index;
     96 	static const glw::GLuint m_tesselation_evaluation_stage_index;
     97 	static const glw::GLuint m_vertex_stage_index;
     98 
     99 	glu::ApiType				 m_api_type;
    100 	de::SharedPtr<deqp::Context> m_base_context;
    101 	glu::RenderContext*			 m_shared_contexts[4];
    102 	glw::GLuint					 m_program_pipelines[5];
    103 	subroutineUniformSet		 m_subroutine_indices[2];
    104 	subroutineUniformSet		 m_subroutine_uniform_locations;
    105 };
    106 
    107 /* Constants used by FunctionalTest20_21 */
    108 const GLuint UniformPreservationTest::m_n_shared_contexts				   = 4;
    109 const GLuint UniformPreservationTest::m_fragment_stage_index			   = 0;
    110 const GLuint UniformPreservationTest::m_geometry_stage_index			   = 1;
    111 const GLuint UniformPreservationTest::m_tesselation_control_stage_index	= 2;
    112 const GLuint UniformPreservationTest::m_tesselation_evaluation_stage_index = 3;
    113 const GLuint UniformPreservationTest::m_vertex_stage_index				   = 4;
    114 
    115 /** Set subroutine indices, indices are taken from one of two sets according to provided <bit_field>
    116  *
    117  * @param bit_field          Selects source of of index for each stage
    118  * @param subroutine_indices Array of two indices sets
    119  **/
    120 void UniformPreservationTest::subroutineUniformSet::set(GLuint					   bit_field,
    121 														const subroutineUniformSet subroutine_indices[2])
    122 {
    123 	GLuint vertex_stage					= ((bit_field & (0x01 << 0)) >> 0);
    124 	GLuint tesselation_control_stage	= ((bit_field & (0x01 << 1)) >> 1);
    125 	GLuint tesselation_evaluation_stage = ((bit_field & (0x01 << 2)) >> 2);
    126 	GLuint geometry_stage				= ((bit_field & (0x01 << 3)) >> 3);
    127 	GLuint fragment_stage				= ((bit_field & (0x01 << 4)) >> 4);
    128 
    129 	m_vertex_shader_stage = subroutine_indices[vertex_stage].m_vertex_shader_stage;
    130 	m_tesselation_control_shader_stage =
    131 		subroutine_indices[tesselation_control_stage].m_tesselation_control_shader_stage;
    132 	m_tesselation_evaluation_shader_stage =
    133 		subroutine_indices[tesselation_evaluation_stage].m_tesselation_evaluation_shader_stage;
    134 	m_geometry_shader_stage = subroutine_indices[geometry_stage].m_geometry_shader_stage;
    135 	m_fragment_shader_stage = subroutine_indices[fragment_stage].m_fragment_shader_stage;
    136 }
    137 
    138 /** Negated comparison of two sets
    139  *
    140  * @param arg Instance that will be compared to this
    141  *
    142  * @return false when both objects are equal, true otherwise
    143  **/
    144 bool UniformPreservationTest::subroutineUniformSet::operator!=(const subroutineUniformSet& arg) const
    145 {
    146 	if ((arg.m_vertex_shader_stage != m_vertex_shader_stage) ||
    147 		(arg.m_tesselation_control_shader_stage != m_tesselation_control_shader_stage) ||
    148 		(arg.m_tesselation_evaluation_shader_stage != m_tesselation_evaluation_shader_stage) ||
    149 		(arg.m_geometry_shader_stage != m_geometry_shader_stage) ||
    150 		(arg.m_fragment_shader_stage != m_fragment_shader_stage))
    151 	{
    152 		return true;
    153 	}
    154 
    155 	return false;
    156 }
    157 
    158 /** Constructor.
    159  *
    160  *  @param context Rendering context.
    161  *
    162  **/
    163 UniformPreservationTest::UniformPreservationTest(tcu::TestContext& testCtx, glu::ApiType apiType)
    164 	: tcu::TestCase(testCtx, "uniform_preservation",
    165 					"Verifies that shader uniforms are preserved when rendering context is switched.")
    166 	, m_api_type(apiType)
    167 {
    168 	for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i)
    169 	{
    170 		m_program_pipelines[i] = 0;
    171 	}
    172 
    173 	for (GLuint i = 0; i < m_n_shared_contexts; ++i)
    174 	{
    175 		m_shared_contexts[i] = 0;
    176 	}
    177 }
    178 
    179 /** Deinitializes all GL objects that may have been created during
    180  *  test execution.
    181  **/
    182 void UniformPreservationTest::deinit()
    183 {
    184 	/* GL entry points */
    185 	const glw::Functions& gl = m_base_context->getRenderContext().getFunctions();
    186 
    187 	for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i)
    188 	{
    189 		if (0 != m_program_pipelines[i])
    190 		{
    191 			gl.deleteProgramPipelines(1, &m_program_pipelines[i]);
    192 			m_program_pipelines[i] = 0;
    193 		}
    194 	}
    195 
    196 	for (GLuint i = 0; i < m_n_shared_contexts; ++i)
    197 	{
    198 		if (0 != m_shared_contexts[i])
    199 		{
    200 			delete m_shared_contexts[i];
    201 			m_shared_contexts[i] = 0;
    202 		}
    203 	}
    204 }
    205 
    206 /** Executes test iteration.
    207  *
    208  *  @return Returns STOP
    209  */
    210 tcu::TestNode::IterateResult UniformPreservationTest::iterate()
    211 {
    212 	/* Test cases, values stored here are used as bit fields */
    213 	static const GLuint test_cases[][m_n_shared_contexts + 1] = {
    214 		{ 0, 1, 2, 3, 4 },		{ 1, 2, 3, 4, 0 },		{ 2, 3, 4, 0, 1 },		{ 3, 4, 0, 1, 2 },
    215 		{ 4, 0, 1, 2, 3 },		{ 27, 28, 29, 30, 31 }, { 28, 29, 30, 31, 27 }, { 29, 30, 31, 27, 28 },
    216 		{ 30, 31, 27, 28, 29 }, { 31, 27, 28, 29, 30 },
    217 	};
    218 	static const GLuint n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
    219 
    220 	glu::ContextType context_type(m_api_type);
    221 	m_base_context = de::SharedPtr<deqp::Context>(new deqp::Context(m_testCtx, context_type));
    222 
    223 	/* Do not execute the test if GL_ARB_shader_subroutine is not supported */
    224 	if (!m_base_context->getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
    225 	{
    226 		throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
    227 	}
    228 
    229 	/* Prepare contexts */
    230 	initSharedContexts();
    231 
    232 	/* Test result */
    233 	bool result = true;
    234 
    235 	/* Program pointers */
    236 	Utils::program* program_pointers[5];
    237 
    238 	/* Test monolithic program */
    239 	{
    240 		/* Prepare program */
    241 		Utils::program program(*m_base_context.get());
    242 
    243 		program_pointers[m_fragment_stage_index] = &program;
    244 
    245 		prepareProgram(program_pointers, false);
    246 
    247 		/* Execute test */
    248 		if (false == testProgram(program_pointers, false, test_cases, n_test_cases))
    249 		{
    250 			m_testCtx.getLog() << tcu::TestLog::Message << "Last error message was caused by monolithic program."
    251 							   << tcu::TestLog::EndMessage;
    252 
    253 			result = false;
    254 		}
    255 	}
    256 
    257 	/* Test separable programs */
    258 	if (true == m_base_context->getContextInfo().isExtensionSupported("GL_ARB_separate_shader_objects"))
    259 	{
    260 		/* Prepare programs */
    261 		Utils::program vertex_program(*m_base_context.get());
    262 		Utils::program tesselation_control_program(*m_base_context.get());
    263 		Utils::program tesselation_evaluation_program(*m_base_context.get());
    264 		Utils::program geometry_program(*m_base_context.get());
    265 		Utils::program fragment_program(*m_base_context.get());
    266 
    267 		program_pointers[m_fragment_stage_index]			   = &fragment_program;
    268 		program_pointers[m_geometry_stage_index]			   = &geometry_program;
    269 		program_pointers[m_tesselation_control_stage_index]	= &tesselation_control_program;
    270 		program_pointers[m_tesselation_evaluation_stage_index] = &tesselation_evaluation_program;
    271 		program_pointers[m_vertex_stage_index]				   = &vertex_program;
    272 
    273 		prepareProgram(program_pointers, true);
    274 
    275 		/* Execute test */
    276 		if (false == testProgram(program_pointers, true, test_cases, n_test_cases))
    277 		{
    278 			m_testCtx.getLog() << tcu::TestLog::Message << "Last error message was caused by separable program."
    279 							   << tcu::TestLog::EndMessage;
    280 			result = false;
    281 		}
    282 	}
    283 
    284 	/* All done */
    285 	if (true == result)
    286 	{
    287 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    288 	}
    289 	else
    290 	{
    291 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
    292 	}
    293 
    294 	return tcu::TestNode::STOP;
    295 }
    296 
    297 /** Query state of subroutine uniforms of current program/pipeline
    298  *
    299  * @param set Storage for results
    300  **/
    301 void UniformPreservationTest::captureCurrentSubroutineSet(subroutineUniformSet& set)
    302 {
    303 	/* GL entry points */
    304 	const glw::Functions& gl = m_base_context->getRenderContext().getFunctions();
    305 
    306 	/* Fragment */
    307 	gl.getUniformSubroutineuiv(GL_FRAGMENT_SHADER, m_subroutine_uniform_locations.m_fragment_shader_stage,
    308 							   &set.m_fragment_shader_stage);
    309 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
    310 
    311 	/* Geometry */
    312 	gl.getUniformSubroutineuiv(GL_GEOMETRY_SHADER, m_subroutine_uniform_locations.m_geometry_shader_stage,
    313 							   &set.m_geometry_shader_stage);
    314 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
    315 
    316 	/* Tess ctrl */
    317 	gl.getUniformSubroutineuiv(GL_TESS_CONTROL_SHADER,
    318 							   m_subroutine_uniform_locations.m_tesselation_control_shader_stage,
    319 							   &set.m_tesselation_control_shader_stage);
    320 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
    321 
    322 	/* Tess eval */
    323 	gl.getUniformSubroutineuiv(GL_TESS_EVALUATION_SHADER,
    324 							   m_subroutine_uniform_locations.m_tesselation_evaluation_shader_stage,
    325 							   &set.m_tesselation_evaluation_shader_stage);
    326 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
    327 
    328 	/* Vertex */
    329 	gl.getUniformSubroutineuiv(GL_VERTEX_SHADER, m_subroutine_uniform_locations.m_vertex_shader_stage,
    330 							   &set.m_vertex_shader_stage);
    331 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
    332 }
    333 
    334 /** Get shaders' source code
    335  *
    336  * @param out_vertex_shader_code                 Vertex source code
    337  * @param out_tesselation_control_shader_code    Tess ctrl source code
    338  * @param out_tesselation_evaluation_shader_code Tess eval source code
    339  * @param out_geometry_shader_code               Geometry source code
    340  * @param out_fragment_shader_code               Fragment source code
    341  **/
    342 void UniformPreservationTest::getShaders(const glw::GLchar*& out_vertex_shader_code,
    343 										 const glw::GLchar*& out_tesselation_control_shader_code,
    344 										 const glw::GLchar*& out_tesselation_evaluation_shader_code,
    345 										 const glw::GLchar*& out_geometry_shader_code,
    346 										 const glw::GLchar*& out_fragment_shader_code)
    347 {
    348 	static const GLchar* vertex_shader_code = "#version 400 core\n"
    349 											  "#extension GL_ARB_shader_subroutine : require\n"
    350 											  "\n"
    351 											  "precision highp float;\n"
    352 											  "\n"
    353 											  "// Subroutine type\n"
    354 											  "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
    355 											  "\n"
    356 											  "// Subroutine definition\n"
    357 											  "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
    358 											  "{\n"
    359 											  "    return left + right;\n"
    360 											  "}\n"
    361 											  "\n"
    362 											  "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
    363 											  "{\n"
    364 											  "    return left * right;\n"
    365 											  "}\n"
    366 											  "\n"
    367 											  "// Sub routine uniform\n"
    368 											  "subroutine uniform routine_type routine;\n"
    369 											  "\n"
    370 											  "// Input data\n"
    371 											  "uniform vec4 uni_vs_left;\n"
    372 											  "uniform vec4 uni_vs_right;\n"
    373 											  "\n"
    374 											  "// Output\n"
    375 											  "out vec4 vs_tcs_result;\n"
    376 											  "\n"
    377 											  "void main()\n"
    378 											  "{\n"
    379 											  "    vs_tcs_result = routine(uni_vs_left, uni_vs_right);\n"
    380 											  "}\n"
    381 											  "\n";
    382 
    383 	static const GLchar* tesselation_control_shader_code =
    384 		"#version 400 core\n"
    385 		"#extension GL_ARB_shader_subroutine : require\n"
    386 		"\n"
    387 		"precision highp float;\n"
    388 		"\n"
    389 		"layout(vertices = 1) out;\n"
    390 		"\n"
    391 		"// Subroutine type\n"
    392 		"subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
    393 		"\n"
    394 		"// Subroutine definition\n"
    395 		"subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
    396 		"{\n"
    397 		"    return left + right;\n"
    398 		"}\n"
    399 		"\n"
    400 		"subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
    401 		"{\n"
    402 		"    return left * right;\n"
    403 		"}\n"
    404 		"\n"
    405 		"// Sub routine uniform\n"
    406 		"subroutine uniform routine_type routine;\n"
    407 		"\n"
    408 		"// Input data\n"
    409 		"uniform vec4 uni_tcs_left;\n"
    410 		"uniform vec4 uni_tcs_right;\n"
    411 		"\n"
    412 		"in vec4 vs_tcs_result[];\n"
    413 		"\n"
    414 		"// Output\n"
    415 		"out vec4 tcs_tes_result[];\n"
    416 		"\n"
    417 		"void main()\n"
    418 		"{\n"
    419 		"    gl_TessLevelOuter[0] = 1.0;\n"
    420 		"    gl_TessLevelOuter[1] = 1.0;\n"
    421 		"    gl_TessLevelOuter[2] = 1.0;\n"
    422 		"    gl_TessLevelOuter[3] = 1.0;\n"
    423 		"    gl_TessLevelInner[0] = 1.0;\n"
    424 		"    gl_TessLevelInner[1] = 1.0;\n"
    425 		"\n"
    426 		"    tcs_tes_result[gl_InvocationID] = routine(uni_tcs_left, uni_tcs_right) + vs_tcs_result[gl_InvocationID];\n"
    427 		"}\n"
    428 		"\n";
    429 
    430 	static const GLchar* tesselation_evaluation_shader_code =
    431 		"#version 400 core\n"
    432 		"#extension GL_ARB_shader_subroutine : require\n"
    433 		"\n"
    434 		"precision highp float;\n"
    435 		"\n"
    436 		"layout(isolines, point_mode) in;\n"
    437 		"\n"
    438 		"// Subroutine type\n"
    439 		"subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
    440 		"\n"
    441 		"// Subroutine definition\n"
    442 		"subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
    443 		"{\n"
    444 		"    return left + right;\n"
    445 		"}\n"
    446 		"\n"
    447 		"subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
    448 		"{\n"
    449 		"    return left * right;\n"
    450 		"}\n"
    451 		"\n"
    452 		"// Sub routine uniform\n"
    453 		"subroutine uniform routine_type routine;\n"
    454 		"\n"
    455 		"// Input data\n"
    456 		"uniform vec4 uni_tes_left;\n"
    457 		"uniform vec4 uni_tes_right;\n"
    458 		"\n"
    459 		"in vec4 tcs_tes_result[];\n"
    460 		"\n"
    461 		"// Output\n"
    462 		"out vec4 tes_gs_result;\n"
    463 		"\n"
    464 		"void main()\n"
    465 		"{\n"
    466 		"    tes_gs_result = routine(uni_tes_left, uni_tes_right) + tcs_tes_result[0];\n"
    467 		"}\n"
    468 		"\n";
    469 
    470 	static const GLchar* geometry_shader_code =
    471 		"#version 400 core\n"
    472 		"#extension GL_ARB_shader_subroutine : require\n"
    473 		"\n"
    474 		"precision highp float;\n"
    475 		"\n"
    476 		"layout(points)                   in;\n"
    477 		"layout(points, max_vertices = 1) out;\n"
    478 		"\n"
    479 		"// Subroutine type\n"
    480 		"subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
    481 		"\n"
    482 		"// Subroutine definition\n"
    483 		"subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
    484 		"{\n"
    485 		"    return left + right;\n"
    486 		"}\n"
    487 		"\n"
    488 		"subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
    489 		"{\n"
    490 		"    return left * right;\n"
    491 		"}\n"
    492 		"\n"
    493 		"// Sub routine uniform\n"
    494 		"subroutine uniform routine_type routine;\n"
    495 		"\n"
    496 		"// Input data\n"
    497 		"uniform vec4 uni_gs_left;\n"
    498 		"uniform vec4 uni_gs_right;\n"
    499 		"\n"
    500 		"in vec4 tes_gs_result[];\n"
    501 		"\n"
    502 		"// Output\n"
    503 		"out vec4 gs_fs_result;\n"
    504 		"\n"
    505 		"void main()\n"
    506 		"{\n"
    507 		"    gs_fs_result = routine(uni_gs_left, uni_gs_right) + tes_gs_result[0];\n"
    508 		"}\n"
    509 		"\n";
    510 
    511 	static const GLchar* fragmenty_shader_code =
    512 		"#version 400 core\n"
    513 		"#extension GL_ARB_shader_subroutine : require\n"
    514 		"\n"
    515 		"precision highp float;\n"
    516 		"\n"
    517 		"// Subroutine type\n"
    518 		"subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
    519 		"\n"
    520 		"// Subroutine definition\n"
    521 		"subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
    522 		"{\n"
    523 		"    return left + right;\n"
    524 		"}\n"
    525 		"\n"
    526 		"subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
    527 		"{\n"
    528 		"    return left * right;\n"
    529 		"}\n"
    530 		"\n"
    531 		"// Sub routine uniform\n"
    532 		"subroutine uniform routine_type routine;\n"
    533 		"\n"
    534 		"// Input data\n"
    535 		"uniform vec4 uni_fs_left;\n"
    536 		"uniform vec4 uni_fs_right;\n"
    537 		"\n"
    538 		"in vec4 gs_fs_result;\n"
    539 		"\n"
    540 		"// Output\n"
    541 		"out vec4 fs_out_result;\n"
    542 		"\n"
    543 		"void main()\n"
    544 		"{\n"
    545 		"    fs_out_result = routine(uni_fs_left, uni_fs_right) + gs_fs_result;\n"
    546 		"}\n"
    547 		"\n";
    548 
    549 	out_vertex_shader_code				   = vertex_shader_code;
    550 	out_tesselation_control_shader_code	= tesselation_control_shader_code;
    551 	out_tesselation_evaluation_shader_code = tesselation_evaluation_shader_code;
    552 	out_geometry_shader_code			   = geometry_shader_code;
    553 	out_fragment_shader_code			   = fragmenty_shader_code;
    554 }
    555 
    556 /** Create <m_n_shared_contexts> shared contexts
    557  *
    558  **/
    559 void UniformPreservationTest::initSharedContexts()
    560 {
    561 	glu::ContextType		context_type(m_api_type);
    562 	glu::RenderConfig		render_config(context_type);
    563 	const tcu::CommandLine& command_line(m_testCtx.getCommandLine());
    564 	glu::RenderContext*		shared_context = &(m_base_context->getRenderContext());
    565 	glu::parseRenderConfig(&render_config, command_line);
    566 
    567 #if (DE_OS == DE_OS_ANDROID)
    568 	// Android can only have one Window created at a time
    569 	// Note that this surface type is not supported on all platforms
    570 	render_config.surfaceType = glu::RenderConfig::SURFACETYPE_OFFSCREEN_GENERIC;
    571 #endif
    572 
    573 	for (GLuint i = 0; i < m_n_shared_contexts; ++i)
    574 	{
    575 		m_shared_contexts[i] =
    576 			glu::createRenderContext(m_testCtx.getPlatform(), command_line, render_config, shared_context);
    577 	}
    578 	m_base_context->getRenderContext().makeCurrent();
    579 }
    580 
    581 /** Prepare program(s)
    582  *
    583  * @param programs     An array of 5 programs' pointers. If monolithic program is prepared that only index m_fragment_stage_index should be initialized, otherwise all 5
    584  * @param is_separable Select if monolithic or separable programs should be prepared
    585  **/
    586 void UniformPreservationTest::prepareProgram(Utils::program** programs, bool is_separable)
    587 {
    588 	/* Get shader sources */
    589 	const GLchar* vertex_shader_code;
    590 	const GLchar* tesselation_control_shader_code;
    591 	const GLchar* tesselation_evaluation_shader_code;
    592 	const GLchar* geometry_shader_code;
    593 	const GLchar* fragmenty_shader_code;
    594 
    595 	getShaders(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code,
    596 			   geometry_shader_code, fragmenty_shader_code);
    597 
    598 	/* Subroutines and uniform names */
    599 	static const GLchar* subroutine_names[] = { "add", "multiply" };
    600 	static const GLuint  n_subroutines		= sizeof(subroutine_names) / sizeof(subroutine_names[0]);
    601 
    602 	static const GLchar* subroutine_uniform_name = "routine";
    603 
    604 	/* Build program */
    605 	if (false == is_separable)
    606 	{
    607 		programs[0]->build(0 /* compute shader source */, fragmenty_shader_code, geometry_shader_code,
    608 						   tesselation_control_shader_code, tesselation_evaluation_shader_code, vertex_shader_code,
    609 						   0 /* varying_names */, 0 /* n_varying_names */);
    610 
    611 		programs[m_geometry_stage_index]			   = programs[m_fragment_stage_index];
    612 		programs[m_tesselation_control_stage_index]	= programs[m_fragment_stage_index];
    613 		programs[m_tesselation_evaluation_stage_index] = programs[m_fragment_stage_index];
    614 		programs[m_vertex_stage_index]				   = programs[m_fragment_stage_index];
    615 	}
    616 	else
    617 	{
    618 		programs[m_fragment_stage_index]->build(0, fragmenty_shader_code, 0, 0, 0, 0, 0, 0, true);
    619 		programs[m_geometry_stage_index]->build(0, 0, geometry_shader_code, 0, 0, 0, 0, 0, true);
    620 		programs[m_tesselation_control_stage_index]->build(0, 0, 0, tesselation_control_shader_code, 0, 0, 0, 0, true);
    621 		programs[m_tesselation_evaluation_stage_index]->build(0, 0, 0, 0, tesselation_evaluation_shader_code, 0, 0, 0,
    622 															  true);
    623 		programs[m_vertex_stage_index]->build(0, 0, 0, 0, 0, vertex_shader_code, 0, 0, true);
    624 	}
    625 
    626 	/* Get subroutine indices */
    627 	for (GLuint i = 0; i < n_subroutines; ++i)
    628 	{
    629 		m_subroutine_indices[i].m_fragment_shader_stage =
    630 			programs[m_fragment_stage_index]->getSubroutineIndex(subroutine_names[i], GL_FRAGMENT_SHADER);
    631 
    632 		m_subroutine_indices[i].m_geometry_shader_stage =
    633 			programs[m_geometry_stage_index]->getSubroutineIndex(subroutine_names[i], GL_GEOMETRY_SHADER);
    634 
    635 		m_subroutine_indices[i].m_tesselation_control_shader_stage =
    636 			programs[m_tesselation_control_stage_index]->getSubroutineIndex(subroutine_names[i],
    637 																			GL_TESS_CONTROL_SHADER);
    638 
    639 		m_subroutine_indices[i].m_tesselation_evaluation_shader_stage =
    640 			programs[m_tesselation_evaluation_stage_index]->getSubroutineIndex(subroutine_names[i],
    641 																			   GL_TESS_EVALUATION_SHADER);
    642 
    643 		m_subroutine_indices[i].m_vertex_shader_stage =
    644 			programs[m_vertex_stage_index]->getSubroutineIndex(subroutine_names[i], GL_VERTEX_SHADER);
    645 	}
    646 
    647 	/* Get subroutine uniform locations */
    648 	m_subroutine_uniform_locations.m_fragment_shader_stage =
    649 		programs[m_fragment_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name, GL_FRAGMENT_SHADER);
    650 
    651 	m_subroutine_uniform_locations.m_geometry_shader_stage =
    652 		programs[m_geometry_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name, GL_GEOMETRY_SHADER);
    653 
    654 	m_subroutine_uniform_locations.m_tesselation_control_shader_stage =
    655 		programs[m_tesselation_control_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name,
    656 																				  GL_TESS_CONTROL_SHADER);
    657 
    658 	m_subroutine_uniform_locations.m_tesselation_evaluation_shader_stage =
    659 		programs[m_tesselation_evaluation_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name,
    660 																					 GL_TESS_EVALUATION_SHADER);
    661 
    662 	m_subroutine_uniform_locations.m_vertex_shader_stage =
    663 		programs[m_vertex_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name, GL_VERTEX_SHADER);
    664 }
    665 
    666 /** Generate program pipeline for current context and attach separable programs
    667  *
    668  * @param out_pipeline_id Id of generated pipeline
    669  * @param programs        Collection of separable programs
    670  **/
    671 void UniformPreservationTest::prepareProgramPipeline(glw::GLuint& out_pipeline_id, Utils::program** programs)
    672 {
    673 	/* GL entry points */
    674 	const glw::Functions& gl = m_base_context->getRenderContext().getFunctions();
    675 
    676 	/* Generate */
    677 	gl.genProgramPipelines(1, &out_pipeline_id);
    678 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenProgramPipelines");
    679 
    680 	/* Bind */
    681 	gl.bindProgramPipeline(out_pipeline_id);
    682 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindProgramPipeline");
    683 
    684 	/* Set up programs */
    685 	gl.useProgramStages(out_pipeline_id, GL_FRAGMENT_SHADER_BIT, programs[m_fragment_stage_index]->m_program_object_id);
    686 	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
    687 
    688 	gl.useProgramStages(out_pipeline_id, GL_GEOMETRY_SHADER_BIT, programs[m_geometry_stage_index]->m_program_object_id);
    689 	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
    690 
    691 	gl.useProgramStages(out_pipeline_id, GL_TESS_CONTROL_SHADER_BIT,
    692 						programs[m_tesselation_control_stage_index]->m_program_object_id);
    693 	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
    694 
    695 	gl.useProgramStages(out_pipeline_id, GL_TESS_EVALUATION_SHADER_BIT,
    696 						programs[m_tesselation_evaluation_stage_index]->m_program_object_id);
    697 	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
    698 
    699 	gl.useProgramStages(out_pipeline_id, GL_VERTEX_SHADER_BIT, programs[m_vertex_stage_index]->m_program_object_id);
    700 	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
    701 }
    702 
    703 /** Test specific case
    704  *
    705  * @param bit_field An array of 5 bit fields used to set up subroutine uniforms, one element per context
    706  *
    707  * @return True if test pass, false otherwise
    708  **/
    709 bool UniformPreservationTest::testCase(const glw::GLuint bit_field[5])
    710 {
    711 	/* Storage for subroutine indices */
    712 	subroutineUniformSet captured_subroutine_indices[m_n_shared_contexts + 1];
    713 	subroutineUniformSet subroutine_indices[m_n_shared_contexts + 1];
    714 
    715 	/* Prepare subroutine_indices with bit fields */
    716 	for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i)
    717 	{
    718 		subroutine_indices[i].set(bit_field[i], m_subroutine_indices);
    719 	};
    720 
    721 	/* Update subroutine uniforms, each context gets different set */
    722 	for (GLuint i = 0; i < m_n_shared_contexts; ++i)
    723 	{
    724 		m_shared_contexts[i]->makeCurrent();
    725 		updateCurrentSubroutineSet(subroutine_indices[i]);
    726 	}
    727 
    728 	m_base_context->getRenderContext().makeCurrent();
    729 	updateCurrentSubroutineSet(subroutine_indices[m_n_shared_contexts]);
    730 
    731 	/* Capture subroutine uniforms */
    732 	for (GLuint i = 0; i < m_n_shared_contexts; ++i)
    733 	{
    734 		m_shared_contexts[i]->makeCurrent();
    735 		captureCurrentSubroutineSet(captured_subroutine_indices[i]);
    736 	}
    737 
    738 	m_base_context->getRenderContext().makeCurrent();
    739 	captureCurrentSubroutineSet(captured_subroutine_indices[m_n_shared_contexts]);
    740 
    741 	/* Verify that captured uniforms match expected values */
    742 	for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i)
    743 	{
    744 		if (subroutine_indices[i] != captured_subroutine_indices[i])
    745 		{
    746 			m_testCtx.getLog() << tcu::TestLog::Message << "Error."
    747 							   << " Context: " << i << " VS, expected: " << subroutine_indices[i].m_vertex_shader_stage
    748 							   << " captured: " << captured_subroutine_indices[i].m_vertex_shader_stage
    749 							   << " TCS, expected: " << subroutine_indices[i].m_tesselation_control_shader_stage
    750 							   << " captured: " << captured_subroutine_indices[i].m_tesselation_control_shader_stage
    751 							   << " TES, expected: " << subroutine_indices[i].m_tesselation_evaluation_shader_stage
    752 							   << " captured: " << captured_subroutine_indices[i].m_tesselation_evaluation_shader_stage
    753 							   << " GS, expected: " << subroutine_indices[i].m_geometry_shader_stage
    754 							   << " captured: " << captured_subroutine_indices[i].m_geometry_shader_stage
    755 							   << " FS, expected: " << subroutine_indices[i].m_fragment_shader_stage
    756 							   << " captured: " << captured_subroutine_indices[i].m_fragment_shader_stage
    757 							   << tcu::TestLog::EndMessage;
    758 
    759 			return false;
    760 		}
    761 	}
    762 
    763 	return true;
    764 }
    765 
    766 /** Test a program or pipeline
    767  *
    768  * @param programs     An array of 5 programs\ pointers, as in preparePrograms
    769  * @param is_separable Selects if monolithic or separable programs should be used
    770  * @param test_cases   Collection of test cases
    771  * @param n_test_cases Number of test cases
    772  *
    773  * @return True if all cases pass, false otherwise
    774  **/
    775 bool UniformPreservationTest::testProgram(Utils::program** programs, bool is_separable,
    776 										  const glw::GLuint test_cases[][5], glw::GLuint n_test_cases)
    777 {
    778 	/* Set program/pipeline as current for all contexts */
    779 	if (false == is_separable)
    780 	{
    781 		programs[0]->use();
    782 
    783 		for (GLuint i = 0; i < m_n_shared_contexts; ++i)
    784 		{
    785 			m_shared_contexts[i]->makeCurrent();
    786 			programs[0]->use();
    787 		}
    788 	}
    789 	else
    790 	{
    791 		/* GL entry points */
    792 		const glw::Functions& gl = m_base_context->getRenderContext().getFunctions();
    793 
    794 		/* Make sure that program pipeline will be used */
    795 		gl.useProgram(0);
    796 		GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
    797 
    798 		prepareProgramPipeline(m_program_pipelines[m_n_shared_contexts], programs);
    799 
    800 		for (GLuint i = 0; i < m_n_shared_contexts; ++i)
    801 		{
    802 			m_shared_contexts[i]->makeCurrent();
    803 
    804 			/* Make sure that program pipeline will be used */
    805 			gl.useProgram(0);
    806 			GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
    807 
    808 			prepareProgramPipeline(m_program_pipelines[i], programs);
    809 		}
    810 	}
    811 
    812 	/* Execute test */
    813 	bool result = true;
    814 	for (GLuint i = 0; i < n_test_cases; ++i)
    815 	{
    816 		if (false == testCase(test_cases[i]))
    817 		{
    818 			result = false;
    819 			break;
    820 		}
    821 	}
    822 
    823 	return result;
    824 }
    825 
    826 /** Set up subroutine uniforms for current program or pipeline
    827  *
    828  * @param set Set of subroutine indices
    829  **/
    830 void UniformPreservationTest::updateCurrentSubroutineSet(const subroutineUniformSet& set)
    831 {
    832 	/* GL entry points */
    833 	const glw::Functions& gl = m_base_context->getRenderContext().getFunctions();
    834 
    835 	/* Fragment */
    836 	gl.uniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1 /* count */, &set.m_fragment_shader_stage);
    837 	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
    838 
    839 	/* Geometry */
    840 	gl.uniformSubroutinesuiv(GL_GEOMETRY_SHADER, 1 /* count */, &set.m_geometry_shader_stage);
    841 	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
    842 
    843 	/* Tess ctrl */
    844 	gl.uniformSubroutinesuiv(GL_TESS_CONTROL_SHADER, 1 /* count */, &set.m_tesselation_control_shader_stage);
    845 	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
    846 
    847 	/* Tess eval */
    848 	gl.uniformSubroutinesuiv(GL_TESS_EVALUATION_SHADER, 1 /* count */, &set.m_tesselation_evaluation_shader_stage);
    849 	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
    850 
    851 	/* Vertex */
    852 	gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, 1 /* count */, &set.m_vertex_shader_stage);
    853 	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
    854 }
    855 
    856 /** Constructor.
    857  *
    858  *  @param context Rendering context.
    859  **/
    860 MultipleContextsTests::MultipleContextsTests(tcu::TestContext& testCtx, glu::ApiType apiType)
    861 	: tcu::TestCaseGroup(testCtx, "multiple_contexts", "Verifies \"shader_subroutine\" functionality")
    862 	, m_apiType(apiType)
    863 {
    864 	/* Left blank on purpose */
    865 }
    866 
    867 /** Initializes a texture_storage_multisample test group.
    868  *
    869  **/
    870 void MultipleContextsTests::init(void)
    871 {
    872 	addChild(new UniformPreservationTest(m_testCtx, m_apiType));
    873 }
    874 
    875 } /* glcts namespace */
    876