Add multiple contexts tests
[platform/upstream/VK-GL-CTS.git] / external / openglcts / modules / common / glcMultipleContextsTests.cpp
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 */