xref: /aosp_15_r20/external/deqp/modules/gles31/functional/es31fLayoutBindingTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.1 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
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
21  * \brief Basic Layout Binding Tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es31fLayoutBindingTests.hpp"
25 
26 #include "gluShaderProgram.hpp"
27 #include "gluPixelTransfer.hpp"
28 #include "gluTextureUtil.hpp"
29 #include "gluContextInfo.hpp"
30 
31 #include "glwFunctions.hpp"
32 #include "glwEnums.hpp"
33 
34 #include "tcuSurface.hpp"
35 #include "tcuTestLog.hpp"
36 #include "tcuTexture.hpp"
37 #include "tcuTextureUtil.hpp"
38 #include "tcuImageCompare.hpp"
39 #include "tcuStringTemplate.hpp"
40 #include "tcuRenderTarget.hpp"
41 
42 #include "deString.h"
43 #include "deStringUtil.hpp"
44 #include "deRandom.hpp"
45 
46 using tcu::TestLog;
47 using tcu::Vec2;
48 using tcu::Vec3;
49 using tcu::Vec4;
50 
51 namespace deqp
52 {
53 namespace gles31
54 {
55 namespace Functional
56 {
57 namespace
58 {
59 
60 enum TestType
61 {
62     TESTTYPE_BINDING_SINGLE = 0,
63     TESTTYPE_BINDING_MAX,
64     TESTTYPE_BINDING_MULTIPLE,
65     TESTTYPE_BINDING_ARRAY,
66     TESTTYPE_BINDING_MAX_ARRAY,
67 
68     TESTTYPE_BINDING_LAST,
69 };
70 
71 enum ShaderType
72 {
73     SHADERTYPE_VERTEX = 0,
74     SHADERTYPE_FRAGMENT,
75     SHADERTYPE_TESS_CONTROL,
76     SHADERTYPE_TESS_EVALUATION,
77     SHADERTYPE_ALL,
78 
79     SHADERTYPE_LAST,
80 };
81 
82 enum
83 {
84     MAX_UNIFORM_MULTIPLE_INSTANCES = 7,
85     MAX_UNIFORM_ARRAY_SIZE         = 7,
86 };
87 
generateVertexShader(ShaderType shaderType,const std::string & shaderUniformDeclarations,const std::string & shaderBody)88 std::string generateVertexShader(ShaderType shaderType, const std::string &shaderUniformDeclarations,
89                                  const std::string &shaderBody)
90 {
91     static const char *const s_simpleVertexShaderSource = "#version 310 es\n"
92                                                           "in highp vec4 a_position;\n"
93                                                           "void main (void)\n"
94                                                           "{\n"
95                                                           "    gl_Position = a_position;\n"
96                                                           "}\n";
97 
98     switch (shaderType)
99     {
100     case SHADERTYPE_VERTEX:
101     case SHADERTYPE_ALL:
102     {
103         std::ostringstream vertexShaderSource;
104         vertexShaderSource << "#version 310 es\n"
105                            << "in highp vec4 a_position;\n"
106                            << "out highp vec4 v_color;\n"
107                            << "uniform highp int u_arrayNdx;\n\n"
108                            << shaderUniformDeclarations << "\n"
109                            << "void main (void)\n"
110                            << "{\n"
111                            << "    highp vec4 color;\n\n"
112                            << shaderBody << "\n"
113                            << "    v_color = color;\n"
114                            << "    gl_Position = a_position;\n"
115                            << "}\n";
116 
117         return vertexShaderSource.str();
118     }
119 
120     case SHADERTYPE_FRAGMENT:
121     case SHADERTYPE_TESS_CONTROL:
122     case SHADERTYPE_TESS_EVALUATION:
123         return s_simpleVertexShaderSource;
124 
125     default:
126         DE_ASSERT(false);
127         return "";
128     }
129 }
130 
generateFragmentShader(ShaderType shaderType,const std::string & shaderUniformDeclarations,const std::string & shaderBody)131 std::string generateFragmentShader(ShaderType shaderType, const std::string &shaderUniformDeclarations,
132                                    const std::string &shaderBody)
133 {
134     static const char *const s_simpleFragmentShaderSource = "#version 310 es\n"
135                                                             "in highp vec4 v_color;\n"
136                                                             "layout(location = 0) out highp vec4 fragColor;\n"
137                                                             "void main (void)\n"
138                                                             "{\n"
139                                                             "    fragColor = v_color;\n"
140                                                             "}\n";
141 
142     switch (shaderType)
143     {
144     case SHADERTYPE_VERTEX:
145     case SHADERTYPE_TESS_CONTROL:
146     case SHADERTYPE_TESS_EVALUATION:
147         return s_simpleFragmentShaderSource;
148 
149     case SHADERTYPE_FRAGMENT:
150     {
151         std::ostringstream fragmentShaderSource;
152         fragmentShaderSource << "#version 310 es\n"
153                              << "layout(location = 0) out highp vec4 fragColor;\n"
154                              << "uniform highp int u_arrayNdx;\n\n"
155                              << shaderUniformDeclarations << "\n"
156                              << "void main (void)\n"
157                              << "{\n"
158                              << "    highp vec4 color;\n\n"
159                              << shaderBody << "\n"
160                              << "    fragColor = color;\n"
161                              << "}\n";
162 
163         return fragmentShaderSource.str();
164     }
165     case SHADERTYPE_ALL:
166     {
167         std::ostringstream fragmentShaderSource;
168         fragmentShaderSource << "#version 310 es\n"
169                              << "in highp vec4 v_color;\n"
170                              << "layout(location = 0) out highp vec4 fragColor;\n"
171                              << "uniform highp int u_arrayNdx;\n\n"
172                              << shaderUniformDeclarations << "\n"
173                              << "void main (void)\n"
174                              << "{\n"
175                              << "    if (v_color.x > 2.0) discard;\n"
176                              << "    highp vec4 color;\n\n"
177                              << shaderBody << "\n"
178                              << "    fragColor = color;\n"
179                              << "}\n";
180 
181         return fragmentShaderSource.str();
182     }
183 
184     default:
185         DE_ASSERT(false);
186         return "";
187     }
188 }
189 
generateTessControlShader(ShaderType shaderType,const std::string & shaderUniformDeclarations,const std::string & shaderBody)190 std::string generateTessControlShader(ShaderType shaderType, const std::string &shaderUniformDeclarations,
191                                       const std::string &shaderBody)
192 {
193     static const char *const s_simpleTessContorlShaderSource =
194         "#version 310 es\n"
195         "#extension GL_EXT_tessellation_shader : require\n"
196         "layout (vertices=3) out;\n"
197         "\n"
198         "void main (void)\n"
199         "{\n"
200         "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
201         "}\n";
202 
203     switch (shaderType)
204     {
205     case SHADERTYPE_VERTEX:
206     case SHADERTYPE_FRAGMENT:
207     case SHADERTYPE_TESS_EVALUATION:
208         return s_simpleTessContorlShaderSource;
209 
210     case SHADERTYPE_TESS_CONTROL:
211     case SHADERTYPE_ALL:
212     {
213         std::ostringstream tessControlShaderSource;
214         tessControlShaderSource << "#version 310 es\n"
215                                 << "#extension GL_EXT_tessellation_shader : require\n"
216                                 << "layout (vertices=3) out;\n"
217                                 << "\n"
218                                 << "uniform highp int u_arrayNdx;\n\n"
219                                 << shaderUniformDeclarations << "\n"
220                                 << "void main (void)\n"
221                                 << "{\n"
222                                 << "    highp vec4 color;\n\n"
223                                 << shaderBody << "\n"
224                                 << "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
225                                 << "}\n";
226 
227         return tessControlShaderSource.str();
228     }
229 
230     default:
231         DE_ASSERT(false);
232         return "";
233     }
234 }
235 
generateTessEvaluationShader(ShaderType shaderType,const std::string & shaderUniformDeclarations,const std::string & shaderBody)236 std::string generateTessEvaluationShader(ShaderType shaderType, const std::string &shaderUniformDeclarations,
237                                          const std::string &shaderBody)
238 {
239     static const char *const s_simpleTessEvaluationShaderSource =
240         "#version 310 es\n"
241         "#extension GL_EXT_tessellation_shader : require\n"
242         "layout (triangles) in;\n"
243         "\n"
244         "void main (void)\n"
245         "{\n"
246         "    gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position + gl_TessCoord[1] * gl_in[1].gl_Position + "
247         "gl_TessCoord[2] * gl_in[2].gl_Position;\n"
248         "}\n";
249 
250     switch (shaderType)
251     {
252     case SHADERTYPE_VERTEX:
253     case SHADERTYPE_FRAGMENT:
254     case SHADERTYPE_TESS_CONTROL:
255         return s_simpleTessEvaluationShaderSource;
256 
257     case SHADERTYPE_TESS_EVALUATION:
258     case SHADERTYPE_ALL:
259     {
260         std::ostringstream tessEvaluationShaderSource;
261         tessEvaluationShaderSource << "#version 310 es\n"
262                                    << "#extension GL_EXT_tessellation_shader : require\n"
263                                    << "layout (triangles) in;\n"
264                                    << "\n"
265                                    << "uniform highp int u_arrayNdx;\n\n"
266                                    << shaderUniformDeclarations << "\n"
267                                    << "out mediump vec4 v_color;\n"
268                                    << "void main (void)\n"
269                                    << "{\n"
270                                    << "    highp vec4 color;\n\n"
271                                    << shaderBody << "\n"
272                                    << "    v_color = color;\n"
273                                    << "    gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position + gl_TessCoord[1] * "
274                                       "gl_in[1].gl_Position + gl_TessCoord[2] * gl_in[2].gl_Position;\n"
275                                    << "}\n";
276 
277         return tessEvaluationShaderSource.str();
278     }
279 
280     default:
281         DE_ASSERT(false);
282         return "";
283     }
284 }
285 
getUniformName(const std::string & name,int declNdx)286 std::string getUniformName(const std::string &name, int declNdx)
287 {
288     return name + de::toString(declNdx);
289 }
290 
getUniformName(const std::string & name,int declNdx,int arrNdx)291 std::string getUniformName(const std::string &name, int declNdx, int arrNdx)
292 {
293     return name + de::toString(declNdx) + "[" + de::toString(arrNdx) + "]";
294 }
295 
getRandomColor(de::Random & rnd)296 Vec4 getRandomColor(de::Random &rnd)
297 {
298     const float r = rnd.getFloat(0.2f, 0.9f);
299     const float g = rnd.getFloat(0.2f, 0.9f);
300     const float b = rnd.getFloat(0.2f, 0.9f);
301     return Vec4(r, g, b, 1.0f);
302 }
303 
304 class LayoutBindingRenderCase : public TestCase
305 {
306 public:
307     enum
308     {
309         MAX_TEST_RENDER_WIDTH  = 256,
310         MAX_TEST_RENDER_HEIGHT = 256,
311         TEST_TEXTURE_SIZE      = 1,
312     };
313 
314     LayoutBindingRenderCase(Context &context, const char *name, const char *desc, ShaderType shaderType,
315                             TestType testType, glw::GLenum maxBindingPointEnum, glw::GLenum maxVertexUnitsEnum,
316                             glw::GLenum maxFragmentUnitsEnum, glw::GLenum maxCombinedUnitsEnum,
317                             const std::string &uniformName);
318     virtual ~LayoutBindingRenderCase(void);
319 
320     virtual void init(void);
321     virtual void deinit(void);
322 
getRenderWidth(void) const323     int getRenderWidth(void) const
324     {
325         return de::min((int)MAX_TEST_RENDER_WIDTH, m_context.getRenderTarget().getWidth());
326     }
getRenderHeight(void) const327     int getRenderHeight(void) const
328     {
329         return de::min((int)MAX_TEST_RENDER_HEIGHT, m_context.getRenderTarget().getHeight());
330     }
331 
332 protected:
333     virtual glu::ShaderProgram *generateShaders(void) const = 0;
334 
335     void initRenderState(void);
336     bool drawAndVerifyResult(const Vec4 &expectedColor);
337     void setTestResult(bool queryTestPassed, bool imageTestPassed);
338 
339     const glu::ShaderProgram *m_program;
340     const ShaderType m_shaderType;
341     const TestType m_testType;
342     const std::string m_uniformName;
343 
344     const glw::GLenum m_maxBindingPointEnum;
345     const glw::GLenum m_maxVertexUnitsEnum;
346     const glw::GLenum m_maxFragmentUnitsEnum;
347     const glw::GLenum m_maxCombinedUnitsEnum;
348 
349     glw::GLuint m_vao;
350     glw::GLuint m_vertexBuffer;
351     glw::GLuint m_indexBuffer;
352     glw::GLint m_shaderProgramLoc;
353     glw::GLint m_shaderProgramPosLoc;
354     glw::GLint m_shaderProgramArrayNdxLoc;
355     glw::GLint m_numBindings;
356 
357     std::vector<glw::GLint> m_bindings;
358 
359 private:
360     void initBindingPoints(int minBindingPoint, int numBindingPoints);
361 };
362 
LayoutBindingRenderCase(Context & context,const char * name,const char * desc,ShaderType shaderType,TestType testType,glw::GLenum maxBindingPointEnum,glw::GLenum maxVertexUnitsEnum,glw::GLenum maxFragmentUnitsEnum,glw::GLenum maxCombinedUnitsEnum,const std::string & uniformName)363 LayoutBindingRenderCase::LayoutBindingRenderCase(Context &context, const char *name, const char *desc,
364                                                  ShaderType shaderType, TestType testType,
365                                                  glw::GLenum maxBindingPointEnum, glw::GLenum maxVertexUnitsEnum,
366                                                  glw::GLenum maxFragmentUnitsEnum, glw::GLenum maxCombinedUnitsEnum,
367                                                  const std::string &uniformName)
368     : TestCase(context, name, desc)
369     , m_program(DE_NULL)
370     , m_shaderType(shaderType)
371     , m_testType(testType)
372     , m_uniformName(uniformName)
373     , m_maxBindingPointEnum(maxBindingPointEnum)
374     , m_maxVertexUnitsEnum(maxVertexUnitsEnum)
375     , m_maxFragmentUnitsEnum(maxFragmentUnitsEnum)
376     , m_maxCombinedUnitsEnum(maxCombinedUnitsEnum)
377     , m_vao(0)
378     , m_vertexBuffer(0)
379     , m_indexBuffer(0)
380     , m_shaderProgramLoc(0)
381     , m_shaderProgramPosLoc(0)
382     , m_shaderProgramArrayNdxLoc(0)
383     , m_numBindings(0)
384 {
385 }
386 
~LayoutBindingRenderCase(void)387 LayoutBindingRenderCase::~LayoutBindingRenderCase(void)
388 {
389     deinit();
390 }
391 
init(void)392 void LayoutBindingRenderCase::init(void)
393 {
394     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
395 
396     {
397         de::Random rnd(deStringHash(getName()) ^ 0xff23a4);
398         glw::GLint numBindingPoints = 0; // Number of available binding points
399         glw::GLint maxVertexUnits   = 0; // Available uniforms in the vertex shader
400         glw::GLint maxFragmentUnits = 0; // Available uniforms in the fragment shader
401         glw::GLint maxCombinedUnits = 0; // Available uniforms in all the shader stages combined
402         glw::GLint maxUnits         = 0; // Maximum available uniforms for this test
403 
404         gl.getIntegerv(m_maxVertexUnitsEnum, &maxVertexUnits);
405         gl.getIntegerv(m_maxFragmentUnitsEnum, &maxFragmentUnits);
406         gl.getIntegerv(m_maxCombinedUnitsEnum, &maxCombinedUnits);
407         gl.getIntegerv(m_maxBindingPointEnum, &numBindingPoints);
408         GLU_EXPECT_NO_ERROR(gl.getError(), "Querying available uniform numbers failed");
409 
410         m_testCtx.getLog() << tcu::TestLog::Message
411                            << "Maximum units for uniform type in the vertex shader: " << maxVertexUnits
412                            << tcu::TestLog::EndMessage;
413         m_testCtx.getLog() << tcu::TestLog::Message
414                            << "Maximum units for uniform type in the fragment shader: " << maxFragmentUnits
415                            << tcu::TestLog::EndMessage;
416         m_testCtx.getLog() << tcu::TestLog::Message << "Maximum combined units for uniform type: " << maxCombinedUnits
417                            << tcu::TestLog::EndMessage;
418         m_testCtx.getLog() << tcu::TestLog::Message
419                            << "Maximum binding point for uniform type: " << numBindingPoints - 1
420                            << tcu::TestLog::EndMessage;
421 
422         // Select maximum number of uniforms used for the test
423         switch (m_shaderType)
424         {
425         case SHADERTYPE_VERTEX:
426             maxUnits = maxVertexUnits;
427             break;
428 
429         case SHADERTYPE_FRAGMENT:
430             maxUnits = maxFragmentUnits;
431             break;
432 
433         case SHADERTYPE_ALL:
434             maxUnits = maxCombinedUnits / 2;
435             break;
436 
437         default:
438             DE_ASSERT(false);
439         }
440 
441         // Select the number of uniforms (= bindings) used for this test
442         switch (m_testType)
443         {
444         case TESTTYPE_BINDING_SINGLE:
445         case TESTTYPE_BINDING_MAX:
446             m_numBindings = 1;
447             break;
448 
449         case TESTTYPE_BINDING_MULTIPLE:
450             if (maxUnits < 2)
451                 throw tcu::NotSupportedError("Not enough uniforms available for test");
452             m_numBindings = rnd.getInt(2, deMin32(MAX_UNIFORM_MULTIPLE_INSTANCES, maxUnits));
453             break;
454 
455         case TESTTYPE_BINDING_ARRAY:
456         case TESTTYPE_BINDING_MAX_ARRAY:
457             if (maxUnits < 2)
458                 throw tcu::NotSupportedError("Not enough uniforms available for test");
459             m_numBindings = rnd.getInt(2, deMin32(MAX_UNIFORM_ARRAY_SIZE, maxUnits));
460             break;
461 
462         default:
463             DE_ASSERT(false);
464         }
465 
466         // Check that we have enough uniforms in different shaders to perform the tests
467         if (((m_shaderType == SHADERTYPE_VERTEX) || (m_shaderType == SHADERTYPE_ALL)) &&
468             (maxVertexUnits < m_numBindings))
469             throw tcu::NotSupportedError("Vertex shader: not enough uniforms available for test");
470         if (((m_shaderType == SHADERTYPE_FRAGMENT) || (m_shaderType == SHADERTYPE_ALL)) &&
471             (maxFragmentUnits < m_numBindings))
472             throw tcu::NotSupportedError("Fragment shader: not enough uniforms available for test");
473         if ((m_shaderType == SHADERTYPE_ALL) && (maxCombinedUnits < m_numBindings * 2))
474             throw tcu::NotSupportedError("Not enough uniforms available for test");
475 
476         // Check that we have enough binding points to perform the tests
477         if (numBindingPoints < m_numBindings)
478             throw tcu::NotSupportedError("Not enough binding points available for test");
479 
480         // Initialize the binding points i.e. populate the two binding point vectors
481         initBindingPoints(0, numBindingPoints);
482     }
483 
484     // Generate the shader program - note: this must be done after deciding the binding points
485     DE_ASSERT(!m_program);
486     m_testCtx.getLog() << tcu::TestLog::Message << "Creating test shaders" << tcu::TestLog::EndMessage;
487     m_program = generateShaders();
488     m_testCtx.getLog() << *m_program;
489 
490     if (!m_program->isOk())
491         throw tcu::TestError("Shader compile failed");
492 
493     // Setup vertex and index buffers
494     {
495         // Get attribute and uniform locations
496         const uint32_t program = m_program->getProgram();
497 
498         m_shaderProgramPosLoc      = gl.getAttribLocation(program, "a_position");
499         m_shaderProgramArrayNdxLoc = gl.getUniformLocation(program, "u_arrayNdx");
500         m_vertexBuffer             = 0;
501         m_indexBuffer              = 0;
502 
503         // Setup buffers so that we render one quad covering the whole viewport
504         const Vec3 vertices[] = {
505             Vec3(-1.0f, -1.0f, +1.0f),
506             Vec3(+1.0f, -1.0f, +1.0f),
507             Vec3(+1.0f, +1.0f, +1.0f),
508             Vec3(-1.0f, +1.0f, +1.0f),
509         };
510 
511         const uint16_t indices[] = {
512             0, 1, 2, 0, 2, 3,
513         };
514 
515         TCU_CHECK((m_shaderProgramPosLoc >= 0) && (m_shaderProgramArrayNdxLoc >= 0));
516 
517         // Generate and bind vao
518         if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
519         {
520             gl.genVertexArrays(1, &m_vao);
521             gl.bindVertexArray(m_vao);
522         }
523 
524         // Generate and bind index buffer
525         gl.genBuffers(1, &m_indexBuffer);
526         gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexBuffer);
527         gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, (DE_LENGTH_OF_ARRAY(indices) * (glw::GLsizeiptr)sizeof(indices[0])),
528                       &indices[0], GL_STATIC_DRAW);
529         GLU_EXPECT_NO_ERROR(gl.getError(), "Index buffer setup failed");
530 
531         // Generate and bind vertex buffer
532         gl.genBuffers(1, &m_vertexBuffer);
533         gl.bindBuffer(GL_ARRAY_BUFFER, m_vertexBuffer);
534         gl.bufferData(GL_ARRAY_BUFFER, (DE_LENGTH_OF_ARRAY(vertices) * (glw::GLsizeiptr)sizeof(vertices[0])),
535                       &vertices[0], GL_STATIC_DRAW);
536         gl.enableVertexAttribArray(m_shaderProgramPosLoc);
537         gl.vertexAttribPointer(m_shaderProgramPosLoc, 3, GL_FLOAT, GL_FALSE, 0, DE_NULL);
538         GLU_EXPECT_NO_ERROR(gl.getError(), "Vertex buffer setup failed");
539     }
540 }
541 
deinit(void)542 void LayoutBindingRenderCase::deinit(void)
543 {
544     if (m_program)
545     {
546         delete m_program;
547         m_program = DE_NULL;
548     }
549 
550     if (m_shaderProgramPosLoc)
551         m_context.getRenderContext().getFunctions().disableVertexAttribArray(m_shaderProgramPosLoc);
552 
553     if (m_vao)
554         m_context.getRenderContext().getFunctions().deleteVertexArrays(1, &m_vao);
555 
556     if (m_vertexBuffer)
557     {
558         m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_vertexBuffer);
559         m_context.getRenderContext().getFunctions().bindBuffer(GL_ARRAY_BUFFER, 0);
560     }
561 
562     if (m_indexBuffer)
563     {
564         m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_indexBuffer);
565         m_context.getRenderContext().getFunctions().bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
566     }
567 }
568 
initBindingPoints(int minBindingPoint,int numBindingPoints)569 void LayoutBindingRenderCase::initBindingPoints(int minBindingPoint, int numBindingPoints)
570 {
571     de::Random rnd(deStringHash(getName()) ^ 0xff23a4);
572 
573     switch (m_testType)
574     {
575     case TESTTYPE_BINDING_SINGLE:
576     {
577         const int bpoint = rnd.getInt(minBindingPoint, numBindingPoints - 1);
578         m_bindings.push_back(bpoint);
579         break;
580     }
581 
582     case TESTTYPE_BINDING_MAX:
583         m_bindings.push_back(numBindingPoints - 1);
584         break;
585 
586     case TESTTYPE_BINDING_MULTIPLE:
587     {
588         // Choose multiple unique binding points from the low and high end of available binding points
589         std::vector<uint32_t> lowBindingPoints;
590         std::vector<uint32_t> highBindingPoints;
591 
592         for (int bpoint = 0; bpoint < numBindingPoints / 2; ++bpoint)
593             lowBindingPoints.push_back(bpoint);
594         for (int bpoint = numBindingPoints / 2; bpoint < numBindingPoints; ++bpoint)
595             highBindingPoints.push_back(bpoint);
596 
597         rnd.shuffle(lowBindingPoints.begin(), lowBindingPoints.end());
598         rnd.shuffle(highBindingPoints.begin(), highBindingPoints.end());
599 
600         for (int ndx = 0; ndx < m_numBindings; ++ndx)
601         {
602             if (ndx % 2 == 0)
603             {
604                 const int bpoint = lowBindingPoints.back();
605                 lowBindingPoints.pop_back();
606                 m_bindings.push_back(bpoint);
607             }
608             else
609             {
610                 const int bpoint = highBindingPoints.back();
611                 highBindingPoints.pop_back();
612                 m_bindings.push_back(bpoint);
613             }
614         }
615         break;
616     }
617 
618     case TESTTYPE_BINDING_ARRAY:
619     {
620         const glw::GLint binding = rnd.getInt(minBindingPoint, numBindingPoints - m_numBindings);
621         for (int ndx = 0; ndx < m_numBindings; ++ndx)
622             m_bindings.push_back(binding + ndx);
623         break;
624     }
625 
626     case TESTTYPE_BINDING_MAX_ARRAY:
627     {
628         const glw::GLint binding = numBindingPoints - m_numBindings;
629         for (int ndx = 0; ndx < m_numBindings; ++ndx)
630             m_bindings.push_back(binding + ndx);
631         break;
632     }
633 
634     default:
635         DE_ASSERT(false);
636     }
637 }
638 
initRenderState(void)639 void LayoutBindingRenderCase::initRenderState(void)
640 {
641     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
642 
643     gl.useProgram(m_program->getProgram());
644     gl.viewport(0, 0, getRenderWidth(), getRenderHeight());
645     gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
646     GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set render state");
647 }
648 
drawAndVerifyResult(const Vec4 & expectedColor)649 bool LayoutBindingRenderCase::drawAndVerifyResult(const Vec4 &expectedColor)
650 {
651     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
652     tcu::Surface reference(getRenderWidth(), getRenderHeight());
653 
654     // the point of these test is to check layout_binding. For this purpose, we can use quite
655     // large thresholds.
656     const tcu::RGBA surfaceThreshold =
657         m_context.getRenderContext().getRenderTarget().getPixelFormat().getColorThreshold();
658     const tcu::RGBA compareThreshold = tcu::RGBA(
659         de::clamp(2 * surfaceThreshold.getRed(), 0, 255), de::clamp(2 * surfaceThreshold.getGreen(), 0, 255),
660         de::clamp(2 * surfaceThreshold.getBlue(), 0, 255), de::clamp(2 * surfaceThreshold.getAlpha(), 0, 255));
661 
662     gl.clear(GL_COLOR_BUFFER_BIT);
663 
664     // Draw
665     gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, DE_NULL);
666     GLU_EXPECT_NO_ERROR(gl.getError(), "Drawing failed");
667 
668     // Verify
669     tcu::Surface result(getRenderWidth(), getRenderHeight());
670     m_testCtx.getLog() << TestLog::Message << "Reading pixels" << TestLog::EndMessage;
671     glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
672     GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels failed");
673 
674     tcu::clear(reference.getAccess(), expectedColor);
675     m_testCtx.getLog() << tcu::TestLog::Message << "Verifying output image, fragment output color is " << expectedColor
676                        << tcu::TestLog::EndMessage;
677 
678     return tcu::pixelThresholdCompare(m_testCtx.getLog(), "Render result", "Result verification", reference, result,
679                                       compareThreshold, tcu::COMPARE_LOG_RESULT);
680 }
681 
setTestResult(bool queryTestPassed,bool imageTestPassed)682 void LayoutBindingRenderCase::setTestResult(bool queryTestPassed, bool imageTestPassed)
683 {
684     if (queryTestPassed && imageTestPassed)
685         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
686     else if (!queryTestPassed && !imageTestPassed)
687         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "One or more binding point queries and image comparisons failed");
688     else if (!queryTestPassed)
689         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "One or more binding point queries failed");
690     else
691         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "One or more image comparisons failed");
692 }
693 
694 class LayoutBindingNegativeCase : public TestCase
695 {
696 public:
697     enum ErrorType
698     {
699         ERRORTYPE_OVER_MAX_UNITS = 0,
700         ERRORTYPE_LESS_THAN_ZERO,
701         ERRORTYPE_CONTRADICTORY,
702 
703         ERRORTYPE_LAST,
704     };
705 
706     LayoutBindingNegativeCase(Context &context, const char *name, const char *desc, ShaderType shaderType,
707                               TestType testType, ErrorType errorType, glw::GLenum maxBindingPointEnum,
708                               glw::GLenum maxVertexUnitsEnum, glw::GLenum maxFragmentUnitsEnum,
709                               glw::GLenum maxTessCtrlUnitsEnum, glw::GLenum maxTessEvalUnitsEnum,
710                               glw::GLenum maxCombinedUnitsEnum, const std::string &uniformName);
711     virtual ~LayoutBindingNegativeCase(void);
712 
713     virtual void init(void);
714     virtual void deinit(void);
715     virtual IterateResult iterate(void);
716 
717 protected:
718     virtual glu::ShaderProgram *generateShaders(void) const = 0;
719 
720     const glu::ShaderProgram *m_program;
721     const ShaderType m_shaderType;
722     const TestType m_testType;
723     const ErrorType m_errorType;
724     const glw::GLenum m_maxBindingPointEnum;
725     const glw::GLenum m_maxVertexUnitsEnum;
726     const glw::GLenum m_maxFragmentUnitsEnum;
727     const glw::GLenum m_maxTessCtrlUnitsEnum;
728     const glw::GLenum m_maxTessEvalUnitsEnum;
729     const glw::GLenum m_maxCombinedUnitsEnum;
730     const std::string m_uniformName;
731     glw::GLint m_numBindings;
732     std::vector<glw::GLint> m_vertexShaderBinding;
733     std::vector<glw::GLint> m_fragmentShaderBinding;
734     std::vector<glw::GLint> m_tessCtrlShaderBinding;
735     std::vector<glw::GLint> m_tessEvalShaderBinding;
736     bool m_tessSupport;
737 
738 private:
739     void initBindingPoints(int minBindingPoint, int numBindingPoints);
740 };
741 
LayoutBindingNegativeCase(Context & context,const char * name,const char * desc,ShaderType shaderType,TestType testType,ErrorType errorType,glw::GLenum maxBindingPointEnum,glw::GLenum maxVertexUnitsEnum,glw::GLenum maxTessCtrlUnitsEnum,glw::GLenum maxTessEvalUnitsEnum,glw::GLenum maxFragmentUnitsEnum,glw::GLenum maxCombinedUnitsEnum,const std::string & uniformName)742 LayoutBindingNegativeCase::LayoutBindingNegativeCase(Context &context, const char *name, const char *desc,
743                                                      ShaderType shaderType, TestType testType, ErrorType errorType,
744                                                      glw::GLenum maxBindingPointEnum, glw::GLenum maxVertexUnitsEnum,
745                                                      glw::GLenum maxTessCtrlUnitsEnum, glw::GLenum maxTessEvalUnitsEnum,
746                                                      glw::GLenum maxFragmentUnitsEnum, glw::GLenum maxCombinedUnitsEnum,
747                                                      const std::string &uniformName)
748     : TestCase(context, name, desc)
749     , m_program(DE_NULL)
750     , m_shaderType(shaderType)
751     , m_testType(testType)
752     , m_errorType(errorType)
753     , m_maxBindingPointEnum(maxBindingPointEnum)
754     , m_maxVertexUnitsEnum(maxVertexUnitsEnum)
755     , m_maxFragmentUnitsEnum(maxFragmentUnitsEnum)
756     , m_maxTessCtrlUnitsEnum(maxTessCtrlUnitsEnum)
757     , m_maxTessEvalUnitsEnum(maxTessEvalUnitsEnum)
758     , m_maxCombinedUnitsEnum(maxCombinedUnitsEnum)
759     , m_uniformName(uniformName)
760     , m_numBindings(0)
761     , m_tessSupport(false)
762 {
763 }
764 
~LayoutBindingNegativeCase(void)765 LayoutBindingNegativeCase::~LayoutBindingNegativeCase(void)
766 {
767     deinit();
768 }
769 
init(void)770 void LayoutBindingNegativeCase::init(void)
771 {
772     // Decide appropriate binding points for the vertex and fragment shaders
773     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
774     de::Random rnd(deStringHash(getName()) ^ 0xff23a4);
775     glw::GLint numBindingPoints = 0; // Number of binding points
776     glw::GLint maxVertexUnits   = 0; // Available uniforms in the vertex shader
777     glw::GLint maxFragmentUnits = 0; // Available uniforms in the fragment shader
778     glw::GLint maxCombinedUnits = 0; // Available uniforms in all the shader stages combined
779     glw::GLint maxTessCtrlUnits = 0; // Available uniforms in tessellation control shader
780     glw::GLint maxTessEvalUnits = 0; // Available uniforms in tessellation evaluation shader
781     glw::GLint maxUnits         = 0; // Maximum available uniforms for this test
782 
783     m_tessSupport = m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader") ||
784                     contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) ||
785                     contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5));
786 
787     if (!m_tessSupport && (m_shaderType == SHADERTYPE_TESS_EVALUATION || m_shaderType == SHADERTYPE_TESS_CONTROL))
788         TCU_THROW(NotSupportedError, "Tesselation shaders not supported");
789 
790     int numShaderStages = m_tessSupport ? 4 : 2;
791 
792     gl.getIntegerv(m_maxVertexUnitsEnum, &maxVertexUnits);
793     gl.getIntegerv(m_maxFragmentUnitsEnum, &maxFragmentUnits);
794 
795     if (m_tessSupport)
796     {
797         gl.getIntegerv(m_maxTessCtrlUnitsEnum, &maxTessCtrlUnits);
798         gl.getIntegerv(m_maxTessEvalUnitsEnum, &maxTessEvalUnits);
799     }
800 
801     gl.getIntegerv(m_maxCombinedUnitsEnum, &maxCombinedUnits);
802     gl.getIntegerv(m_maxBindingPointEnum, &numBindingPoints);
803     GLU_EXPECT_NO_ERROR(gl.getError(), "Querying available uniform numbers failed");
804 
805     m_testCtx.getLog() << tcu::TestLog::Message
806                        << "Maximum units for uniform type in the vertex shader: " << maxVertexUnits
807                        << tcu::TestLog::EndMessage;
808     m_testCtx.getLog() << tcu::TestLog::Message
809                        << "Maximum units for uniform type in the fragment shader: " << maxFragmentUnits
810                        << tcu::TestLog::EndMessage;
811 
812     if (m_tessSupport)
813     {
814         m_testCtx.getLog() << tcu::TestLog::Message
815                            << "Maximum units for uniform type in the tessellation control shader: " << maxTessCtrlUnits
816                            << tcu::TestLog::EndMessage;
817         m_testCtx.getLog() << tcu::TestLog::Message
818                            << "Maximum units for uniform type in the tessellation evaluation shader: "
819                            << maxTessCtrlUnits << tcu::TestLog::EndMessage;
820     }
821 
822     m_testCtx.getLog() << tcu::TestLog::Message << "Maximum combined units for uniform type: " << maxCombinedUnits
823                        << tcu::TestLog::EndMessage;
824     m_testCtx.getLog() << tcu::TestLog::Message << "Maximum binding point for uniform type: " << numBindingPoints - 1
825                        << tcu::TestLog::EndMessage;
826 
827     // Select maximum number of uniforms used for the test
828     switch (m_shaderType)
829     {
830     case SHADERTYPE_VERTEX:
831         maxUnits = maxVertexUnits;
832         break;
833 
834     case SHADERTYPE_FRAGMENT:
835         maxUnits = maxFragmentUnits;
836         break;
837 
838     case SHADERTYPE_ALL:
839         maxUnits =
840             de::min(de::min(de::min(maxVertexUnits, maxFragmentUnits), de::min(maxTessCtrlUnits, maxTessEvalUnits)),
841                     maxCombinedUnits / numShaderStages);
842         break;
843 
844     case SHADERTYPE_TESS_CONTROL:
845         maxUnits = maxTessCtrlUnits;
846         break;
847 
848     case SHADERTYPE_TESS_EVALUATION:
849         maxUnits = maxTessEvalUnits;
850         break;
851 
852     default:
853         DE_ASSERT(false);
854     }
855 
856     // Select the number of uniforms (= bindings) used for this test
857     switch (m_testType)
858     {
859     case TESTTYPE_BINDING_SINGLE:
860     case TESTTYPE_BINDING_MAX:
861         m_numBindings = 1;
862         break;
863 
864     case TESTTYPE_BINDING_MULTIPLE:
865     case TESTTYPE_BINDING_ARRAY:
866     case TESTTYPE_BINDING_MAX_ARRAY:
867         if (m_errorType == ERRORTYPE_CONTRADICTORY)
868         {
869             // leave room for contradictory case
870             if (maxUnits < 3)
871                 TCU_THROW(NotSupportedError, "Not enough uniforms available for test");
872             m_numBindings = rnd.getInt(2, deMin32(MAX_UNIFORM_ARRAY_SIZE, maxUnits - 1));
873         }
874         else
875         {
876             if (maxUnits < 2)
877                 TCU_THROW(NotSupportedError, "Not enough uniforms available for test");
878             m_numBindings = rnd.getInt(2, deMin32(MAX_UNIFORM_ARRAY_SIZE, maxUnits));
879         }
880         break;
881 
882     default:
883         DE_ASSERT(false);
884     }
885 
886     // Check that we have enough uniforms in different shaders to perform the tests
887     if (((m_shaderType == SHADERTYPE_VERTEX) || (m_shaderType == SHADERTYPE_ALL)) && (maxVertexUnits < m_numBindings))
888         TCU_THROW(NotSupportedError, "Vertex shader: not enough uniforms available for test");
889 
890     if (((m_shaderType == SHADERTYPE_FRAGMENT) || (m_shaderType == SHADERTYPE_ALL)) &&
891         (maxFragmentUnits < m_numBindings))
892         TCU_THROW(NotSupportedError, "Fragment shader: not enough uniforms available for test");
893 
894     if (m_tessSupport && ((m_shaderType == SHADERTYPE_TESS_CONTROL) || (m_shaderType == SHADERTYPE_ALL)) &&
895         (maxTessCtrlUnits < m_numBindings))
896         TCU_THROW(NotSupportedError, "Tessellation control shader: not enough uniforms available for test");
897 
898     if (m_tessSupport && ((m_shaderType == SHADERTYPE_TESS_EVALUATION) || (m_shaderType == SHADERTYPE_ALL)) &&
899         (maxTessEvalUnits < m_numBindings))
900         TCU_THROW(NotSupportedError, "Tessellation evaluation shader: not enough uniforms available for test");
901 
902     if ((m_shaderType == SHADERTYPE_ALL) && (maxCombinedUnits < m_numBindings * numShaderStages))
903         TCU_THROW(NotSupportedError, "Not enough uniforms available for test");
904 
905     // Check that we have enough binding points to perform the tests
906     if (numBindingPoints < m_numBindings)
907         TCU_THROW(NotSupportedError, "Not enough binding points available for test");
908 
909     if (m_errorType == ERRORTYPE_CONTRADICTORY && numBindingPoints == m_numBindings)
910         TCU_THROW(NotSupportedError, "Not enough binding points available for test");
911 
912     // Initialize the binding points i.e. populate the two binding point vectors
913     initBindingPoints(0, numBindingPoints);
914 
915     // Generate the shader program - note: this must be done after deciding the binding points
916     DE_ASSERT(!m_program);
917     m_testCtx.getLog() << tcu::TestLog::Message << "Creating test shaders" << tcu::TestLog::EndMessage;
918     m_program = generateShaders();
919     m_testCtx.getLog() << *m_program;
920 }
921 
deinit(void)922 void LayoutBindingNegativeCase::deinit(void)
923 {
924     if (m_program)
925     {
926         delete m_program;
927         m_program = DE_NULL;
928     }
929 }
930 
iterate(void)931 TestCase::IterateResult LayoutBindingNegativeCase::iterate(void)
932 {
933     bool pass = false;
934     std::string failMessage;
935 
936     switch (m_errorType)
937     {
938     case ERRORTYPE_CONTRADICTORY: // Contradictory binding points should cause a link-time error
939         if (!(m_program->getProgramInfo()).linkOk)
940             pass = true;
941         failMessage = "Test failed - expected a link-time error";
942         break;
943 
944     case ERRORTYPE_LESS_THAN_ZERO: // Out of bounds binding points should cause a compile-time error
945     case ERRORTYPE_OVER_MAX_UNITS:
946         if (m_tessSupport)
947         {
948             if (!(m_program->getShaderInfo(glu::SHADERTYPE_VERTEX)).compileOk ||
949                 !(m_program->getShaderInfo(glu::SHADERTYPE_FRAGMENT).compileOk) ||
950                 !(m_program->getShaderInfo(glu::SHADERTYPE_TESSELLATION_CONTROL).compileOk) ||
951                 !(m_program->getShaderInfo(glu::SHADERTYPE_TESSELLATION_EVALUATION)).compileOk)
952                 pass = true;
953         }
954         else
955         {
956             if (!(m_program->getShaderInfo(glu::SHADERTYPE_VERTEX)).compileOk ||
957                 !(m_program->getShaderInfo(glu::SHADERTYPE_FRAGMENT).compileOk))
958                 pass = true;
959         }
960 
961         failMessage = "Test failed - expected a compile-time error";
962         break;
963 
964     default:
965         DE_ASSERT(false);
966     }
967 
968     if (pass)
969         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
970     else
971         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, failMessage.c_str());
972 
973     return STOP;
974 }
975 
initBindingPoints(int minBindingPoint,int numBindingPoints)976 void LayoutBindingNegativeCase::initBindingPoints(int minBindingPoint, int numBindingPoints)
977 {
978     de::Random rnd(deStringHash(getName()) ^ 0xff23a4);
979 
980     switch (m_errorType)
981     {
982     case ERRORTYPE_OVER_MAX_UNITS: // Select a binding point that is 1 over the maximum
983     {
984         m_vertexShaderBinding.push_back(numBindingPoints + 1 - m_numBindings);
985         m_fragmentShaderBinding.push_back(numBindingPoints + 1 - m_numBindings);
986         m_tessCtrlShaderBinding.push_back(numBindingPoints + 1 - m_numBindings);
987         m_tessEvalShaderBinding.push_back(numBindingPoints + 1 - m_numBindings);
988         break;
989     }
990 
991     case ERRORTYPE_LESS_THAN_ZERO: // Select a random negative binding point
992     {
993         const glw::GLint binding = -rnd.getInt(1, m_numBindings);
994         m_vertexShaderBinding.push_back(binding);
995         m_fragmentShaderBinding.push_back(binding);
996         m_tessCtrlShaderBinding.push_back(binding);
997         m_tessEvalShaderBinding.push_back(binding);
998         break;
999     }
1000 
1001     case ERRORTYPE_CONTRADICTORY: // Select two valid, but contradictory binding points
1002     {
1003         m_vertexShaderBinding.push_back(minBindingPoint);
1004         m_fragmentShaderBinding.push_back((minBindingPoint + 1) % numBindingPoints);
1005         m_tessCtrlShaderBinding.push_back((minBindingPoint + 2) % numBindingPoints);
1006         m_tessEvalShaderBinding.push_back((minBindingPoint + 3) % numBindingPoints);
1007 
1008         DE_ASSERT(m_vertexShaderBinding.back() != m_fragmentShaderBinding.back());
1009         DE_ASSERT(m_fragmentShaderBinding.back() != m_tessEvalShaderBinding.back());
1010         DE_ASSERT(m_tessEvalShaderBinding.back() != m_tessCtrlShaderBinding.back());
1011         DE_ASSERT(m_tessCtrlShaderBinding.back() != m_vertexShaderBinding.back());
1012         DE_ASSERT(m_vertexShaderBinding.back() != m_tessEvalShaderBinding.back());
1013         DE_ASSERT(m_tessCtrlShaderBinding.back() != m_fragmentShaderBinding.back());
1014         break;
1015     }
1016 
1017     default:
1018         DE_ASSERT(false);
1019     }
1020 
1021     // In case we are testing with multiple uniforms populate the rest of the binding points
1022     for (int ndx = 1; ndx < m_numBindings; ++ndx)
1023     {
1024         m_vertexShaderBinding.push_back(m_vertexShaderBinding.front() + ndx);
1025         m_fragmentShaderBinding.push_back(m_fragmentShaderBinding.front() + ndx);
1026         m_tessCtrlShaderBinding.push_back(m_tessCtrlShaderBinding.front() + ndx);
1027         m_tessEvalShaderBinding.push_back(m_tessCtrlShaderBinding.front() + ndx);
1028     }
1029 }
1030 
1031 class SamplerBindingRenderCase : public LayoutBindingRenderCase
1032 {
1033 public:
1034     SamplerBindingRenderCase(Context &context, const char *name, const char *desc, ShaderType shaderType,
1035                              TestType testType, glw::GLenum samplerType, glw::GLenum textureType);
1036     ~SamplerBindingRenderCase(void);
1037 
1038     void init(void);
1039     void deinit(void);
1040     IterateResult iterate(void);
1041 
1042 private:
1043     glu::ShaderProgram *generateShaders(void) const;
1044     glu::DataType getSamplerTexCoordType(void) const;
1045     void initializeTexture(glw::GLint bindingPoint, glw::GLint textureName, const Vec4 &color) const;
1046 
1047     const glw::GLenum m_samplerType;
1048     const glw::GLenum m_textureType;
1049 
1050     std::vector<glw::GLuint> m_textures;
1051     std::vector<Vec4> m_textureColors;
1052 };
1053 
SamplerBindingRenderCase(Context & context,const char * name,const char * desc,ShaderType shaderType,TestType testType,glw::GLenum samplerType,glw::GLenum textureType)1054 SamplerBindingRenderCase::SamplerBindingRenderCase(Context &context, const char *name, const char *desc,
1055                                                    ShaderType shaderType, TestType testType, glw::GLenum samplerType,
1056                                                    glw::GLenum textureType)
1057     : LayoutBindingRenderCase(context, name, desc, shaderType, testType, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
1058                               GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, GL_MAX_TEXTURE_IMAGE_UNITS,
1059                               GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, "u_sampler")
1060     , m_samplerType(samplerType)
1061     , m_textureType(textureType)
1062 {
1063 }
1064 
~SamplerBindingRenderCase(void)1065 SamplerBindingRenderCase::~SamplerBindingRenderCase(void)
1066 {
1067     deinit();
1068 }
1069 
init(void)1070 void SamplerBindingRenderCase::init(void)
1071 {
1072     LayoutBindingRenderCase::init();
1073     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1074     de::Random rnd(deStringHash(getName()) ^ 0xff23a4);
1075 
1076     // Initialize texture resources
1077     m_textures = std::vector<glw::GLuint>(m_numBindings, 0);
1078 
1079     // Texture colors
1080     for (int texNdx = 0; texNdx < (int)m_textures.size(); ++texNdx)
1081         m_textureColors.push_back(getRandomColor(rnd));
1082 
1083     // Textures
1084     gl.genTextures((glw::GLsizei)m_textures.size(), &m_textures[0]);
1085 
1086     for (int texNdx = 0; texNdx < (int)m_textures.size(); ++texNdx)
1087         initializeTexture(m_bindings[texNdx], m_textures[texNdx], m_textureColors[texNdx]);
1088 
1089     gl.activeTexture(GL_TEXTURE0);
1090 }
1091 
deinit(void)1092 void SamplerBindingRenderCase::deinit(void)
1093 {
1094     LayoutBindingRenderCase::deinit();
1095 
1096     // Clean up texture data
1097     for (int i = 0; i < (int)m_textures.size(); ++i)
1098     {
1099         if (m_textures[i])
1100         {
1101             m_context.getRenderContext().getFunctions().deleteTextures(1, &m_textures[i]);
1102             m_context.getRenderContext().getFunctions().bindTexture(m_textureType, 0);
1103         }
1104     }
1105 }
1106 
iterate(void)1107 TestCase::IterateResult SamplerBindingRenderCase::iterate(void)
1108 {
1109     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1110     const int iterations     = m_numBindings;
1111     const bool arrayInstance = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY);
1112     bool imageTestPassed     = true;
1113     bool queryTestPassed     = true;
1114 
1115     // Set the viewport and enable the shader program
1116     initRenderState();
1117 
1118     for (int iterNdx = 0; iterNdx < iterations; ++iterNdx)
1119     {
1120         // Set the uniform value indicating the current array index
1121         gl.uniform1i(m_shaderProgramArrayNdxLoc, iterNdx);
1122 
1123         // Query binding point
1124         const std::string name =
1125             arrayInstance ? getUniformName(m_uniformName, 0, iterNdx) : getUniformName(m_uniformName, iterNdx);
1126         const glw::GLint binding = m_bindings[iterNdx];
1127         glw::GLint val           = -1;
1128 
1129         gl.getUniformiv(m_program->getProgram(), gl.getUniformLocation(m_program->getProgram(), name.c_str()), &val);
1130         m_testCtx.getLog() << tcu::TestLog::Message << "Querying binding point for " << name << ": " << val
1131                            << " == " << binding << tcu::TestLog::EndMessage;
1132         GLU_EXPECT_NO_ERROR(gl.getError(), "Binding point query failed");
1133 
1134         // Draw and verify
1135         if (val != binding)
1136             queryTestPassed = false;
1137         if (!drawAndVerifyResult(m_textureColors[iterNdx]))
1138             imageTestPassed = false;
1139     }
1140 
1141     setTestResult(queryTestPassed, imageTestPassed);
1142     return STOP;
1143 }
1144 
generateShaders(void) const1145 glu::ShaderProgram *SamplerBindingRenderCase::generateShaders(void) const
1146 {
1147     std::ostringstream shaderUniformDecl;
1148     std::ostringstream shaderBody;
1149 
1150     const std::string texCoordType = glu::getDataTypeName(getSamplerTexCoordType());
1151     const std::string samplerType  = glu::getDataTypeName(glu::getDataTypeFromGLType(m_samplerType));
1152     const bool arrayInstance =
1153         (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY) ? true : false;
1154     const int numDeclarations = arrayInstance ? 1 : m_numBindings;
1155 
1156     // Generate the uniform declarations for the vertex and fragment shaders
1157     for (int declNdx = 0; declNdx < numDeclarations; ++declNdx)
1158     {
1159         shaderUniformDecl << "layout(binding = " << m_bindings[declNdx] << ") uniform highp " << samplerType << " "
1160                           << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) :
1161                                               getUniformName(m_uniformName, declNdx))
1162                           << ";\n";
1163     }
1164 
1165     // Generate the shader body for the vertex and fragment shaders
1166     for (int bindNdx = 0; bindNdx < m_numBindings; ++bindNdx)
1167     {
1168         shaderBody << "    " << (bindNdx == 0 ? "if" : "else if") << " (u_arrayNdx == " << de::toString(bindNdx)
1169                    << ")\n"
1170                    << "    {\n"
1171                    << "        color = texture("
1172                    << (arrayInstance ? getUniformName(m_uniformName, 0, bindNdx) :
1173                                        getUniformName(m_uniformName, bindNdx))
1174                    << ", " << texCoordType << "(0.5));\n"
1175                    << "    }\n";
1176     }
1177 
1178     shaderBody << "    else\n"
1179                << "    {\n"
1180                << "        color = vec4(0.0, 0.0, 0.0, 1.0);\n"
1181                << "    }\n";
1182 
1183     return new glu::ShaderProgram(m_context.getRenderContext(),
1184                                   glu::ProgramSources()
1185                                       << glu::VertexSource(generateVertexShader(m_shaderType, shaderUniformDecl.str(),
1186                                                                                 shaderBody.str()))
1187                                       << glu::FragmentSource(generateFragmentShader(
1188                                              m_shaderType, shaderUniformDecl.str(), shaderBody.str())));
1189 }
1190 
initializeTexture(glw::GLint bindingPoint,glw::GLint textureName,const Vec4 & color) const1191 void SamplerBindingRenderCase::initializeTexture(glw::GLint bindingPoint, glw::GLint textureName,
1192                                                  const Vec4 &color) const
1193 {
1194     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1195 
1196     gl.activeTexture(GL_TEXTURE0 + bindingPoint);
1197     gl.bindTexture(m_textureType, textureName);
1198     gl.texParameteri(m_textureType, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1199 
1200     switch (m_textureType)
1201     {
1202     case GL_TEXTURE_2D:
1203     {
1204         tcu::TextureLevel level(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8),
1205                                 TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE);
1206         tcu::clear(level.getAccess(), color);
1207         glu::texImage2D(m_context.getRenderContext(), m_textureType, 0, GL_RGBA8, level.getAccess());
1208         break;
1209     }
1210 
1211     case GL_TEXTURE_3D:
1212     {
1213         tcu::TextureLevel level(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8),
1214                                 TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE);
1215         tcu::clear(level.getAccess(), color);
1216         glu::texImage3D(m_context.getRenderContext(), m_textureType, 0, GL_RGBA8, level.getAccess());
1217         break;
1218     }
1219 
1220     default:
1221         DE_ASSERT(false);
1222     }
1223 
1224     GLU_EXPECT_NO_ERROR(gl.getError(), "Texture initialization failed");
1225 }
1226 
getSamplerTexCoordType(void) const1227 glu::DataType SamplerBindingRenderCase::getSamplerTexCoordType(void) const
1228 {
1229     switch (m_samplerType)
1230     {
1231     case GL_SAMPLER_2D:
1232         return glu::TYPE_FLOAT_VEC2;
1233 
1234     case GL_SAMPLER_3D:
1235         return glu::TYPE_FLOAT_VEC3;
1236 
1237     default:
1238         DE_ASSERT(false);
1239         return glu::TYPE_INVALID;
1240     }
1241 }
1242 
1243 class SamplerBindingNegativeCase : public LayoutBindingNegativeCase
1244 {
1245 public:
1246     SamplerBindingNegativeCase(Context &context, const char *name, const char *desc, ShaderType shaderType,
1247                                TestType testType, ErrorType errorType, glw::GLenum samplerType);
1248     ~SamplerBindingNegativeCase(void);
1249 
1250 private:
1251     glu::ShaderProgram *generateShaders(void) const;
1252     glu::DataType getSamplerTexCoordType(void) const;
1253 
1254     const glw::GLenum m_samplerType;
1255 };
1256 
SamplerBindingNegativeCase(Context & context,const char * name,const char * desc,ShaderType shaderType,TestType testType,ErrorType errorType,glw::GLenum samplerType)1257 SamplerBindingNegativeCase::SamplerBindingNegativeCase(Context &context, const char *name, const char *desc,
1258                                                        ShaderType shaderType, TestType testType, ErrorType errorType,
1259                                                        glw::GLenum samplerType)
1260     : LayoutBindingNegativeCase(context, name, desc, shaderType, testType, errorType,
1261                                 GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,
1262                                 GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS, GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS,
1263                                 GL_MAX_TEXTURE_IMAGE_UNITS, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, "u_sampler")
1264     , m_samplerType(samplerType)
1265 {
1266 }
1267 
~SamplerBindingNegativeCase(void)1268 SamplerBindingNegativeCase::~SamplerBindingNegativeCase(void)
1269 {
1270     LayoutBindingNegativeCase::deinit();
1271 }
1272 
generateShaders(void) const1273 glu::ShaderProgram *SamplerBindingNegativeCase::generateShaders(void) const
1274 {
1275     std::ostringstream vertexUniformDecl;
1276     std::ostringstream fragmentUniformDecl;
1277     std::ostringstream tessCtrlUniformDecl;
1278     std::ostringstream tessEvalUniformDecl;
1279     std::ostringstream shaderBody;
1280 
1281     const std::string texCoordType = glu::getDataTypeName(getSamplerTexCoordType());
1282     const std::string samplerType  = glu::getDataTypeName(glu::getDataTypeFromGLType(m_samplerType));
1283     const bool arrayInstance       = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY);
1284     const int numDeclarations      = arrayInstance ? 1 : m_numBindings;
1285 
1286     // Generate the uniform declarations for the vertex and fragment shaders
1287     for (int declNdx = 0; declNdx < numDeclarations; ++declNdx)
1288     {
1289         vertexUniformDecl << "layout(binding = " << m_vertexShaderBinding[declNdx] << ") uniform highp " << samplerType
1290                           << " "
1291                           << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) :
1292                                               getUniformName(m_uniformName, declNdx))
1293                           << ";\n";
1294         fragmentUniformDecl << "layout(binding = " << m_fragmentShaderBinding[declNdx] << ") uniform highp "
1295                             << samplerType << " "
1296                             << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) :
1297                                                 getUniformName(m_uniformName, declNdx))
1298                             << ";\n";
1299         tessCtrlUniformDecl << "layout(binding = " << m_tessCtrlShaderBinding[declNdx] << ") uniform highp "
1300                             << samplerType << " "
1301                             << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) :
1302                                                 getUniformName(m_uniformName, declNdx))
1303                             << ";\n";
1304         tessEvalUniformDecl << "layout(binding = " << m_tessEvalShaderBinding[declNdx] << ") uniform highp "
1305                             << samplerType << " "
1306                             << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) :
1307                                                 getUniformName(m_uniformName, declNdx))
1308                             << ";\n";
1309     }
1310 
1311     // Generate the shader body for the vertex and fragment shaders
1312     for (int bindNdx = 0; bindNdx < m_numBindings; ++bindNdx)
1313     {
1314         shaderBody << "    " << (bindNdx == 0 ? "if" : "else if") << " (u_arrayNdx == " << de::toString(bindNdx)
1315                    << ")\n"
1316                    << "    {\n"
1317                    << "        color = texture("
1318                    << (arrayInstance ? getUniformName(m_uniformName, 0, bindNdx) :
1319                                        getUniformName(m_uniformName, bindNdx))
1320                    << ", " << texCoordType << "(0.5));\n"
1321                    << "    }\n";
1322     }
1323 
1324     shaderBody << "    else\n"
1325                << "    {\n"
1326                << "        color = vec4(0.0, 0.0, 0.0, 1.0);\n"
1327                << "    }\n";
1328 
1329     glu::ProgramSources sources = glu::ProgramSources()
1330                                   << glu::VertexSource(
1331                                          generateVertexShader(m_shaderType, vertexUniformDecl.str(), shaderBody.str()))
1332                                   << glu::FragmentSource(generateFragmentShader(m_shaderType, fragmentUniformDecl.str(),
1333                                                                                 shaderBody.str()));
1334 
1335     if (m_tessSupport)
1336         sources << glu::TessellationControlSource(
1337                        generateTessControlShader(m_shaderType, tessCtrlUniformDecl.str(), shaderBody.str()))
1338                 << glu::TessellationEvaluationSource(
1339                        generateTessEvaluationShader(m_shaderType, tessEvalUniformDecl.str(), shaderBody.str()));
1340 
1341     return new glu::ShaderProgram(m_context.getRenderContext(), sources);
1342 }
1343 
getSamplerTexCoordType(void) const1344 glu::DataType SamplerBindingNegativeCase::getSamplerTexCoordType(void) const
1345 {
1346     switch (m_samplerType)
1347     {
1348     case GL_SAMPLER_2D:
1349         return glu::TYPE_FLOAT_VEC2;
1350 
1351     case GL_SAMPLER_3D:
1352         return glu::TYPE_FLOAT_VEC3;
1353 
1354     default:
1355         DE_ASSERT(false);
1356         return glu::TYPE_INVALID;
1357     }
1358 }
1359 
1360 class ImageBindingRenderCase : public LayoutBindingRenderCase
1361 {
1362 public:
1363     ImageBindingRenderCase(Context &context, const char *name, const char *desc, ShaderType shaderType,
1364                            TestType testType, glw::GLenum imageType, glw::GLenum textureType);
1365     ~ImageBindingRenderCase(void);
1366 
1367     void init(void);
1368     void deinit(void);
1369     IterateResult iterate(void);
1370 
1371 private:
1372     glu::ShaderProgram *generateShaders(void) const;
1373     void initializeImage(glw::GLint imageBindingPoint, glw::GLint textureBindingPoint, glw::GLint textureName,
1374                          const Vec4 &color) const;
1375     glu::DataType getImageTexCoordType(void) const;
1376 
1377     const glw::GLenum m_imageType;
1378     const glw::GLenum m_textureType;
1379 
1380     std::vector<glw::GLuint> m_textures;
1381     std::vector<Vec4> m_textureColors;
1382 };
1383 
ImageBindingRenderCase(Context & context,const char * name,const char * desc,ShaderType shaderType,TestType testType,glw::GLenum imageType,glw::GLenum textureType)1384 ImageBindingRenderCase::ImageBindingRenderCase(Context &context, const char *name, const char *desc,
1385                                                ShaderType shaderType, TestType testType, glw::GLenum imageType,
1386                                                glw::GLenum textureType)
1387     : LayoutBindingRenderCase(context, name, desc, shaderType, testType, GL_MAX_IMAGE_UNITS,
1388                               GL_MAX_VERTEX_IMAGE_UNIFORMS, GL_MAX_FRAGMENT_IMAGE_UNIFORMS,
1389                               GL_MAX_COMBINED_IMAGE_UNIFORMS, "u_image")
1390     , m_imageType(imageType)
1391     , m_textureType(textureType)
1392 {
1393 }
1394 
~ImageBindingRenderCase(void)1395 ImageBindingRenderCase::~ImageBindingRenderCase(void)
1396 {
1397     deinit();
1398 }
1399 
init(void)1400 void ImageBindingRenderCase::init(void)
1401 {
1402     LayoutBindingRenderCase::init();
1403 
1404     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1405     de::Random rnd(deStringHash(getName()) ^ 0xff23a4);
1406 
1407     // Initialize image / texture resources
1408     m_textures = std::vector<glw::GLuint>(m_numBindings, 0);
1409 
1410     // Texture colors
1411     for (int texNdx = 0; texNdx < (int)m_textures.size(); ++texNdx)
1412         m_textureColors.push_back(getRandomColor(rnd));
1413 
1414     // Image textures
1415     gl.genTextures(m_numBindings, &m_textures[0]);
1416 
1417     for (int texNdx = 0; texNdx < (int)m_textures.size(); ++texNdx)
1418         initializeImage(m_bindings[texNdx], texNdx, m_textures[texNdx], m_textureColors[texNdx]);
1419 }
1420 
deinit(void)1421 void ImageBindingRenderCase::deinit(void)
1422 {
1423     LayoutBindingRenderCase::deinit();
1424 
1425     // Clean up texture data
1426     for (int texNdx = 0; texNdx < (int)m_textures.size(); ++texNdx)
1427     {
1428         if (m_textures[texNdx])
1429         {
1430             m_context.getRenderContext().getFunctions().deleteTextures(1, &m_textures[texNdx]);
1431             m_context.getRenderContext().getFunctions().bindTexture(m_textureType, 0);
1432         }
1433     }
1434 }
1435 
iterate(void)1436 TestCase::IterateResult ImageBindingRenderCase::iterate(void)
1437 {
1438     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1439     const int iterations     = m_numBindings;
1440     const bool arrayInstance = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY);
1441     bool queryTestPassed     = true;
1442     bool imageTestPassed     = true;
1443 
1444     // Set the viewport and enable the shader program
1445     initRenderState();
1446 
1447     for (int iterNdx = 0; iterNdx < iterations; ++iterNdx)
1448     {
1449         // Set the uniform value indicating the current array index
1450         gl.uniform1i(m_shaderProgramArrayNdxLoc, iterNdx);
1451 
1452         const std::string name =
1453             (arrayInstance ? getUniformName(m_uniformName, 0, iterNdx) : getUniformName(m_uniformName, iterNdx));
1454         const glw::GLint binding = m_bindings[iterNdx];
1455         glw::GLint val           = -1;
1456 
1457         gl.getUniformiv(m_program->getProgram(), gl.getUniformLocation(m_program->getProgram(), name.c_str()), &val);
1458         m_testCtx.getLog() << tcu::TestLog::Message << "Querying binding point for " << name << ": " << val
1459                            << " == " << binding << tcu::TestLog::EndMessage;
1460         GLU_EXPECT_NO_ERROR(gl.getError(), "Binding point query failed");
1461 
1462         // Draw and verify
1463         if (val != binding)
1464             queryTestPassed = false;
1465         if (!drawAndVerifyResult(m_textureColors[iterNdx]))
1466             imageTestPassed = false;
1467     }
1468 
1469     setTestResult(queryTestPassed, imageTestPassed);
1470     return STOP;
1471 }
1472 
initializeImage(glw::GLint imageBindingPoint,glw::GLint textureBindingPoint,glw::GLint textureName,const Vec4 & color) const1473 void ImageBindingRenderCase::initializeImage(glw::GLint imageBindingPoint, glw::GLint textureBindingPoint,
1474                                              glw::GLint textureName, const Vec4 &color) const
1475 {
1476     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1477 
1478     gl.activeTexture(GL_TEXTURE0 + textureBindingPoint);
1479     gl.bindTexture(m_textureType, textureName);
1480     gl.texParameteri(m_textureType, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1481 
1482     switch (m_textureType)
1483     {
1484     case GL_TEXTURE_2D:
1485     {
1486         tcu::TextureLevel level(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8),
1487                                 TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE);
1488         tcu::clear(level.getAccess(), color);
1489         gl.texStorage2D(m_textureType, 1, GL_RGBA8, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE);
1490         gl.texSubImage2D(m_textureType, 0, 0, 0, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE, GL_RGBA, GL_UNSIGNED_BYTE,
1491                          level.getAccess().getDataPtr());
1492         break;
1493     }
1494 
1495     case GL_TEXTURE_3D:
1496     {
1497         tcu::TextureLevel level(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8),
1498                                 TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE);
1499         tcu::clear(level.getAccess(), color);
1500         gl.texStorage3D(m_textureType, 1, GL_RGBA8, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE);
1501         gl.texSubImage3D(m_textureType, 0, 0, 0, 0, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE, GL_RGBA,
1502                          GL_UNSIGNED_BYTE, level.getAccess().getDataPtr());
1503         break;
1504     }
1505 
1506     default:
1507         DE_ASSERT(false);
1508     }
1509 
1510     gl.bindTexture(m_textureType, 0);
1511     gl.bindImageTexture(imageBindingPoint, textureName, 0, GL_TRUE, 0, GL_READ_ONLY, GL_RGBA8);
1512     GLU_EXPECT_NO_ERROR(gl.getError(), "Image initialization failed");
1513 }
1514 
generateShaders(void) const1515 glu::ShaderProgram *ImageBindingRenderCase::generateShaders(void) const
1516 {
1517     std::ostringstream shaderUniformDecl;
1518     std::ostringstream shaderBody;
1519 
1520     const std::string texCoordType = glu::getDataTypeName(getImageTexCoordType());
1521     const std::string imageType    = glu::getDataTypeName(glu::getDataTypeFromGLType(m_imageType));
1522     const bool arrayInstance =
1523         (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY) ? true : false;
1524     const int numDeclarations = (arrayInstance ? 1 : m_numBindings);
1525 
1526     // Generate the uniform declarations for the vertex and fragment shaders
1527     for (int declNdx = 0; declNdx < numDeclarations; ++declNdx)
1528     {
1529         shaderUniformDecl << "layout(rgba8, binding = " << m_bindings[declNdx] << ") uniform readonly highp "
1530                           << imageType << " "
1531                           << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) :
1532                                               getUniformName(m_uniformName, declNdx))
1533                           << ";\n";
1534     }
1535 
1536     // Generate the shader body for the vertex and fragment shaders
1537     for (int bindNdx = 0; bindNdx < m_numBindings; ++bindNdx)
1538     {
1539         shaderBody << "    " << (bindNdx == 0 ? "if" : "else if") << " (u_arrayNdx == " << de::toString(bindNdx)
1540                    << ")\n"
1541                    << "    {\n"
1542                    << "        color = imageLoad("
1543                    << (arrayInstance ? getUniformName(m_uniformName, 0, bindNdx) :
1544                                        getUniformName(m_uniformName, bindNdx))
1545                    << ", " << texCoordType << "(0));\n"
1546                    << "    }\n";
1547     }
1548 
1549     shaderBody << "    else\n"
1550                << "    {\n"
1551                << "        color = vec4(0.0, 0.0, 0.0, 1.0);\n"
1552                << "    }\n";
1553 
1554     return new glu::ShaderProgram(m_context.getRenderContext(),
1555                                   glu::ProgramSources()
1556                                       << glu::VertexSource(generateVertexShader(m_shaderType, shaderUniformDecl.str(),
1557                                                                                 shaderBody.str()))
1558                                       << glu::FragmentSource(generateFragmentShader(
1559                                              m_shaderType, shaderUniformDecl.str(), shaderBody.str())));
1560 }
1561 
getImageTexCoordType(void) const1562 glu::DataType ImageBindingRenderCase::getImageTexCoordType(void) const
1563 {
1564     switch (m_imageType)
1565     {
1566     case GL_IMAGE_2D:
1567         return glu::TYPE_INT_VEC2;
1568 
1569     case GL_IMAGE_3D:
1570         return glu::TYPE_INT_VEC3;
1571 
1572     default:
1573         DE_ASSERT(false);
1574         return glu::TYPE_INVALID;
1575     }
1576 }
1577 
1578 class ImageBindingNegativeCase : public LayoutBindingNegativeCase
1579 {
1580 public:
1581     ImageBindingNegativeCase(Context &context, const char *name, const char *desc, ShaderType shaderType,
1582                              TestType testType, ErrorType errorType, glw::GLenum imageType);
1583     ~ImageBindingNegativeCase(void);
1584 
1585 private:
1586     glu::ShaderProgram *generateShaders(void) const;
1587     glu::DataType getImageTexCoordType(void) const;
1588 
1589     const glw::GLenum m_imageType;
1590 };
1591 
ImageBindingNegativeCase(Context & context,const char * name,const char * desc,ShaderType shaderType,TestType testType,ErrorType errorType,glw::GLenum imageType)1592 ImageBindingNegativeCase::ImageBindingNegativeCase(Context &context, const char *name, const char *desc,
1593                                                    ShaderType shaderType, TestType testType, ErrorType errorType,
1594                                                    glw::GLenum imageType)
1595     : LayoutBindingNegativeCase(context, name, desc, shaderType, testType, errorType, GL_MAX_IMAGE_UNITS,
1596                                 GL_MAX_VERTEX_IMAGE_UNIFORMS, GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS,
1597                                 GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS, GL_MAX_FRAGMENT_IMAGE_UNIFORMS,
1598                                 GL_MAX_COMBINED_IMAGE_UNIFORMS, "u_image")
1599     , m_imageType(imageType)
1600 {
1601 }
1602 
~ImageBindingNegativeCase(void)1603 ImageBindingNegativeCase::~ImageBindingNegativeCase(void)
1604 {
1605     deinit();
1606 }
1607 
generateShaders(void) const1608 glu::ShaderProgram *ImageBindingNegativeCase::generateShaders(void) const
1609 {
1610     std::ostringstream vertexUniformDecl;
1611     std::ostringstream fragmentUniformDecl;
1612     std::ostringstream tessCtrlUniformDecl;
1613     std::ostringstream tessEvalUniformDecl;
1614     std::ostringstream shaderBody;
1615 
1616     const std::string texCoordType = glu::getDataTypeName(getImageTexCoordType());
1617     const std::string imageType    = glu::getDataTypeName(glu::getDataTypeFromGLType(m_imageType));
1618     const bool arrayInstance       = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY);
1619     const int numDeclarations      = (arrayInstance ? 1 : m_numBindings);
1620 
1621     // Generate the uniform declarations for the vertex and fragment shaders
1622     for (int declNdx = 0; declNdx < numDeclarations; ++declNdx)
1623     {
1624         vertexUniformDecl << "layout(rgba8, binding = " << m_vertexShaderBinding[declNdx] << ") uniform readonly highp "
1625                           << imageType << " "
1626                           << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) :
1627                                               getUniformName(m_uniformName, declNdx))
1628                           << ";\n";
1629         fragmentUniformDecl << "layout(rgba8, binding = " << m_fragmentShaderBinding[declNdx]
1630                             << ") uniform readonly highp " << imageType << " "
1631                             << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) :
1632                                                 getUniformName(m_uniformName, declNdx))
1633                             << ";\n";
1634         tessCtrlUniformDecl << "layout(rgba8, binding = " << m_tessCtrlShaderBinding[declNdx]
1635                             << ") uniform readonly highp " << imageType << " "
1636                             << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) :
1637                                                 getUniformName(m_uniformName, declNdx))
1638                             << ";\n";
1639         tessEvalUniformDecl << "layout(rgba8, binding = " << m_tessEvalShaderBinding[declNdx]
1640                             << ") uniform readonly highp " << imageType << " "
1641                             << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) :
1642                                                 getUniformName(m_uniformName, declNdx))
1643                             << ";\n";
1644     }
1645 
1646     // Generate the shader body for the vertex and fragment shaders
1647     for (int bindNdx = 0; bindNdx < m_numBindings; ++bindNdx)
1648     {
1649         shaderBody << "    " << (bindNdx == 0 ? "if" : "else if") << " (u_arrayNdx == " << de::toString(bindNdx)
1650                    << ")\n"
1651                    << "    {\n"
1652                    << "        color = imageLoad("
1653                    << (arrayInstance ? getUniformName(m_uniformName, 0, bindNdx) :
1654                                        getUniformName(m_uniformName, bindNdx))
1655                    << ", " << texCoordType << "(0));\n"
1656                    << "    }\n";
1657     }
1658 
1659     shaderBody << "    else\n"
1660                << "    {\n"
1661                << "        color = vec4(0.0, 0.0, 0.0, 1.0);\n"
1662                << "    }\n";
1663 
1664     glu::ProgramSources sources = glu::ProgramSources()
1665                                   << glu::VertexSource(
1666                                          generateVertexShader(m_shaderType, vertexUniformDecl.str(), shaderBody.str()))
1667                                   << glu::FragmentSource(generateFragmentShader(m_shaderType, fragmentUniformDecl.str(),
1668                                                                                 shaderBody.str()));
1669 
1670     if (m_tessSupport)
1671         sources << glu::TessellationControlSource(
1672                        generateTessControlShader(m_shaderType, tessCtrlUniformDecl.str(), shaderBody.str()))
1673                 << glu::TessellationEvaluationSource(
1674                        generateTessEvaluationShader(m_shaderType, tessEvalUniformDecl.str(), shaderBody.str()));
1675 
1676     return new glu::ShaderProgram(m_context.getRenderContext(), sources);
1677 }
1678 
getImageTexCoordType(void) const1679 glu::DataType ImageBindingNegativeCase::getImageTexCoordType(void) const
1680 {
1681     switch (m_imageType)
1682     {
1683     case GL_IMAGE_2D:
1684         return glu::TYPE_INT_VEC2;
1685 
1686     case GL_IMAGE_3D:
1687         return glu::TYPE_INT_VEC3;
1688 
1689     default:
1690         DE_ASSERT(false);
1691         return glu::TYPE_INVALID;
1692     }
1693 }
1694 
1695 class UBOBindingRenderCase : public LayoutBindingRenderCase
1696 {
1697 public:
1698     UBOBindingRenderCase(Context &context, const char *name, const char *desc, ShaderType shaderType,
1699                          TestType testType);
1700     ~UBOBindingRenderCase(void);
1701 
1702     void init(void);
1703     void deinit(void);
1704     IterateResult iterate(void);
1705 
1706 private:
1707     glu::ShaderProgram *generateShaders(void) const;
1708 
1709     std::vector<uint32_t> m_buffers;
1710     std::vector<Vec4> m_expectedColors;
1711 };
1712 
UBOBindingRenderCase(Context & context,const char * name,const char * desc,ShaderType shaderType,TestType testType)1713 UBOBindingRenderCase::UBOBindingRenderCase(Context &context, const char *name, const char *desc, ShaderType shaderType,
1714                                            TestType testType)
1715     : LayoutBindingRenderCase(context, name, desc, shaderType, testType, GL_MAX_UNIFORM_BUFFER_BINDINGS,
1716                               GL_MAX_VERTEX_UNIFORM_BLOCKS, GL_MAX_FRAGMENT_UNIFORM_BLOCKS,
1717                               GL_MAX_COMBINED_UNIFORM_BLOCKS, "ColorBlock")
1718 {
1719 }
1720 
~UBOBindingRenderCase(void)1721 UBOBindingRenderCase::~UBOBindingRenderCase(void)
1722 {
1723     deinit();
1724 }
1725 
init(void)1726 void UBOBindingRenderCase::init(void)
1727 {
1728     LayoutBindingRenderCase::init();
1729 
1730     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1731     de::Random rnd(deStringHash(getName()) ^ 0xff23a4);
1732 
1733     // Initialize UBOs and related data
1734     m_buffers = std::vector<glw::GLuint>(m_numBindings, 0);
1735     gl.genBuffers((glw::GLsizei)m_buffers.size(), &m_buffers[0]);
1736 
1737     for (int bufNdx = 0; bufNdx < (int)m_buffers.size(); ++bufNdx)
1738     {
1739         m_expectedColors.push_back(getRandomColor(rnd));
1740         m_expectedColors.push_back(getRandomColor(rnd));
1741     }
1742 
1743     for (int bufNdx = 0; bufNdx < (int)m_buffers.size(); ++bufNdx)
1744     {
1745         gl.bindBuffer(GL_UNIFORM_BUFFER, m_buffers[bufNdx]);
1746         gl.bufferData(GL_UNIFORM_BUFFER, 2 * sizeof(Vec4), &(m_expectedColors[2 * bufNdx]), GL_STATIC_DRAW);
1747         gl.bindBufferBase(GL_UNIFORM_BUFFER, m_bindings[bufNdx], m_buffers[bufNdx]);
1748     }
1749 
1750     GLU_EXPECT_NO_ERROR(gl.getError(), "UBO setup failed");
1751 }
1752 
deinit(void)1753 void UBOBindingRenderCase::deinit(void)
1754 {
1755     LayoutBindingRenderCase::deinit();
1756 
1757     // Clean up UBO data
1758     for (int bufNdx = 0; bufNdx < (int)m_buffers.size(); ++bufNdx)
1759     {
1760         if (m_buffers[bufNdx])
1761         {
1762             m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_buffers[bufNdx]);
1763             m_context.getRenderContext().getFunctions().bindBuffer(GL_UNIFORM_BUFFER, 0);
1764         }
1765     }
1766 }
1767 
iterate(void)1768 TestCase::IterateResult UBOBindingRenderCase::iterate(void)
1769 {
1770     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1771     const int iterations     = m_numBindings;
1772     const glw::GLenum prop   = GL_BUFFER_BINDING;
1773     const bool arrayInstance = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY);
1774     bool queryTestPassed     = true;
1775     bool imageTestPassed     = true;
1776 
1777     // Set the viewport and enable the shader program
1778     initRenderState();
1779 
1780     for (int iterNdx = 0; iterNdx < iterations; ++iterNdx)
1781     {
1782         // Query binding point
1783         const std::string name =
1784             (arrayInstance ? getUniformName(m_uniformName, 0, iterNdx) : getUniformName(m_uniformName, iterNdx));
1785         const glw::GLint binding = m_bindings[iterNdx];
1786         glw::GLint val           = -1;
1787 
1788         gl.getProgramResourceiv(m_program->getProgram(), GL_UNIFORM_BLOCK,
1789                                 gl.getProgramResourceIndex(m_program->getProgram(), GL_UNIFORM_BLOCK, name.c_str()), 1,
1790                                 &prop, 1, DE_NULL, &val);
1791         m_testCtx.getLog() << tcu::TestLog::Message << "Querying binding point for " << name << ": " << val
1792                            << " == " << binding << tcu::TestLog::EndMessage;
1793         GLU_EXPECT_NO_ERROR(gl.getError(), "Binding point query failed");
1794 
1795         if (val != binding)
1796             queryTestPassed = false;
1797 
1798         // Draw twice to render both colors within the UBO
1799         for (int drawCycle = 0; drawCycle < 2; ++drawCycle)
1800         {
1801             // Set the uniform indicating the array index to be used and set the expected color
1802             const int arrayNdx = iterNdx * 2 + drawCycle;
1803             gl.uniform1i(m_shaderProgramArrayNdxLoc, arrayNdx);
1804 
1805             if (!drawAndVerifyResult(m_expectedColors[arrayNdx]))
1806                 imageTestPassed = false;
1807         }
1808     }
1809 
1810     setTestResult(queryTestPassed, imageTestPassed);
1811     return STOP;
1812 }
1813 
generateShaders(void) const1814 glu::ShaderProgram *UBOBindingRenderCase::generateShaders(void) const
1815 {
1816     std::ostringstream shaderUniformDecl;
1817     std::ostringstream shaderBody;
1818     const bool arrayInstance  = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY);
1819     const int numDeclarations = (arrayInstance ? 1 : m_numBindings);
1820 
1821     // Generate the uniform declarations for the vertex and fragment shaders
1822     for (int declNdx = 0; declNdx < numDeclarations; ++declNdx)
1823     {
1824         shaderUniformDecl << "layout(std140, binding = " << m_bindings[declNdx] << ") uniform "
1825                           << getUniformName(m_uniformName, declNdx) << "\n"
1826                           << "{\n"
1827                           << "    highp vec4 color1;\n"
1828                           << "    highp vec4 color2;\n"
1829                           << "} "
1830                           << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) :
1831                                               getUniformName("colors", declNdx))
1832                           << ";\n";
1833     }
1834 
1835     // Generate the shader body for the vertex and fragment shaders
1836     for (int bindNdx = 0; bindNdx < m_numBindings * 2;
1837          ++bindNdx) // Multiply by two to cover cases for both colors for each UBO
1838     {
1839         const std::string uname =
1840             (arrayInstance ? getUniformName("colors", 0, bindNdx / 2) : getUniformName("colors", bindNdx / 2));
1841         shaderBody << "    " << (bindNdx == 0 ? "if" : "else if") << " (u_arrayNdx == " << de::toString(bindNdx)
1842                    << ")\n"
1843                    << "    {\n"
1844                    << "        color = " << uname << (bindNdx % 2 == 0 ? ".color1" : ".color2") << ";\n"
1845                    << "    }\n";
1846     }
1847 
1848     shaderBody << "    else\n"
1849                << "    {\n"
1850                << "        color = vec4(0.0, 0.0, 0.0, 1.0);\n"
1851                << "    }\n";
1852 
1853     return new glu::ShaderProgram(m_context.getRenderContext(),
1854                                   glu::ProgramSources()
1855                                       << glu::VertexSource(generateVertexShader(m_shaderType, shaderUniformDecl.str(),
1856                                                                                 shaderBody.str()))
1857                                       << glu::FragmentSource(generateFragmentShader(
1858                                              m_shaderType, shaderUniformDecl.str(), shaderBody.str())));
1859 }
1860 
1861 class UBOBindingNegativeCase : public LayoutBindingNegativeCase
1862 {
1863 public:
1864     UBOBindingNegativeCase(Context &context, const char *name, const char *desc, ShaderType shaderType,
1865                            TestType testType, ErrorType errorType);
1866     ~UBOBindingNegativeCase(void);
1867 
1868 private:
1869     glu::ShaderProgram *generateShaders(void) const;
1870 };
1871 
UBOBindingNegativeCase(Context & context,const char * name,const char * desc,ShaderType shaderType,TestType testType,ErrorType errorType)1872 UBOBindingNegativeCase::UBOBindingNegativeCase(Context &context, const char *name, const char *desc,
1873                                                ShaderType shaderType, TestType testType, ErrorType errorType)
1874     : LayoutBindingNegativeCase(context, name, desc, shaderType, testType, errorType, GL_MAX_UNIFORM_BUFFER_BINDINGS,
1875                                 GL_MAX_VERTEX_UNIFORM_BLOCKS, GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS,
1876                                 GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS, GL_MAX_FRAGMENT_UNIFORM_BLOCKS,
1877                                 GL_MAX_COMBINED_UNIFORM_BLOCKS, "ColorBlock")
1878 {
1879 }
1880 
~UBOBindingNegativeCase(void)1881 UBOBindingNegativeCase::~UBOBindingNegativeCase(void)
1882 {
1883     deinit();
1884 }
1885 
generateShaders(void) const1886 glu::ShaderProgram *UBOBindingNegativeCase::generateShaders(void) const
1887 {
1888     std::ostringstream vertexUniformDecl;
1889     std::ostringstream fragmentUniformDecl;
1890     std::ostringstream tessCtrlUniformDecl;
1891     std::ostringstream tessEvalUniformDecl;
1892     std::ostringstream shaderBody;
1893     const bool arrayInstance  = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY);
1894     const int numDeclarations = (arrayInstance ? 1 : m_numBindings);
1895 
1896     // Generate the uniform declarations for the vertex and fragment shaders
1897     for (int declNdx = 0; declNdx < numDeclarations; ++declNdx)
1898     {
1899         vertexUniformDecl << "layout(std140, binding = " << m_vertexShaderBinding[declNdx] << ") uniform "
1900                           << getUniformName(m_uniformName, declNdx) << "\n"
1901                           << "{\n"
1902                           << "    highp vec4 color1;\n"
1903                           << "    highp vec4 color2;\n"
1904                           << "} "
1905                           << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) :
1906                                               getUniformName("colors", declNdx))
1907                           << ";\n";
1908 
1909         fragmentUniformDecl << "layout(std140, binding = " << m_fragmentShaderBinding[declNdx] << ") uniform "
1910                             << getUniformName(m_uniformName, declNdx) << "\n"
1911                             << "{\n"
1912                             << "    highp vec4 color1;\n"
1913                             << "    highp vec4 color2;\n"
1914                             << "} "
1915                             << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) :
1916                                                 getUniformName("colors", declNdx))
1917                             << ";\n";
1918 
1919         tessCtrlUniformDecl << "layout(std140, binding = " << m_tessCtrlShaderBinding[declNdx] << ") uniform "
1920                             << getUniformName(m_uniformName, declNdx) << "\n"
1921                             << "{\n"
1922                             << "    highp vec4 color1;\n"
1923                             << "    highp vec4 color2;\n"
1924                             << "} "
1925                             << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) :
1926                                                 getUniformName("colors", declNdx))
1927                             << ";\n";
1928 
1929         tessEvalUniformDecl << "layout(std140, binding = " << m_tessCtrlShaderBinding[declNdx] << ") uniform "
1930                             << getUniformName(m_uniformName, declNdx) << "\n"
1931                             << "{\n"
1932                             << "    highp vec4 color1;\n"
1933                             << "    highp vec4 color2;\n"
1934                             << "} "
1935                             << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) :
1936                                                 getUniformName("colors", declNdx))
1937                             << ";\n";
1938     }
1939 
1940     // Generate the shader body for the vertex and fragment shaders
1941     for (int bindNdx = 0; bindNdx < m_numBindings * 2;
1942          ++bindNdx) // Multiply by two to cover cases for both colors for each UBO
1943     {
1944         const std::string uname =
1945             (arrayInstance ? getUniformName("colors", 0, bindNdx / 2) : getUniformName("colors", bindNdx / 2));
1946         shaderBody << "    " << (bindNdx == 0 ? "if" : "else if") << " (u_arrayNdx == " << de::toString(bindNdx)
1947                    << ")\n"
1948                    << "    {\n"
1949                    << "        color = " << uname << (bindNdx % 2 == 0 ? ".color1" : ".color2") << ";\n"
1950                    << "    }\n";
1951     }
1952 
1953     shaderBody << "    else\n"
1954                << "    {\n"
1955                << "        color = vec4(0.0, 0.0, 0.0, 1.0);\n"
1956                << "    }\n";
1957 
1958     glu::ProgramSources sources = glu::ProgramSources()
1959                                   << glu::VertexSource(
1960                                          generateVertexShader(m_shaderType, vertexUniformDecl.str(), shaderBody.str()))
1961                                   << glu::FragmentSource(generateFragmentShader(m_shaderType, fragmentUniformDecl.str(),
1962                                                                                 shaderBody.str()));
1963 
1964     if (m_tessSupport)
1965         sources << glu::TessellationControlSource(
1966                        generateTessControlShader(m_shaderType, tessCtrlUniformDecl.str(), shaderBody.str()))
1967                 << glu::TessellationEvaluationSource(
1968                        generateTessEvaluationShader(m_shaderType, tessEvalUniformDecl.str(), shaderBody.str()));
1969 
1970     return new glu::ShaderProgram(m_context.getRenderContext(), sources);
1971 }
1972 
1973 class SSBOBindingRenderCase : public LayoutBindingRenderCase
1974 {
1975 public:
1976     SSBOBindingRenderCase(Context &context, const char *name, const char *desc, ShaderType shaderType,
1977                           TestType testType);
1978     ~SSBOBindingRenderCase(void);
1979 
1980     void init(void);
1981     void deinit(void);
1982     IterateResult iterate(void);
1983 
1984 private:
1985     glu::ShaderProgram *generateShaders(void) const;
1986 
1987     std::vector<glw::GLuint> m_buffers;
1988     std::vector<Vec4> m_expectedColors;
1989 };
1990 
SSBOBindingRenderCase(Context & context,const char * name,const char * desc,ShaderType shaderType,TestType testType)1991 SSBOBindingRenderCase::SSBOBindingRenderCase(Context &context, const char *name, const char *desc,
1992                                              ShaderType shaderType, TestType testType)
1993     : LayoutBindingRenderCase(context, name, desc, shaderType, testType, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS,
1994                               GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS,
1995                               GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, "ColorBuffer")
1996 {
1997 }
1998 
~SSBOBindingRenderCase(void)1999 SSBOBindingRenderCase::~SSBOBindingRenderCase(void)
2000 {
2001     deinit();
2002 }
2003 
init(void)2004 void SSBOBindingRenderCase::init(void)
2005 {
2006     LayoutBindingRenderCase::init();
2007 
2008     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2009     de::Random rnd(deStringHash(getName()) ^ 0xff23a4);
2010 
2011     // Initialize SSBOs and related data
2012     m_buffers = std::vector<glw::GLuint>(m_numBindings, 0);
2013     gl.genBuffers((glw::GLsizei)m_buffers.size(), &m_buffers[0]);
2014 
2015     for (int bufNdx = 0; bufNdx < (int)m_buffers.size(); ++bufNdx)
2016     {
2017         m_expectedColors.push_back(getRandomColor(rnd));
2018         m_expectedColors.push_back(getRandomColor(rnd));
2019     }
2020 
2021     for (int bufNdx = 0; bufNdx < (int)m_buffers.size(); ++bufNdx)
2022     {
2023         gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffers[bufNdx]);
2024         gl.bufferData(GL_SHADER_STORAGE_BUFFER, 2 * sizeof(Vec4), &(m_expectedColors[2 * bufNdx]), GL_STATIC_DRAW);
2025         gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, m_bindings[bufNdx], m_buffers[bufNdx]);
2026     }
2027 
2028     GLU_EXPECT_NO_ERROR(gl.getError(), "SSBO setup failed");
2029 }
2030 
deinit(void)2031 void SSBOBindingRenderCase::deinit(void)
2032 {
2033     LayoutBindingRenderCase::deinit();
2034 
2035     // Clean up SSBO data
2036     for (int bufNdx = 0; bufNdx < (int)m_buffers.size(); ++bufNdx)
2037     {
2038         if (m_buffers[bufNdx])
2039         {
2040             m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_buffers[bufNdx]);
2041             m_context.getRenderContext().getFunctions().bindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
2042             m_buffers[bufNdx] = 0;
2043         }
2044     }
2045 }
2046 
iterate(void)2047 TestCase::IterateResult SSBOBindingRenderCase::iterate(void)
2048 {
2049     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2050     const int iterations     = m_numBindings;
2051     const glw::GLenum prop   = GL_BUFFER_BINDING;
2052     const bool arrayInstance = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY);
2053     bool queryTestPassed     = true;
2054     bool imageTestPassed     = true;
2055 
2056     initRenderState();
2057 
2058     for (int iterNdx = 0; iterNdx < iterations; ++iterNdx)
2059     {
2060         // Query binding point
2061         const std::string name =
2062             (arrayInstance ? getUniformName(m_uniformName, 0, iterNdx) : getUniformName(m_uniformName, iterNdx));
2063         const glw::GLint binding = m_bindings[iterNdx];
2064         glw::GLint val           = -1;
2065 
2066         gl.getProgramResourceiv(
2067             m_program->getProgram(), GL_SHADER_STORAGE_BLOCK,
2068             gl.getProgramResourceIndex(m_program->getProgram(), GL_SHADER_STORAGE_BLOCK, name.c_str()), 1, &prop, 1,
2069             DE_NULL, &val);
2070         m_testCtx.getLog() << tcu::TestLog::Message << "Querying binding point for " << name << ": " << val
2071                            << " == " << binding << tcu::TestLog::EndMessage;
2072         GLU_EXPECT_NO_ERROR(gl.getError(), "Binding point query failed");
2073 
2074         if (val != binding)
2075             queryTestPassed = false;
2076 
2077         // Draw twice to render both colors within the SSBO
2078         for (int drawCycle = 0; drawCycle < 2; ++drawCycle)
2079         {
2080             // Set the uniform indicating the array index to be used and set the expected color
2081             const int arrayNdx = iterNdx * 2 + drawCycle;
2082             gl.uniform1i(m_shaderProgramArrayNdxLoc, arrayNdx);
2083 
2084             if (!drawAndVerifyResult(m_expectedColors[arrayNdx]))
2085                 imageTestPassed = false;
2086         }
2087     }
2088 
2089     setTestResult(queryTestPassed, imageTestPassed);
2090     return STOP;
2091 }
2092 
generateShaders(void) const2093 glu::ShaderProgram *SSBOBindingRenderCase::generateShaders(void) const
2094 {
2095     std::ostringstream shaderUniformDecl;
2096     std::ostringstream shaderBody;
2097     const bool arrayInstance  = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY);
2098     const int numDeclarations = (arrayInstance ? 1 : m_numBindings);
2099 
2100     // Generate the uniform declarations for the vertex and fragment shaders
2101     for (int declNdx = 0; declNdx < numDeclarations; ++declNdx)
2102     {
2103         shaderUniformDecl << "layout(std140, binding = " << m_bindings[declNdx] << ") buffer "
2104                           << getUniformName(m_uniformName, declNdx) << "\n"
2105                           << "{\n"
2106                           << "    highp vec4 color1;\n"
2107                           << "    highp vec4 color2;\n"
2108                           << "} "
2109                           << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) :
2110                                               getUniformName("colors", declNdx))
2111                           << ";\n";
2112     }
2113 
2114     // Generate the shader body for the vertex and fragment shaders
2115     for (int bindNdx = 0; bindNdx < m_numBindings * 2;
2116          ++bindNdx) // Multiply by two to cover cases for both colors for each UBO
2117     {
2118         const std::string uname =
2119             (arrayInstance ? getUniformName("colors", 0, bindNdx / 2) : getUniformName("colors", bindNdx / 2));
2120         shaderBody << "    " << (bindNdx == 0 ? "if" : "else if") << " (u_arrayNdx == " << de::toString(bindNdx)
2121                    << ")\n"
2122                    << "    {\n"
2123                    << "        color = " << uname << (bindNdx % 2 == 0 ? ".color1" : ".color2") << ";\n"
2124                    << "    }\n";
2125     }
2126 
2127     shaderBody << "    else\n"
2128                << "    {\n"
2129                << "        color = vec4(0.0, 0.0, 0.0, 1.0);\n"
2130                << "    }\n";
2131 
2132     return new glu::ShaderProgram(m_context.getRenderContext(),
2133                                   glu::ProgramSources()
2134                                       << glu::VertexSource(generateVertexShader(m_shaderType, shaderUniformDecl.str(),
2135                                                                                 shaderBody.str()))
2136                                       << glu::FragmentSource(generateFragmentShader(
2137                                              m_shaderType, shaderUniformDecl.str(), shaderBody.str())));
2138 }
2139 
2140 class SSBOBindingNegativeCase : public LayoutBindingNegativeCase
2141 {
2142 public:
2143     SSBOBindingNegativeCase(Context &context, const char *name, const char *desc, ShaderType shaderType,
2144                             TestType testType, ErrorType errorType);
2145     ~SSBOBindingNegativeCase(void);
2146 
2147 private:
2148     glu::ShaderProgram *generateShaders(void) const;
2149 };
2150 
SSBOBindingNegativeCase(Context & context,const char * name,const char * desc,ShaderType shaderType,TestType testType,ErrorType errorType)2151 SSBOBindingNegativeCase::SSBOBindingNegativeCase(Context &context, const char *name, const char *desc,
2152                                                  ShaderType shaderType, TestType testType, ErrorType errorType)
2153     : LayoutBindingNegativeCase(context, name, desc, shaderType, testType, errorType,
2154                                 GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS,
2155                                 GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS, GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS,
2156                                 GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS,
2157                                 "ColorBuffer")
2158 {
2159 }
2160 
~SSBOBindingNegativeCase(void)2161 SSBOBindingNegativeCase::~SSBOBindingNegativeCase(void)
2162 {
2163     deinit();
2164 }
2165 
generateShaders(void) const2166 glu::ShaderProgram *SSBOBindingNegativeCase::generateShaders(void) const
2167 {
2168     std::ostringstream vertexUniformDecl;
2169     std::ostringstream fragmentUniformDecl;
2170     std::ostringstream tessCtrlUniformDecl;
2171     std::ostringstream tessEvalUniformDecl;
2172     std::ostringstream shaderBody;
2173     const bool arrayInstance  = (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY);
2174     const int numDeclarations = (arrayInstance ? 1 : m_numBindings);
2175 
2176     // Generate the uniform declarations for the vertex and fragment shaders
2177     for (int declNdx = 0; declNdx < numDeclarations; ++declNdx)
2178     {
2179         vertexUniformDecl << "layout(std140, binding = " << m_vertexShaderBinding[declNdx] << ") buffer "
2180                           << getUniformName(m_uniformName, declNdx) << "\n"
2181                           << "{\n"
2182                           << "    highp vec4 color1;\n"
2183                           << "    highp vec4 color2;\n"
2184                           << "} "
2185                           << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) :
2186                                               getUniformName("colors", declNdx))
2187                           << ";\n";
2188 
2189         fragmentUniformDecl << "layout(std140, binding = " << m_fragmentShaderBinding[declNdx] << ") buffer "
2190                             << getUniformName(m_uniformName, declNdx) << "\n"
2191                             << "{\n"
2192                             << "    highp vec4 color1;\n"
2193                             << "    highp vec4 color2;\n"
2194                             << "} "
2195                             << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) :
2196                                                 getUniformName("colors", declNdx))
2197                             << ";\n";
2198 
2199         tessCtrlUniformDecl << "layout(std140, binding = " << m_tessCtrlShaderBinding[declNdx] << ") buffer "
2200                             << getUniformName(m_uniformName, declNdx) << "\n"
2201                             << "{\n"
2202                             << "    highp vec4 color1;\n"
2203                             << "    highp vec4 color2;\n"
2204                             << "} "
2205                             << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) :
2206                                                 getUniformName("colors", declNdx))
2207                             << ";\n";
2208 
2209         tessEvalUniformDecl << "layout(std140, binding = " << m_tessEvalShaderBinding[declNdx] << ") buffer "
2210                             << getUniformName(m_uniformName, declNdx) << "\n"
2211                             << "{\n"
2212                             << "    highp vec4 color1;\n"
2213                             << "    highp vec4 color2;\n"
2214                             << "} "
2215                             << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) :
2216                                                 getUniformName("colors", declNdx))
2217                             << ";\n";
2218     }
2219 
2220     // Generate the shader body for the vertex and fragment shaders
2221     for (int bindNdx = 0; bindNdx < m_numBindings * 2;
2222          ++bindNdx) // Multiply by two to cover cases for both colors for each UBO
2223     {
2224         const std::string uname =
2225             (arrayInstance ? getUniformName("colors", 0, bindNdx / 2) : getUniformName("colors", bindNdx / 2));
2226         shaderBody << "    " << (bindNdx == 0 ? "if" : "else if") << " (u_arrayNdx == " << de::toString(bindNdx)
2227                    << ")\n"
2228                    << "    {\n"
2229                    << "        color = " << uname << (bindNdx % 2 == 0 ? ".color1" : ".color2") << ";\n"
2230                    << "    }\n";
2231     }
2232 
2233     shaderBody << "    else\n"
2234                << "    {\n"
2235                << "        color = vec4(0.0, 0.0, 0.0, 1.0);\n"
2236                << "    }\n";
2237 
2238     glu::ProgramSources sources = glu::ProgramSources()
2239                                   << glu::VertexSource(
2240                                          generateVertexShader(m_shaderType, vertexUniformDecl.str(), shaderBody.str()))
2241                                   << glu::FragmentSource(generateFragmentShader(m_shaderType, fragmentUniformDecl.str(),
2242                                                                                 shaderBody.str()));
2243 
2244     if (m_tessSupport)
2245         sources << glu::TessellationControlSource(
2246                        generateTessControlShader(m_shaderType, tessCtrlUniformDecl.str(), shaderBody.str()))
2247                 << glu::TessellationEvaluationSource(
2248                        generateTessEvaluationShader(m_shaderType, tessEvalUniformDecl.str(), shaderBody.str()));
2249 
2250     return new glu::ShaderProgram(m_context.getRenderContext(), sources);
2251 }
2252 
2253 } // namespace
2254 
LayoutBindingTests(Context & context)2255 LayoutBindingTests::LayoutBindingTests(Context &context)
2256     : TestCaseGroup(context, "layout_binding", "Layout binding tests")
2257 {
2258 }
2259 
~LayoutBindingTests(void)2260 LayoutBindingTests::~LayoutBindingTests(void)
2261 {
2262 }
2263 
init(void)2264 void LayoutBindingTests::init(void)
2265 {
2266     // Render test groups
2267     tcu::TestCaseGroup *const samplerBindingTestGroup =
2268         new tcu::TestCaseGroup(m_testCtx, "sampler", "Test sampler layout binding");
2269     tcu::TestCaseGroup *const sampler2dBindingTestGroup =
2270         new tcu::TestCaseGroup(m_testCtx, "sampler2d", "Test sampler2d layout binding");
2271     tcu::TestCaseGroup *const sampler3dBindingTestGroup =
2272         new tcu::TestCaseGroup(m_testCtx, "sampler3d", "Test sampler3d layout binding");
2273 
2274     tcu::TestCaseGroup *const imageBindingTestGroup =
2275         new tcu::TestCaseGroup(m_testCtx, "image", "Test image layout binding");
2276     tcu::TestCaseGroup *const image2dBindingTestGroup =
2277         new tcu::TestCaseGroup(m_testCtx, "image2d", "Test image2d layout binding");
2278     tcu::TestCaseGroup *const image3dBindingTestGroup =
2279         new tcu::TestCaseGroup(m_testCtx, "image3d", "Test image3d layout binding");
2280 
2281     tcu::TestCaseGroup *const UBOBindingTestGroup = new tcu::TestCaseGroup(m_testCtx, "ubo", "Test UBO layout binding");
2282     tcu::TestCaseGroup *const SSBOBindingTestGroup =
2283         new tcu::TestCaseGroup(m_testCtx, "ssbo", "Test SSBO layout binding");
2284 
2285     // Negative test groups
2286     tcu::TestCaseGroup *const negativeBindingTestGroup =
2287         new tcu::TestCaseGroup(m_testCtx, "negative", "Test layout binding with invalid bindings");
2288 
2289     tcu::TestCaseGroup *const negativeSamplerBindingTestGroup =
2290         new tcu::TestCaseGroup(m_testCtx, "sampler", "Test sampler layout binding with invalid bindings");
2291     tcu::TestCaseGroup *const negativeSampler2dBindingTestGroup =
2292         new tcu::TestCaseGroup(m_testCtx, "sampler2d", "Test sampler2d layout binding with invalid bindings");
2293     tcu::TestCaseGroup *const negativeSampler3dBindingTestGroup =
2294         new tcu::TestCaseGroup(m_testCtx, "sampler3d", "Test sampler3d layout binding with invalid bindings");
2295 
2296     tcu::TestCaseGroup *const negativeImageBindingTestGroup =
2297         new tcu::TestCaseGroup(m_testCtx, "image", "Test image layout binding with invalid bindings");
2298     tcu::TestCaseGroup *const negativeImage2dBindingTestGroup =
2299         new tcu::TestCaseGroup(m_testCtx, "image2d", "Test image2d layout binding with invalid bindings");
2300     tcu::TestCaseGroup *const negativeImage3dBindingTestGroup =
2301         new tcu::TestCaseGroup(m_testCtx, "image3d", "Test image3d layout binding with invalid bindings");
2302 
2303     tcu::TestCaseGroup *const negativeUBOBindingTestGroup =
2304         new tcu::TestCaseGroup(m_testCtx, "ubo", "Test UBO layout binding with invalid bindings");
2305     tcu::TestCaseGroup *const negativeSSBOBindingTestGroup =
2306         new tcu::TestCaseGroup(m_testCtx, "ssbo", "Test SSBO layout binding with invalid bindings");
2307 
2308     static const struct RenderTestType
2309     {
2310         ShaderType shaderType;
2311         TestType testType;
2312         std::string name;
2313         std::string descPostfix;
2314     } s_renderTestTypes[] = {
2315         {SHADERTYPE_VERTEX, TESTTYPE_BINDING_SINGLE, "vertex_binding_single", "a single instance"},
2316         {SHADERTYPE_VERTEX, TESTTYPE_BINDING_MAX, "vertex_binding_max", "maximum binding point"},
2317         {SHADERTYPE_VERTEX, TESTTYPE_BINDING_MULTIPLE, "vertex_binding_multiple", "multiple instances"},
2318         {SHADERTYPE_VERTEX, TESTTYPE_BINDING_ARRAY, "vertex_binding_array", "an array instance"},
2319         {SHADERTYPE_VERTEX, TESTTYPE_BINDING_MAX_ARRAY, "vertex_binding_max_array",
2320          "an array instance with maximum binding point"},
2321 
2322         {SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_SINGLE, "fragment_binding_single", "a single instance"},
2323         {SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_MAX, "fragment_binding_max", "maximum binding point"},
2324         {SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_MULTIPLE, "fragment_binding_multiple", "multiple instances"},
2325         {SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_ARRAY, "fragment_binding_array", "an array instance"},
2326         {SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_MAX_ARRAY, "fragment_binding_max_array",
2327          "an array instance with maximum binding point"},
2328     };
2329 
2330     static const struct NegativeTestType
2331     {
2332         ShaderType shaderType;
2333         TestType testType;
2334         LayoutBindingNegativeCase::ErrorType errorType;
2335         std::string name;
2336         std::string descPostfix;
2337     } s_negativeTestTypes[] = {
2338         {SHADERTYPE_VERTEX, TESTTYPE_BINDING_SINGLE, LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS,
2339          "vertex_binding_over_max", "over maximum binding point"},
2340         {SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_SINGLE, LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS,
2341          "fragment_binding_over_max", "over maximum binding point"},
2342         {SHADERTYPE_TESS_CONTROL, TESTTYPE_BINDING_SINGLE, LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS,
2343          "tess_control_binding_over_max", "over maximum binding point"},
2344         {SHADERTYPE_TESS_EVALUATION, TESTTYPE_BINDING_SINGLE, LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS,
2345          "tess_evaluation_binding_over_max", "over maximum binding point"},
2346         {SHADERTYPE_VERTEX, TESTTYPE_BINDING_SINGLE, LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO,
2347          "vertex_binding_neg", "negative binding point"},
2348         {SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_SINGLE, LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO,
2349          "fragment_binding_neg", "negative binding point"},
2350         {SHADERTYPE_TESS_CONTROL, TESTTYPE_BINDING_SINGLE, LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO,
2351          "tess_control_binding_neg", "negative binding point"},
2352         {SHADERTYPE_TESS_EVALUATION, TESTTYPE_BINDING_SINGLE, LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO,
2353          "tess_evaluation_binding_neg", "negative binding point"},
2354 
2355         {SHADERTYPE_VERTEX, TESTTYPE_BINDING_ARRAY, LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS,
2356          "vertex_binding_over_max_array", "over maximum binding point"},
2357         {SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_ARRAY, LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS,
2358          "fragment_binding_over_max_array", "over maximum binding point"},
2359         {SHADERTYPE_TESS_CONTROL, TESTTYPE_BINDING_ARRAY, LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS,
2360          "tess_control_binding_over_max_array", "over maximum binding point"},
2361         {SHADERTYPE_TESS_EVALUATION, TESTTYPE_BINDING_ARRAY, LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS,
2362          "tess_evaluation_binding_over_max_array", "over maximum binding point"},
2363         {SHADERTYPE_VERTEX, TESTTYPE_BINDING_ARRAY, LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO,
2364          "vertex_binding_neg_array", "negative binding point"},
2365         {SHADERTYPE_FRAGMENT, TESTTYPE_BINDING_ARRAY, LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO,
2366          "fragment_binding_neg_array", "negative binding point"},
2367         {SHADERTYPE_TESS_CONTROL, TESTTYPE_BINDING_ARRAY, LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO,
2368          "tess_control_binding_neg_array", "negative binding point"},
2369         {SHADERTYPE_TESS_EVALUATION, TESTTYPE_BINDING_ARRAY, LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO,
2370          "tess_evaluation_binding_neg_array", "negative binding point"},
2371 
2372         {SHADERTYPE_ALL, TESTTYPE_BINDING_SINGLE, LayoutBindingNegativeCase::ERRORTYPE_CONTRADICTORY,
2373          "binding_contradictory", "contradictory binding points"},
2374         {SHADERTYPE_ALL, TESTTYPE_BINDING_ARRAY, LayoutBindingNegativeCase::ERRORTYPE_CONTRADICTORY,
2375          "binding_contradictory_array", "contradictory binding points"},
2376     };
2377 
2378     // Render tests
2379     for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(s_renderTestTypes); ++testNdx)
2380     {
2381         const RenderTestType &test = s_renderTestTypes[testNdx];
2382 
2383         // Render sampler binding tests
2384         sampler2dBindingTestGroup->addChild(new SamplerBindingRenderCase(
2385             m_context, test.name.c_str(), ("Sampler2D layout binding with " + test.descPostfix).c_str(),
2386             test.shaderType, test.testType, GL_SAMPLER_2D, GL_TEXTURE_2D));
2387         sampler3dBindingTestGroup->addChild(new SamplerBindingRenderCase(
2388             m_context, test.name.c_str(), ("Sampler3D layout binding with " + test.descPostfix).c_str(),
2389             test.shaderType, test.testType, GL_SAMPLER_3D, GL_TEXTURE_3D));
2390 
2391         // Render image binding tests
2392         image2dBindingTestGroup->addChild(new ImageBindingRenderCase(
2393             m_context, test.name.c_str(), ("Image2D layout binding with " + test.descPostfix).c_str(), test.shaderType,
2394             test.testType, GL_IMAGE_2D, GL_TEXTURE_2D));
2395         image3dBindingTestGroup->addChild(new ImageBindingRenderCase(
2396             m_context, test.name.c_str(), ("Image3D layout binding with " + test.descPostfix).c_str(), test.shaderType,
2397             test.testType, GL_IMAGE_3D, GL_TEXTURE_3D));
2398 
2399         // Render UBO binding tests
2400         UBOBindingTestGroup->addChild(new UBOBindingRenderCase(m_context, test.name.c_str(),
2401                                                                ("UBO layout binding with " + test.descPostfix).c_str(),
2402                                                                test.shaderType, test.testType));
2403 
2404         // Render SSBO binding tests
2405         SSBOBindingTestGroup->addChild(new SSBOBindingRenderCase(
2406             m_context, test.name.c_str(), ("SSBO layout binding with " + test.descPostfix).c_str(), test.shaderType,
2407             test.testType));
2408     }
2409 
2410     // Negative binding tests
2411     for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(s_negativeTestTypes); ++testNdx)
2412     {
2413         const NegativeTestType &test = s_negativeTestTypes[testNdx];
2414 
2415         // Negative sampler binding tests
2416         negativeSampler2dBindingTestGroup->addChild(new SamplerBindingNegativeCase(
2417             m_context, test.name.c_str(), ("Invalid sampler2d layout binding using " + test.descPostfix).c_str(),
2418             test.shaderType, test.testType, test.errorType, GL_SAMPLER_2D));
2419         negativeSampler3dBindingTestGroup->addChild(new SamplerBindingNegativeCase(
2420             m_context, test.name.c_str(), ("Invalid sampler3d layout binding using " + test.descPostfix).c_str(),
2421             test.shaderType, test.testType, test.errorType, GL_SAMPLER_3D));
2422 
2423         // Negative image binding tests
2424         negativeImage2dBindingTestGroup->addChild(new ImageBindingNegativeCase(
2425             m_context, test.name.c_str(), ("Invalid image2d layout binding using " + test.descPostfix).c_str(),
2426             test.shaderType, test.testType, test.errorType, GL_IMAGE_2D));
2427         negativeImage3dBindingTestGroup->addChild(new ImageBindingNegativeCase(
2428             m_context, test.name.c_str(), ("Invalid image3d layout binding using " + test.descPostfix).c_str(),
2429             test.shaderType, test.testType, test.errorType, GL_IMAGE_3D));
2430 
2431         // Negative UBO binding tests
2432         negativeUBOBindingTestGroup->addChild(new UBOBindingNegativeCase(
2433             m_context, test.name.c_str(), ("Invalid UBO layout binding using " + test.descPostfix).c_str(),
2434             test.shaderType, test.testType, test.errorType));
2435 
2436         // Negative SSBO binding tests
2437         negativeSSBOBindingTestGroup->addChild(new SSBOBindingNegativeCase(
2438             m_context, test.name.c_str(), ("Invalid SSBO layout binding using " + test.descPostfix).c_str(),
2439             test.shaderType, test.testType, test.errorType));
2440     }
2441 
2442     samplerBindingTestGroup->addChild(sampler2dBindingTestGroup);
2443     samplerBindingTestGroup->addChild(sampler3dBindingTestGroup);
2444 
2445     imageBindingTestGroup->addChild(image2dBindingTestGroup);
2446     imageBindingTestGroup->addChild(image3dBindingTestGroup);
2447 
2448     negativeSamplerBindingTestGroup->addChild(negativeSampler2dBindingTestGroup);
2449     negativeSamplerBindingTestGroup->addChild(negativeSampler3dBindingTestGroup);
2450 
2451     negativeImageBindingTestGroup->addChild(negativeImage2dBindingTestGroup);
2452     negativeImageBindingTestGroup->addChild(negativeImage3dBindingTestGroup);
2453 
2454     negativeBindingTestGroup->addChild(negativeSamplerBindingTestGroup);
2455     negativeBindingTestGroup->addChild(negativeUBOBindingTestGroup);
2456     negativeBindingTestGroup->addChild(negativeSSBOBindingTestGroup);
2457     negativeBindingTestGroup->addChild(negativeImageBindingTestGroup);
2458 
2459     addChild(samplerBindingTestGroup);
2460     addChild(UBOBindingTestGroup);
2461     addChild(SSBOBindingTestGroup);
2462     addChild(imageBindingTestGroup);
2463     addChild(negativeBindingTestGroup);
2464 }
2465 
2466 } // namespace Functional
2467 } // namespace gles31
2468 } // namespace deqp
2469