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