1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
5 * Copyright (c) 2017 The Khronos Group Inc.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 * \file glcMultipleContextsTests.cpp
22 */ /*-------------------------------------------------------------------*/
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"
36 using namespace gl4cts::ShaderSubroutine;
42 * * Create multiple contexts and verify that subroutine uniforms values
43 * are preserved for each program stage when switching rendering context.
45 * OpenGL 4.1 or ARB_separate_shader_objects support required
46 * * Same as above, but use pipelines instead of monolithic program.
48 class UniformPreservationTest : public tcu::TestCase
52 UniformPreservationTest(tcu::TestContext& testCtx, glu::ApiType apiType);
54 virtual void deinit();
55 virtual tcu::TestNode::IterateResult iterate();
59 struct subroutineUniformSet
61 bool operator!=(const subroutineUniformSet& arg) const;
62 void set(glw::GLuint bit_field, const subroutineUniformSet subroutine_indices[2]);
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;
72 void captureCurrentSubroutineSet(subroutineUniformSet& set);
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);
78 void initSharedContexts();
80 void prepareProgram(Utils::program** programs, bool is_separable);
82 void prepareProgramPipeline(glw::GLuint& pipeline_id, Utils::program** programs);
84 bool testCase(const glw::GLuint bit_field[5]);
86 bool testProgram(Utils::program** programs, bool is_separable, const glw::GLuint test_cases[][5],
87 glw::GLuint n_test_cases);
89 void updateCurrentSubroutineSet(const subroutineUniformSet& set);
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;
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;
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;
115 /** Set subroutine indices, indices are taken from one of two sets according to provided <bit_field>
117 * @param bit_field Selects source of of index for each stage
118 * @param subroutine_indices Array of two indices sets
120 void UniformPreservationTest::subroutineUniformSet::set(GLuint bit_field,
121 const subroutineUniformSet subroutine_indices[2])
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);
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;
138 /** Negated comparison of two sets
140 * @param arg Instance that will be compared to this
142 * @return false when both objects are equal, true otherwise
144 bool UniformPreservationTest::subroutineUniformSet::operator!=(const subroutineUniformSet& arg) const
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))
160 * @param context Rendering context.
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)
168 for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i)
170 m_program_pipelines[i] = 0;
173 for (GLuint i = 0; i < m_n_shared_contexts; ++i)
175 m_shared_contexts[i] = 0;
179 /** Deinitializes all GL objects that may have been created during
182 void UniformPreservationTest::deinit()
184 /* GL entry points */
185 const glw::Functions& gl = m_base_context->getRenderContext().getFunctions();
187 for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i)
189 if (0 != m_program_pipelines[i])
191 gl.deleteProgramPipelines(1, &m_program_pipelines[i]);
192 m_program_pipelines[i] = 0;
196 for (GLuint i = 0; i < m_n_shared_contexts; ++i)
198 if (0 != m_shared_contexts[i])
200 delete m_shared_contexts[i];
201 m_shared_contexts[i] = 0;
206 /** Executes test iteration.
208 * @return Returns STOP
210 tcu::TestNode::IterateResult UniformPreservationTest::iterate()
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 },
218 static const GLuint n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
220 glu::ContextType context_type(m_api_type);
221 m_base_context = de::SharedPtr<deqp::Context>(new deqp::Context(m_testCtx, context_type));
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"))
226 throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
229 /* Prepare contexts */
230 initSharedContexts();
235 /* Program pointers */
236 Utils::program* program_pointers[5];
238 /* Test monolithic program */
240 /* Prepare program */
241 Utils::program program(*m_base_context.get());
243 program_pointers[m_fragment_stage_index] = &program;
245 prepareProgram(program_pointers, false);
248 if (false == testProgram(program_pointers, false, test_cases, n_test_cases))
250 m_testCtx.getLog() << tcu::TestLog::Message << "Last error message was caused by monolithic program."
251 << tcu::TestLog::EndMessage;
257 /* Test separable programs */
258 if (true == m_base_context->getContextInfo().isExtensionSupported("GL_ARB_separate_shader_objects"))
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());
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;
273 prepareProgram(program_pointers, true);
276 if (false == testProgram(program_pointers, true, test_cases, n_test_cases))
278 m_testCtx.getLog() << tcu::TestLog::Message << "Last error message was caused by separable program."
279 << tcu::TestLog::EndMessage;
287 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
291 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
294 return tcu::TestNode::STOP;
297 /** Query state of subroutine uniforms of current program/pipeline
299 * @param set Storage for results
301 void UniformPreservationTest::captureCurrentSubroutineSet(subroutineUniformSet& set)
303 /* GL entry points */
304 const glw::Functions& gl = m_base_context->getRenderContext().getFunctions();
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");
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");
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");
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");
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");
334 /** Get shaders' source code
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
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)
348 static const GLchar* vertex_shader_code = "#version 400 core\n"
349 "#extension GL_ARB_shader_subroutine : require\n"
351 "precision highp float;\n"
353 "// Subroutine type\n"
354 "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
356 "// Subroutine definition\n"
357 "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
359 " return left + right;\n"
362 "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
364 " return left * right;\n"
367 "// Sub routine uniform\n"
368 "subroutine uniform routine_type routine;\n"
371 "uniform vec4 uni_vs_left;\n"
372 "uniform vec4 uni_vs_right;\n"
375 "out vec4 vs_tcs_result;\n"
379 " vs_tcs_result = routine(uni_vs_left, uni_vs_right);\n"
383 static const GLchar* tesselation_control_shader_code =
384 "#version 400 core\n"
385 "#extension GL_ARB_shader_subroutine : require\n"
387 "precision highp float;\n"
389 "layout(vertices = 1) out;\n"
391 "// Subroutine type\n"
392 "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
394 "// Subroutine definition\n"
395 "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
397 " return left + right;\n"
400 "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
402 " return left * right;\n"
405 "// Sub routine uniform\n"
406 "subroutine uniform routine_type routine;\n"
409 "uniform vec4 uni_tcs_left;\n"
410 "uniform vec4 uni_tcs_right;\n"
412 "in vec4 vs_tcs_result[];\n"
415 "out vec4 tcs_tes_result[];\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"
426 " tcs_tes_result[gl_InvocationID] = routine(uni_tcs_left, uni_tcs_right) + vs_tcs_result[gl_InvocationID];\n"
430 static const GLchar* tesselation_evaluation_shader_code =
431 "#version 400 core\n"
432 "#extension GL_ARB_shader_subroutine : require\n"
434 "precision highp float;\n"
436 "layout(isolines, point_mode) in;\n"
438 "// Subroutine type\n"
439 "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
441 "// Subroutine definition\n"
442 "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
444 " return left + right;\n"
447 "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
449 " return left * right;\n"
452 "// Sub routine uniform\n"
453 "subroutine uniform routine_type routine;\n"
456 "uniform vec4 uni_tes_left;\n"
457 "uniform vec4 uni_tes_right;\n"
459 "in vec4 tcs_tes_result[];\n"
462 "out vec4 tes_gs_result;\n"
466 " tes_gs_result = routine(uni_tes_left, uni_tes_right) + tcs_tes_result[0];\n"
470 static const GLchar* geometry_shader_code =
471 "#version 400 core\n"
472 "#extension GL_ARB_shader_subroutine : require\n"
474 "precision highp float;\n"
476 "layout(points) in;\n"
477 "layout(points, max_vertices = 1) out;\n"
479 "// Subroutine type\n"
480 "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
482 "// Subroutine definition\n"
483 "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
485 " return left + right;\n"
488 "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
490 " return left * right;\n"
493 "// Sub routine uniform\n"
494 "subroutine uniform routine_type routine;\n"
497 "uniform vec4 uni_gs_left;\n"
498 "uniform vec4 uni_gs_right;\n"
500 "in vec4 tes_gs_result[];\n"
503 "out vec4 gs_fs_result;\n"
507 " gs_fs_result = routine(uni_gs_left, uni_gs_right) + tes_gs_result[0];\n"
511 static const GLchar* fragmenty_shader_code =
512 "#version 400 core\n"
513 "#extension GL_ARB_shader_subroutine : require\n"
515 "precision highp float;\n"
517 "// Subroutine type\n"
518 "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
520 "// Subroutine definition\n"
521 "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
523 " return left + right;\n"
526 "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
528 " return left * right;\n"
531 "// Sub routine uniform\n"
532 "subroutine uniform routine_type routine;\n"
535 "uniform vec4 uni_fs_left;\n"
536 "uniform vec4 uni_fs_right;\n"
538 "in vec4 gs_fs_result;\n"
541 "out vec4 fs_out_result;\n"
545 " fs_out_result = routine(uni_fs_left, uni_fs_right) + gs_fs_result;\n"
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;
556 /** Create <m_n_shared_contexts> shared contexts
559 void UniformPreservationTest::initSharedContexts()
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);
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;
573 for (GLuint i = 0; i < m_n_shared_contexts; ++i)
575 m_shared_contexts[i] =
576 glu::createRenderContext(m_testCtx.getPlatform(), command_line, render_config, shared_context);
578 m_base_context->getRenderContext().makeCurrent();
581 /** Prepare program(s)
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
586 void UniformPreservationTest::prepareProgram(Utils::program** programs, bool is_separable)
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;
595 getShaders(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code,
596 geometry_shader_code, fragmenty_shader_code);
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]);
602 static const GLchar* subroutine_uniform_name = "routine";
605 if (false == is_separable)
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 */);
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];
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,
623 programs[m_vertex_stage_index]->build(0, 0, 0, 0, 0, vertex_shader_code, 0, 0, true);
626 /* Get subroutine indices */
627 for (GLuint i = 0; i < n_subroutines; ++i)
629 m_subroutine_indices[i].m_fragment_shader_stage =
630 programs[m_fragment_stage_index]->getSubroutineIndex(subroutine_names[i], GL_FRAGMENT_SHADER);
632 m_subroutine_indices[i].m_geometry_shader_stage =
633 programs[m_geometry_stage_index]->getSubroutineIndex(subroutine_names[i], GL_GEOMETRY_SHADER);
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);
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);
643 m_subroutine_indices[i].m_vertex_shader_stage =
644 programs[m_vertex_stage_index]->getSubroutineIndex(subroutine_names[i], GL_VERTEX_SHADER);
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);
651 m_subroutine_uniform_locations.m_geometry_shader_stage =
652 programs[m_geometry_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name, GL_GEOMETRY_SHADER);
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);
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);
662 m_subroutine_uniform_locations.m_vertex_shader_stage =
663 programs[m_vertex_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name, GL_VERTEX_SHADER);
666 /** Generate program pipeline for current context and attach separable programs
668 * @param out_pipeline_id Id of generated pipeline
669 * @param programs Collection of separable programs
671 void UniformPreservationTest::prepareProgramPipeline(glw::GLuint& out_pipeline_id, Utils::program** programs)
673 /* GL entry points */
674 const glw::Functions& gl = m_base_context->getRenderContext().getFunctions();
677 gl.genProgramPipelines(1, &out_pipeline_id);
678 GLU_EXPECT_NO_ERROR(gl.getError(), "GenProgramPipelines");
681 gl.bindProgramPipeline(out_pipeline_id);
682 GLU_EXPECT_NO_ERROR(gl.getError(), "BindProgramPipeline");
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");
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");
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");
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");
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");
703 /** Test specific case
705 * @param bit_field An array of 5 bit fields used to set up subroutine uniforms, one element per context
707 * @return True if test pass, false otherwise
709 bool UniformPreservationTest::testCase(const glw::GLuint bit_field[5])
711 /* Storage for subroutine indices */
712 subroutineUniformSet captured_subroutine_indices[m_n_shared_contexts + 1];
713 subroutineUniformSet subroutine_indices[m_n_shared_contexts + 1];
715 /* Prepare subroutine_indices with bit fields */
716 for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i)
718 subroutine_indices[i].set(bit_field[i], m_subroutine_indices);
721 /* Update subroutine uniforms, each context gets different set */
722 for (GLuint i = 0; i < m_n_shared_contexts; ++i)
724 m_shared_contexts[i]->makeCurrent();
725 updateCurrentSubroutineSet(subroutine_indices[i]);
728 m_base_context->getRenderContext().makeCurrent();
729 updateCurrentSubroutineSet(subroutine_indices[m_n_shared_contexts]);
731 /* Capture subroutine uniforms */
732 for (GLuint i = 0; i < m_n_shared_contexts; ++i)
734 m_shared_contexts[i]->makeCurrent();
735 captureCurrentSubroutineSet(captured_subroutine_indices[i]);
738 m_base_context->getRenderContext().makeCurrent();
739 captureCurrentSubroutineSet(captured_subroutine_indices[m_n_shared_contexts]);
741 /* Verify that captured uniforms match expected values */
742 for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i)
744 if (subroutine_indices[i] != captured_subroutine_indices[i])
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;
766 /** Test a program or pipeline
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
773 * @return True if all cases pass, false otherwise
775 bool UniformPreservationTest::testProgram(Utils::program** programs, bool is_separable,
776 const glw::GLuint test_cases[][5], glw::GLuint n_test_cases)
778 /* Set program/pipeline as current for all contexts */
779 if (false == is_separable)
783 for (GLuint i = 0; i < m_n_shared_contexts; ++i)
785 m_shared_contexts[i]->makeCurrent();
791 /* GL entry points */
792 const glw::Functions& gl = m_base_context->getRenderContext().getFunctions();
794 /* Make sure that program pipeline will be used */
796 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
798 prepareProgramPipeline(m_program_pipelines[m_n_shared_contexts], programs);
800 for (GLuint i = 0; i < m_n_shared_contexts; ++i)
802 m_shared_contexts[i]->makeCurrent();
804 /* Make sure that program pipeline will be used */
806 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
808 prepareProgramPipeline(m_program_pipelines[i], programs);
814 for (GLuint i = 0; i < n_test_cases; ++i)
816 if (false == testCase(test_cases[i]))
826 /** Set up subroutine uniforms for current program or pipeline
828 * @param set Set of subroutine indices
830 void UniformPreservationTest::updateCurrentSubroutineSet(const subroutineUniformSet& set)
832 /* GL entry points */
833 const glw::Functions& gl = m_base_context->getRenderContext().getFunctions();
836 gl.uniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1 /* count */, &set.m_fragment_shader_stage);
837 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
840 gl.uniformSubroutinesuiv(GL_GEOMETRY_SHADER, 1 /* count */, &set.m_geometry_shader_stage);
841 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
844 gl.uniformSubroutinesuiv(GL_TESS_CONTROL_SHADER, 1 /* count */, &set.m_tesselation_control_shader_stage);
845 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
848 gl.uniformSubroutinesuiv(GL_TESS_EVALUATION_SHADER, 1 /* count */, &set.m_tesselation_evaluation_shader_stage);
849 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
852 gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, 1 /* count */, &set.m_vertex_shader_stage);
853 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
858 * @param context Rendering context.
860 MultipleContextsTests::MultipleContextsTests(tcu::TestContext& testCtx, glu::ApiType apiType)
861 : tcu::TestCaseGroup(testCtx, "multiple_contexts", "Verifies \"shader_subroutine\" functionality")
864 /* Left blank on purpose */
867 /** Initializes a texture_storage_multisample test group.
870 void MultipleContextsTests::init(void)
872 addChild(new UniformPreservationTest(m_testCtx, m_apiType));
875 } /* glcts namespace */