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