xref: /aosp_15_r20/external/deqp/external/openglcts/modules/common/glcMultipleContextsTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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  **/
set(GLuint bit_field,const subroutineUniformSet subroutine_indices[2])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  **/
operator !=(const subroutineUniformSet & arg) const144 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  **/
UniformPreservationTest(tcu::TestContext & testCtx,glu::ApiType apiType)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  **/
deinit()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  */
iterate()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},      {4, 0, 1, 2, 3},
215         {27, 28, 29, 30, 31}, {28, 29, 30, 31, 27}, {29, 30, 31, 27, 28}, {30, 31, 27, 28, 29}, {31, 27, 28, 29, 30},
216     };
217     static const GLuint n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
218 
219     glu::ContextType context_type(m_api_type);
220     m_base_context = de::SharedPtr<deqp::Context>(new deqp::Context(m_testCtx, context_type));
221 
222     /* Do not execute the test if GL_ARB_shader_subroutine is not supported */
223     if (!m_base_context->getContextInfo().isExtensionSupported("GL_ARB_shader_subroutine"))
224     {
225         throw tcu::NotSupportedError("GL_ARB_shader_subroutine is not supported.");
226     }
227 
228     /* Prepare contexts */
229     initSharedContexts();
230 
231     /* Test result */
232     bool result = true;
233 
234     /* Program pointers */
235     Utils::program *program_pointers[5];
236 
237     /* Test monolithic program */
238     {
239         /* Prepare program */
240         Utils::program program(*m_base_context.get());
241 
242         program_pointers[m_fragment_stage_index] = &program;
243 
244         prepareProgram(program_pointers, false);
245 
246         /* Execute test */
247         if (false == testProgram(program_pointers, false, test_cases, n_test_cases))
248         {
249             m_testCtx.getLog() << tcu::TestLog::Message << "Last error message was caused by monolithic program."
250                                << tcu::TestLog::EndMessage;
251 
252             result = false;
253         }
254     }
255 
256     /* Test separable programs */
257     if (true == m_base_context->getContextInfo().isExtensionSupported("GL_ARB_separate_shader_objects"))
258     {
259         /* Prepare programs */
260         Utils::program vertex_program(*m_base_context.get());
261         Utils::program tesselation_control_program(*m_base_context.get());
262         Utils::program tesselation_evaluation_program(*m_base_context.get());
263         Utils::program geometry_program(*m_base_context.get());
264         Utils::program fragment_program(*m_base_context.get());
265 
266         program_pointers[m_fragment_stage_index]               = &fragment_program;
267         program_pointers[m_geometry_stage_index]               = &geometry_program;
268         program_pointers[m_tesselation_control_stage_index]    = &tesselation_control_program;
269         program_pointers[m_tesselation_evaluation_stage_index] = &tesselation_evaluation_program;
270         program_pointers[m_vertex_stage_index]                 = &vertex_program;
271 
272         prepareProgram(program_pointers, true);
273 
274         /* Execute test */
275         if (false == testProgram(program_pointers, true, test_cases, n_test_cases))
276         {
277             m_testCtx.getLog() << tcu::TestLog::Message << "Last error message was caused by separable program."
278                                << tcu::TestLog::EndMessage;
279             result = false;
280         }
281     }
282 
283     /* All done */
284     if (true == result)
285     {
286         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
287     }
288     else
289     {
290         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
291     }
292 
293     return tcu::TestNode::STOP;
294 }
295 
296 /** Query state of subroutine uniforms of current program/pipeline
297  *
298  * @param set Storage for results
299  **/
captureCurrentSubroutineSet(subroutineUniformSet & set)300 void UniformPreservationTest::captureCurrentSubroutineSet(subroutineUniformSet &set)
301 {
302     /* GL entry points */
303     const glw::Functions &gl = m_base_context->getRenderContext().getFunctions();
304 
305     /* Fragment */
306     gl.getUniformSubroutineuiv(GL_FRAGMENT_SHADER, m_subroutine_uniform_locations.m_fragment_shader_stage,
307                                &set.m_fragment_shader_stage);
308     GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
309 
310     /* Geometry */
311     gl.getUniformSubroutineuiv(GL_GEOMETRY_SHADER, m_subroutine_uniform_locations.m_geometry_shader_stage,
312                                &set.m_geometry_shader_stage);
313     GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
314 
315     /* Tess ctrl */
316     gl.getUniformSubroutineuiv(GL_TESS_CONTROL_SHADER,
317                                m_subroutine_uniform_locations.m_tesselation_control_shader_stage,
318                                &set.m_tesselation_control_shader_stage);
319     GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
320 
321     /* Tess eval */
322     gl.getUniformSubroutineuiv(GL_TESS_EVALUATION_SHADER,
323                                m_subroutine_uniform_locations.m_tesselation_evaluation_shader_stage,
324                                &set.m_tesselation_evaluation_shader_stage);
325     GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
326 
327     /* Vertex */
328     gl.getUniformSubroutineuiv(GL_VERTEX_SHADER, m_subroutine_uniform_locations.m_vertex_shader_stage,
329                                &set.m_vertex_shader_stage);
330     GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformSubroutineuiv");
331 }
332 
333 /** Get shaders' source code
334  *
335  * @param out_vertex_shader_code                 Vertex source code
336  * @param out_tesselation_control_shader_code    Tess ctrl source code
337  * @param out_tesselation_evaluation_shader_code Tess eval source code
338  * @param out_geometry_shader_code               Geometry source code
339  * @param out_fragment_shader_code               Fragment source code
340  **/
getShaders(const glw::GLchar * & out_vertex_shader_code,const glw::GLchar * & out_tesselation_control_shader_code,const glw::GLchar * & out_tesselation_evaluation_shader_code,const glw::GLchar * & out_geometry_shader_code,const glw::GLchar * & out_fragment_shader_code)341 void UniformPreservationTest::getShaders(const glw::GLchar *&out_vertex_shader_code,
342                                          const glw::GLchar *&out_tesselation_control_shader_code,
343                                          const glw::GLchar *&out_tesselation_evaluation_shader_code,
344                                          const glw::GLchar *&out_geometry_shader_code,
345                                          const glw::GLchar *&out_fragment_shader_code)
346 {
347     static const GLchar *vertex_shader_code = "#version 400 core\n"
348                                               "#extension GL_ARB_shader_subroutine : require\n"
349                                               "\n"
350                                               "precision highp float;\n"
351                                               "\n"
352                                               "// Subroutine type\n"
353                                               "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
354                                               "\n"
355                                               "// Subroutine definition\n"
356                                               "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
357                                               "{\n"
358                                               "    return left + right;\n"
359                                               "}\n"
360                                               "\n"
361                                               "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
362                                               "{\n"
363                                               "    return left * right;\n"
364                                               "}\n"
365                                               "\n"
366                                               "// Sub routine uniform\n"
367                                               "subroutine uniform routine_type routine;\n"
368                                               "\n"
369                                               "// Input data\n"
370                                               "uniform vec4 uni_vs_left;\n"
371                                               "uniform vec4 uni_vs_right;\n"
372                                               "\n"
373                                               "// Output\n"
374                                               "out vec4 vs_tcs_result;\n"
375                                               "\n"
376                                               "void main()\n"
377                                               "{\n"
378                                               "    vs_tcs_result = routine(uni_vs_left, uni_vs_right);\n"
379                                               "}\n"
380                                               "\n";
381 
382     static const GLchar *tesselation_control_shader_code =
383         "#version 400 core\n"
384         "#extension GL_ARB_shader_subroutine : require\n"
385         "\n"
386         "precision highp float;\n"
387         "\n"
388         "layout(vertices = 1) out;\n"
389         "\n"
390         "// Subroutine type\n"
391         "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
392         "\n"
393         "// Subroutine definition\n"
394         "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
395         "{\n"
396         "    return left + right;\n"
397         "}\n"
398         "\n"
399         "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
400         "{\n"
401         "    return left * right;\n"
402         "}\n"
403         "\n"
404         "// Sub routine uniform\n"
405         "subroutine uniform routine_type routine;\n"
406         "\n"
407         "// Input data\n"
408         "uniform vec4 uni_tcs_left;\n"
409         "uniform vec4 uni_tcs_right;\n"
410         "\n"
411         "in vec4 vs_tcs_result[];\n"
412         "\n"
413         "// Output\n"
414         "out vec4 tcs_tes_result[];\n"
415         "\n"
416         "void main()\n"
417         "{\n"
418         "    gl_TessLevelOuter[0] = 1.0;\n"
419         "    gl_TessLevelOuter[1] = 1.0;\n"
420         "    gl_TessLevelOuter[2] = 1.0;\n"
421         "    gl_TessLevelOuter[3] = 1.0;\n"
422         "    gl_TessLevelInner[0] = 1.0;\n"
423         "    gl_TessLevelInner[1] = 1.0;\n"
424         "\n"
425         "    tcs_tes_result[gl_InvocationID] = routine(uni_tcs_left, uni_tcs_right) + vs_tcs_result[gl_InvocationID];\n"
426         "}\n"
427         "\n";
428 
429     static const GLchar *tesselation_evaluation_shader_code =
430         "#version 400 core\n"
431         "#extension GL_ARB_shader_subroutine : require\n"
432         "\n"
433         "precision highp float;\n"
434         "\n"
435         "layout(isolines, point_mode) in;\n"
436         "\n"
437         "// Subroutine type\n"
438         "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
439         "\n"
440         "// Subroutine definition\n"
441         "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
442         "{\n"
443         "    return left + right;\n"
444         "}\n"
445         "\n"
446         "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
447         "{\n"
448         "    return left * right;\n"
449         "}\n"
450         "\n"
451         "// Sub routine uniform\n"
452         "subroutine uniform routine_type routine;\n"
453         "\n"
454         "// Input data\n"
455         "uniform vec4 uni_tes_left;\n"
456         "uniform vec4 uni_tes_right;\n"
457         "\n"
458         "in vec4 tcs_tes_result[];\n"
459         "\n"
460         "// Output\n"
461         "out vec4 tes_gs_result;\n"
462         "\n"
463         "void main()\n"
464         "{\n"
465         "    tes_gs_result = routine(uni_tes_left, uni_tes_right) + tcs_tes_result[0];\n"
466         "}\n"
467         "\n";
468 
469     static const GLchar *geometry_shader_code =
470         "#version 400 core\n"
471         "#extension GL_ARB_shader_subroutine : require\n"
472         "\n"
473         "precision highp float;\n"
474         "\n"
475         "layout(points)                   in;\n"
476         "layout(points, max_vertices = 1) out;\n"
477         "\n"
478         "// Subroutine type\n"
479         "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
480         "\n"
481         "// Subroutine definition\n"
482         "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
483         "{\n"
484         "    return left + right;\n"
485         "}\n"
486         "\n"
487         "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
488         "{\n"
489         "    return left * right;\n"
490         "}\n"
491         "\n"
492         "// Sub routine uniform\n"
493         "subroutine uniform routine_type routine;\n"
494         "\n"
495         "// Input data\n"
496         "uniform vec4 uni_gs_left;\n"
497         "uniform vec4 uni_gs_right;\n"
498         "\n"
499         "in vec4 tes_gs_result[];\n"
500         "\n"
501         "// Output\n"
502         "out vec4 gs_fs_result;\n"
503         "\n"
504         "void main()\n"
505         "{\n"
506         "    gs_fs_result = routine(uni_gs_left, uni_gs_right) + tes_gs_result[0];\n"
507         "}\n"
508         "\n";
509 
510     static const GLchar *fragmenty_shader_code =
511         "#version 400 core\n"
512         "#extension GL_ARB_shader_subroutine : require\n"
513         "\n"
514         "precision highp float;\n"
515         "\n"
516         "// Subroutine type\n"
517         "subroutine vec4 routine_type(in vec4 left, in vec4 right);\n"
518         "\n"
519         "// Subroutine definition\n"
520         "subroutine(routine_type) vec4 add(in vec4 left, in vec4 right)\n"
521         "{\n"
522         "    return left + right;\n"
523         "}\n"
524         "\n"
525         "subroutine(routine_type) vec4 multiply(in vec4 left, in vec4 right)\n"
526         "{\n"
527         "    return left * right;\n"
528         "}\n"
529         "\n"
530         "// Sub routine uniform\n"
531         "subroutine uniform routine_type routine;\n"
532         "\n"
533         "// Input data\n"
534         "uniform vec4 uni_fs_left;\n"
535         "uniform vec4 uni_fs_right;\n"
536         "\n"
537         "in vec4 gs_fs_result;\n"
538         "\n"
539         "// Output\n"
540         "out vec4 fs_out_result;\n"
541         "\n"
542         "void main()\n"
543         "{\n"
544         "    fs_out_result = routine(uni_fs_left, uni_fs_right) + gs_fs_result;\n"
545         "}\n"
546         "\n";
547 
548     out_vertex_shader_code                 = vertex_shader_code;
549     out_tesselation_control_shader_code    = tesselation_control_shader_code;
550     out_tesselation_evaluation_shader_code = tesselation_evaluation_shader_code;
551     out_geometry_shader_code               = geometry_shader_code;
552     out_fragment_shader_code               = fragmenty_shader_code;
553 }
554 
555 /** Create <m_n_shared_contexts> shared contexts
556  *
557  **/
initSharedContexts()558 void UniformPreservationTest::initSharedContexts()
559 {
560     glu::ContextType context_type(m_api_type);
561     glu::RenderConfig render_config(context_type);
562     const tcu::CommandLine &command_line(m_testCtx.getCommandLine());
563     glu::RenderContext *shared_context = &(m_base_context->getRenderContext());
564     glu::parseRenderConfig(&render_config, command_line);
565 
566 #if (DE_OS == DE_OS_ANDROID)
567     // Android can only have one Window created at a time
568     // Note that this surface type is not supported on all platforms
569     render_config.surfaceType = glu::RenderConfig::SURFACETYPE_OFFSCREEN_GENERIC;
570 #endif
571 
572     for (GLuint i = 0; i < m_n_shared_contexts; ++i)
573     {
574         m_shared_contexts[i] =
575             glu::createRenderContext(m_testCtx.getPlatform(), command_line, render_config, shared_context);
576     }
577     m_base_context->getRenderContext().makeCurrent();
578 }
579 
580 /** Prepare program(s)
581  *
582  * @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
583  * @param is_separable Select if monolithic or separable programs should be prepared
584  **/
prepareProgram(Utils::program ** programs,bool is_separable)585 void UniformPreservationTest::prepareProgram(Utils::program **programs, bool is_separable)
586 {
587     /* Get shader sources */
588     const GLchar *vertex_shader_code;
589     const GLchar *tesselation_control_shader_code;
590     const GLchar *tesselation_evaluation_shader_code;
591     const GLchar *geometry_shader_code;
592     const GLchar *fragmenty_shader_code;
593 
594     getShaders(vertex_shader_code, tesselation_control_shader_code, tesselation_evaluation_shader_code,
595                geometry_shader_code, fragmenty_shader_code);
596 
597     /* Subroutines and uniform names */
598     static const GLchar *subroutine_names[] = {"add", "multiply"};
599     static const GLuint n_subroutines       = sizeof(subroutine_names) / sizeof(subroutine_names[0]);
600 
601     static const GLchar *subroutine_uniform_name = "routine";
602 
603     /* Build program */
604     if (false == is_separable)
605     {
606         programs[0]->build(0 /* compute shader source */, fragmenty_shader_code, geometry_shader_code,
607                            tesselation_control_shader_code, tesselation_evaluation_shader_code, vertex_shader_code,
608                            0 /* varying_names */, 0 /* n_varying_names */);
609 
610         programs[m_geometry_stage_index]               = programs[m_fragment_stage_index];
611         programs[m_tesselation_control_stage_index]    = programs[m_fragment_stage_index];
612         programs[m_tesselation_evaluation_stage_index] = programs[m_fragment_stage_index];
613         programs[m_vertex_stage_index]                 = programs[m_fragment_stage_index];
614     }
615     else
616     {
617         programs[m_fragment_stage_index]->build(0, fragmenty_shader_code, 0, 0, 0, 0, 0, 0, true);
618         programs[m_geometry_stage_index]->build(0, 0, geometry_shader_code, 0, 0, 0, 0, 0, true);
619         programs[m_tesselation_control_stage_index]->build(0, 0, 0, tesselation_control_shader_code, 0, 0, 0, 0, true);
620         programs[m_tesselation_evaluation_stage_index]->build(0, 0, 0, 0, tesselation_evaluation_shader_code, 0, 0, 0,
621                                                               true);
622         programs[m_vertex_stage_index]->build(0, 0, 0, 0, 0, vertex_shader_code, 0, 0, true);
623     }
624 
625     /* Get subroutine indices */
626     for (GLuint i = 0; i < n_subroutines; ++i)
627     {
628         m_subroutine_indices[i].m_fragment_shader_stage =
629             programs[m_fragment_stage_index]->getSubroutineIndex(subroutine_names[i], GL_FRAGMENT_SHADER);
630 
631         m_subroutine_indices[i].m_geometry_shader_stage =
632             programs[m_geometry_stage_index]->getSubroutineIndex(subroutine_names[i], GL_GEOMETRY_SHADER);
633 
634         m_subroutine_indices[i].m_tesselation_control_shader_stage =
635             programs[m_tesselation_control_stage_index]->getSubroutineIndex(subroutine_names[i],
636                                                                             GL_TESS_CONTROL_SHADER);
637 
638         m_subroutine_indices[i].m_tesselation_evaluation_shader_stage =
639             programs[m_tesselation_evaluation_stage_index]->getSubroutineIndex(subroutine_names[i],
640                                                                                GL_TESS_EVALUATION_SHADER);
641 
642         m_subroutine_indices[i].m_vertex_shader_stage =
643             programs[m_vertex_stage_index]->getSubroutineIndex(subroutine_names[i], GL_VERTEX_SHADER);
644     }
645 
646     /* Get subroutine uniform locations */
647     m_subroutine_uniform_locations.m_fragment_shader_stage =
648         programs[m_fragment_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name, GL_FRAGMENT_SHADER);
649 
650     m_subroutine_uniform_locations.m_geometry_shader_stage =
651         programs[m_geometry_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name, GL_GEOMETRY_SHADER);
652 
653     m_subroutine_uniform_locations.m_tesselation_control_shader_stage =
654         programs[m_tesselation_control_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name,
655                                                                                   GL_TESS_CONTROL_SHADER);
656 
657     m_subroutine_uniform_locations.m_tesselation_evaluation_shader_stage =
658         programs[m_tesselation_evaluation_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name,
659                                                                                      GL_TESS_EVALUATION_SHADER);
660 
661     m_subroutine_uniform_locations.m_vertex_shader_stage =
662         programs[m_vertex_stage_index]->getSubroutineUniformLocation(subroutine_uniform_name, GL_VERTEX_SHADER);
663 }
664 
665 /** Generate program pipeline for current context and attach separable programs
666  *
667  * @param out_pipeline_id Id of generated pipeline
668  * @param programs        Collection of separable programs
669  **/
prepareProgramPipeline(glw::GLuint & out_pipeline_id,Utils::program ** programs)670 void UniformPreservationTest::prepareProgramPipeline(glw::GLuint &out_pipeline_id, Utils::program **programs)
671 {
672     /* GL entry points */
673     const glw::Functions &gl = m_base_context->getRenderContext().getFunctions();
674 
675     /* Generate */
676     gl.genProgramPipelines(1, &out_pipeline_id);
677     GLU_EXPECT_NO_ERROR(gl.getError(), "GenProgramPipelines");
678 
679     /* Bind */
680     gl.bindProgramPipeline(out_pipeline_id);
681     GLU_EXPECT_NO_ERROR(gl.getError(), "BindProgramPipeline");
682 
683     /* Set up programs */
684     gl.useProgramStages(out_pipeline_id, GL_FRAGMENT_SHADER_BIT, programs[m_fragment_stage_index]->m_program_object_id);
685     GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
686 
687     gl.useProgramStages(out_pipeline_id, GL_GEOMETRY_SHADER_BIT, programs[m_geometry_stage_index]->m_program_object_id);
688     GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
689 
690     gl.useProgramStages(out_pipeline_id, GL_TESS_CONTROL_SHADER_BIT,
691                         programs[m_tesselation_control_stage_index]->m_program_object_id);
692     GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
693 
694     gl.useProgramStages(out_pipeline_id, GL_TESS_EVALUATION_SHADER_BIT,
695                         programs[m_tesselation_evaluation_stage_index]->m_program_object_id);
696     GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
697 
698     gl.useProgramStages(out_pipeline_id, GL_VERTEX_SHADER_BIT, programs[m_vertex_stage_index]->m_program_object_id);
699     GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
700 }
701 
702 /** Test specific case
703  *
704  * @param bit_field An array of 5 bit fields used to set up subroutine uniforms, one element per context
705  *
706  * @return True if test pass, false otherwise
707  **/
testCase(const glw::GLuint bit_field[5])708 bool UniformPreservationTest::testCase(const glw::GLuint bit_field[5])
709 {
710     /* Storage for subroutine indices */
711     subroutineUniformSet captured_subroutine_indices[m_n_shared_contexts + 1];
712     subroutineUniformSet subroutine_indices[m_n_shared_contexts + 1];
713 
714     /* Prepare subroutine_indices with bit fields */
715     for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i)
716     {
717         subroutine_indices[i].set(bit_field[i], m_subroutine_indices);
718     }
719 
720     /* Update subroutine uniforms, each context gets different set */
721     for (GLuint i = 0; i < m_n_shared_contexts; ++i)
722     {
723         m_shared_contexts[i]->makeCurrent();
724         updateCurrentSubroutineSet(subroutine_indices[i]);
725     }
726 
727     m_base_context->getRenderContext().makeCurrent();
728     updateCurrentSubroutineSet(subroutine_indices[m_n_shared_contexts]);
729 
730     /* Capture subroutine uniforms */
731     for (GLuint i = 0; i < m_n_shared_contexts; ++i)
732     {
733         m_shared_contexts[i]->makeCurrent();
734         captureCurrentSubroutineSet(captured_subroutine_indices[i]);
735     }
736 
737     m_base_context->getRenderContext().makeCurrent();
738     captureCurrentSubroutineSet(captured_subroutine_indices[m_n_shared_contexts]);
739 
740     /* Verify that captured uniforms match expected values */
741     for (GLuint i = 0; i < m_n_shared_contexts + 1; ++i)
742     {
743         if (subroutine_indices[i] != captured_subroutine_indices[i])
744         {
745             m_testCtx.getLog() << tcu::TestLog::Message << "Error."
746                                << " Context: " << i << " VS, expected: " << subroutine_indices[i].m_vertex_shader_stage
747                                << " captured: " << captured_subroutine_indices[i].m_vertex_shader_stage
748                                << " TCS, expected: " << subroutine_indices[i].m_tesselation_control_shader_stage
749                                << " captured: " << captured_subroutine_indices[i].m_tesselation_control_shader_stage
750                                << " TES, expected: " << subroutine_indices[i].m_tesselation_evaluation_shader_stage
751                                << " captured: " << captured_subroutine_indices[i].m_tesselation_evaluation_shader_stage
752                                << " GS, expected: " << subroutine_indices[i].m_geometry_shader_stage
753                                << " captured: " << captured_subroutine_indices[i].m_geometry_shader_stage
754                                << " FS, expected: " << subroutine_indices[i].m_fragment_shader_stage
755                                << " captured: " << captured_subroutine_indices[i].m_fragment_shader_stage
756                                << tcu::TestLog::EndMessage;
757 
758             return false;
759         }
760     }
761 
762     return true;
763 }
764 
765 /** Test a program or pipeline
766  *
767  * @param programs     An array of 5 programs\ pointers, as in preparePrograms
768  * @param is_separable Selects if monolithic or separable programs should be used
769  * @param test_cases   Collection of test cases
770  * @param n_test_cases Number of test cases
771  *
772  * @return True if all cases pass, false otherwise
773  **/
testProgram(Utils::program ** programs,bool is_separable,const glw::GLuint test_cases[][5],glw::GLuint n_test_cases)774 bool UniformPreservationTest::testProgram(Utils::program **programs, bool is_separable,
775                                           const glw::GLuint test_cases[][5], glw::GLuint n_test_cases)
776 {
777     /* Set program/pipeline as current for all contexts */
778     if (false == is_separable)
779     {
780         programs[0]->use();
781 
782         for (GLuint i = 0; i < m_n_shared_contexts; ++i)
783         {
784             m_shared_contexts[i]->makeCurrent();
785             programs[0]->use();
786         }
787     }
788     else
789     {
790         /* GL entry points */
791         const glw::Functions &gl = m_base_context->getRenderContext().getFunctions();
792 
793         /* Make sure that program pipeline will be used */
794         gl.useProgram(0);
795         GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
796 
797         prepareProgramPipeline(m_program_pipelines[m_n_shared_contexts], programs);
798 
799         for (GLuint i = 0; i < m_n_shared_contexts; ++i)
800         {
801             m_shared_contexts[i]->makeCurrent();
802 
803             /* Make sure that program pipeline will be used */
804             gl.useProgram(0);
805             GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
806 
807             prepareProgramPipeline(m_program_pipelines[i], programs);
808         }
809     }
810 
811     /* Execute test */
812     bool result = true;
813     for (GLuint i = 0; i < n_test_cases; ++i)
814     {
815         if (false == testCase(test_cases[i]))
816         {
817             result = false;
818             break;
819         }
820     }
821 
822     return result;
823 }
824 
825 /** Set up subroutine uniforms for current program or pipeline
826  *
827  * @param set Set of subroutine indices
828  **/
updateCurrentSubroutineSet(const subroutineUniformSet & set)829 void UniformPreservationTest::updateCurrentSubroutineSet(const subroutineUniformSet &set)
830 {
831     /* GL entry points */
832     const glw::Functions &gl = m_base_context->getRenderContext().getFunctions();
833 
834     /* Fragment */
835     gl.uniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1 /* count */, &set.m_fragment_shader_stage);
836     GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
837 
838     /* Geometry */
839     gl.uniformSubroutinesuiv(GL_GEOMETRY_SHADER, 1 /* count */, &set.m_geometry_shader_stage);
840     GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
841 
842     /* Tess ctrl */
843     gl.uniformSubroutinesuiv(GL_TESS_CONTROL_SHADER, 1 /* count */, &set.m_tesselation_control_shader_stage);
844     GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
845 
846     /* Tess eval */
847     gl.uniformSubroutinesuiv(GL_TESS_EVALUATION_SHADER, 1 /* count */, &set.m_tesselation_evaluation_shader_stage);
848     GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
849 
850     /* Vertex */
851     gl.uniformSubroutinesuiv(GL_VERTEX_SHADER, 1 /* count */, &set.m_vertex_shader_stage);
852     GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
853 }
854 
855 /** Constructor.
856  *
857  *  @param context Rendering context.
858  **/
MultipleContextsTests(tcu::TestContext & testCtx,glu::ApiType apiType)859 MultipleContextsTests::MultipleContextsTests(tcu::TestContext &testCtx, glu::ApiType apiType)
860     : tcu::TestCaseGroup(testCtx, "multiple_contexts", "Verifies \"shader_subroutine\" functionality")
861     , m_apiType(apiType)
862 {
863     /* Left blank on purpose */
864 }
865 
866 /** Initializes a texture_storage_multisample test group.
867  *
868  **/
init(void)869 void MultipleContextsTests::init(void)
870 {
871     addChild(new UniformPreservationTest(m_testCtx, m_apiType));
872 }
873 
874 } // namespace glcts
875