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