1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2014-2016 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 */ /*!
20 * \file
21 * \brief
22 */ /*-------------------------------------------------------------------*/
23 #include "es31cLayoutBindingTests.hpp"
24
25 #include "tcuRenderTarget.hpp"
26 #include "tcuStringTemplate.hpp"
27 #include "tcuSurface.hpp"
28 #include "tcuTestLog.hpp"
29 #include "tcuTexture.hpp"
30 #include "tcuTextureUtil.hpp"
31
32 #include "deRandom.hpp"
33 #include "deStringUtil.hpp"
34
35 #include "glwDefs.hpp"
36 #include "glwEnums.hpp"
37 #include "glwFunctions.hpp"
38
39 #include "gluDrawUtil.hpp"
40 #include "gluPixelTransfer.hpp"
41 #include "gluShaderProgram.hpp"
42 #include "gluTexture.hpp"
43 #include "gluTextureUtil.hpp"
44
45 namespace glcts
46 {
47
48 //=========================================================================
49 //= typedefs
50 //=========================================================================
51 typedef std::string String;
52 typedef std::map<String, String> StringMap;
53 typedef std::map<String, glw::GLint> StringIntMap;
54 typedef std::map<glw::GLint, glw::GLint> IntIntMap;
55 typedef std::vector<String> StringVector;
56 typedef std::vector<int> IntVector;
57
58 typedef std::map<int, glu::Texture2D*> Texture2DMap;
59 typedef std::map<int, glu::Texture2DArray*> Texture2DArrayMap;
60 typedef std::map<int, glu::Texture3D*> Texture3DMap;
61
62 //=========================================================================
63 //= utility classes
64 //=========================================================================
65
66 //= string stream that saves some typing
67 class StringStream : public std::ostringstream
68 {
69 public:
reset()70 void reset()
71 {
72 clear();
73 str("");
74 }
75 };
76
77 class LayoutBindingProgram;
78
79 class IProgramContextSupplier
80 {
81 public:
~IProgramContextSupplier()82 virtual ~IProgramContextSupplier()
83 {
84 }
85 virtual Context& getContext() = 0;
86 virtual const LayoutBindingParameters& getTestParameters() = 0;
87 virtual eStageType getStage() = 0;
88 virtual const String& getSource(eStageType stage) = 0;
89 virtual LayoutBindingProgram* createProgram() = 0;
90 };
91
92 class LayoutBindingProgram
93 {
94 public:
LayoutBindingProgram(IProgramContextSupplier & contextSupplier)95 LayoutBindingProgram(IProgramContextSupplier& contextSupplier)
96 : m_contextSupplier(contextSupplier)
97 , m_context(contextSupplier.getContext().getRenderContext())
98 , m_stage(contextSupplier.getStage())
99 , m_testParams(contextSupplier.getTestParameters())
100 , m_gl(contextSupplier.getContext().getRenderContext().getFunctions())
101 {
102 if (getStage() != ComputeShader)
103 m_program = new glu::ShaderProgram(
104 m_context, glu::makeVtxFragSources(m_contextSupplier.getSource(VertexShader).c_str(),
105 m_contextSupplier.getSource(FragmentShader).c_str()));
106 else
107 m_program = new glu::ShaderProgram(
108 m_context,
109 glu::ProgramSources() << glu::ComputeSource(m_contextSupplier.getSource(ComputeShader).c_str()));
110 }
~LayoutBindingProgram()111 virtual ~LayoutBindingProgram()
112 {
113 delete m_program;
114 }
115
116 class LayoutBindingProgramAutoPtr
117 {
118 public:
LayoutBindingProgramAutoPtr(IProgramContextSupplier & contextSupplier)119 LayoutBindingProgramAutoPtr(IProgramContextSupplier& contextSupplier)
120 {
121 m_program = contextSupplier.createProgram();
122 }
~LayoutBindingProgramAutoPtr()123 ~LayoutBindingProgramAutoPtr()
124 {
125 delete m_program;
126 }
operator ->()127 LayoutBindingProgram* operator->()
128 {
129 return m_program;
130 }
131
132 private:
133 LayoutBindingProgram* m_program;
134 };
135
getErrorLog(bool dumpShaders=false)136 String getErrorLog(bool dumpShaders = false)
137 {
138 StringStream errLog;
139
140 if (getStage() != ComputeShader)
141 {
142 const glu::ShaderInfo& fragmentShaderInfo = m_program->getShaderInfo(glu::SHADERTYPE_FRAGMENT);
143 const glu::ShaderInfo& vertexShaderInfo = m_program->getShaderInfo(glu::SHADERTYPE_VERTEX);
144
145 if (!fragmentShaderInfo.compileOk || !m_program->getProgramInfo().linkOk || dumpShaders)
146 {
147 errLog << "### dump of " << stageToName(FragmentShader) << "###\n";
148 String msg((dumpShaders ? "Fragment shader should not have compiled" :
149 "Vertex shader compile failed while testing "));
150 errLog << "Fragment shader compile failed while testing " << stageToName(getStage()) << ": "
151 << fragmentShaderInfo.infoLog << "\n";
152 errLog << m_contextSupplier.getSource(FragmentShader);
153 }
154 if (!vertexShaderInfo.compileOk || !m_program->getProgramInfo().linkOk || dumpShaders)
155 {
156 errLog << "### dump of " << stageToName(VertexShader) << "###\n";
157 String msg((dumpShaders ? "Vertex shader should not have compiled" :
158 "Vertex shader compile failed while testing "));
159 errLog << msg << stageToName(getStage()) << ": " << vertexShaderInfo.infoLog << "\n";
160 errLog << m_contextSupplier.getSource(VertexShader);
161 }
162 }
163 else
164 {
165 const glu::ShaderInfo& computeShaderInfo = m_program->getShaderInfo(glu::SHADERTYPE_COMPUTE);
166
167 if (!computeShaderInfo.compileOk || !m_program->getProgramInfo().linkOk || dumpShaders)
168 {
169 errLog << "### dump of " << stageToName(ComputeShader) << "###\n";
170 String msg((dumpShaders ? "Compute shader should not have compiled" :
171 "Compute shader compile failed while testing "));
172 errLog << msg << stageToName(ComputeShader) << ": " << computeShaderInfo.infoLog << "\n";
173 errLog << m_contextSupplier.getSource(ComputeShader);
174 }
175 }
176 if (!m_program->getProgramInfo().linkOk)
177 {
178 getStage();
179 errLog << "Linking failed while testing " << stageToName(getStage()) << ": "
180 << m_program->getProgramInfo().infoLog << "\n";
181 errLog << "### other stages ###\n";
182 switch (getStage())
183 {
184 case FragmentShader:
185 errLog << "### dump of " << stageToName(VertexShader) << "###\n";
186 errLog << m_contextSupplier.getSource(VertexShader);
187 break;
188 case VertexShader:
189 errLog << "### dump of " << stageToName(FragmentShader) << "###\n";
190 errLog << stageToName(FragmentShader) << "\n";
191 errLog << m_contextSupplier.getSource(FragmentShader);
192 break;
193 case ComputeShader:
194 errLog << "### dump of " << stageToName(ComputeShader) << "###\n";
195 errLog << stageToName(ComputeShader) << "\n";
196 errLog << m_contextSupplier.getSource(ComputeShader);
197 break;
198 default:
199 DE_ASSERT(0);
200 break;
201 }
202 }
203 return errLog.str();
204 }
205
206 private:
207 IProgramContextSupplier& m_contextSupplier;
208
209 const glu::RenderContext& m_context;
210 const eStageType m_stage; // shader stage currently tested
211 const LayoutBindingParameters& m_testParams; // parameters for shader generation (table at end of file)
212 const glw::Functions& m_gl;
213
214 glu::ShaderProgram* m_program;
215
216 private:
getUniformLocations(StringVector args) const217 StringIntMap getUniformLocations(StringVector args) const
218 {
219 StringVector::iterator it;
220 StringIntMap locations;
221 bool passed = true;
222
223 for (it = args.begin(); it != args.end(); it++)
224 {
225 const char* name = (*it).c_str();
226 glw::GLint location = m_gl.getUniformLocation(getProgram(), name);
227 passed &= (0 <= location);
228 if (passed)
229 {
230 locations[name] = location;
231 }
232 }
233
234 return locations;
235 }
236
237 public:
getProgram() const238 glw::GLint getProgram() const
239 {
240 return m_program->getProgram();
241 }
242
gl() const243 const glw::Functions& gl() const
244 {
245 return m_gl;
246 }
247
getStage() const248 virtual eStageType getStage() const
249 {
250 return m_stage;
251 }
252
stageToName(eStageType stage) const253 String stageToName(eStageType stage) const
254 {
255 switch (stage)
256 {
257 case FragmentShader:
258 return "FragmentShader";
259 case VertexShader:
260 return "VertexShader";
261 case ComputeShader:
262 return "ComputeShader";
263 default:
264 DE_ASSERT(0);
265 break;
266 }
267 return String();
268 }
269
error() const270 bool error() const
271 {
272 return (m_gl.getError() == GL_NO_ERROR);
273 }
274
compiledAndLinked() const275 bool compiledAndLinked() const
276 {
277 if (getStage() != ComputeShader)
278 return m_program->getShaderInfo(glu::SHADERTYPE_FRAGMENT).compileOk &&
279 m_program->getShaderInfo(glu::SHADERTYPE_VERTEX).compileOk && m_program->getProgramInfo().linkOk;
280
281 return m_program->getShaderInfo(glu::SHADERTYPE_COMPUTE).compileOk && m_program->getProgramInfo().linkOk;
282 }
283
getBindingPoints(StringVector args) const284 virtual StringIntMap getBindingPoints(StringVector args) const
285 {
286 StringIntMap bindingPoints;
287
288 StringIntMap locations = getUniformLocations(args);
289 if (!locations.empty())
290 {
291 glw::GLint bindingPoint;
292 for (StringIntMap::iterator it = locations.begin(); it != locations.end(); it++)
293 {
294 glw::GLint location = it->second;
295 m_gl.getUniformiv(getProgram(), location, &bindingPoint);
296 bool hasNoError = (GL_NO_ERROR == m_gl.getError());
297 if (hasNoError)
298 {
299 bindingPoints[it->first] = bindingPoint;
300 }
301 }
302 }
303 return bindingPoints;
304 }
305
setBindingPoints(StringVector list,glw::GLint bindingPoint) const306 virtual bool setBindingPoints(StringVector list, glw::GLint bindingPoint) const
307 {
308 bool bNoError = true;
309
310 StringIntMap locations = getUniformLocations(list);
311 if (!locations.empty())
312 {
313 for (StringIntMap::iterator it = locations.begin(); it != locations.end(); it++)
314 {
315 m_gl.uniform1i(it->second, bindingPoint);
316 bNoError &= (GL_NO_ERROR == m_gl.getError());
317 }
318 }
319 return bNoError;
320 }
321
getOffsets(StringVector) const322 virtual StringIntMap getOffsets(StringVector /*args*/) const
323 {
324 return StringIntMap();
325 }
326 };
327
328 class LayoutBindingTestResult
329 {
330 public:
LayoutBindingTestResult(bool passed=true,const String & reason=String (),bool notRunforThisContext=false)331 LayoutBindingTestResult(bool passed = true, const String& reason = String(), bool notRunforThisContext = false)
332 : m_passed(passed), m_notRunForThisContext(notRunforThisContext), m_reason(reason)
333 {
334 }
335
336 public:
testPassed() const337 bool testPassed() const
338 {
339 return m_passed;
340 }
341
getReason() const342 String getReason() const
343 {
344 return m_reason;
345 }
346
runForThisContext() const347 bool runForThisContext() const
348 {
349 return !m_notRunForThisContext;
350 }
351
352 private:
353 bool m_passed;
354 bool m_notRunForThisContext;
355 String m_reason;
356 };
357
358 class IntegerConstant
359 {
360 public:
361 enum Literals
362 {
363 decimal = 0,
364 decimal_u,
365 decimal_U,
366 octal,
367 octal_u,
368 octal_U,
369 hex_x,
370 hex_X,
371 hex_u,
372 hex_u_X,
373 hex_U,
374 hex_U_X,
375 last
376 };
377
378 public:
IntegerConstant(Literals lit,int ai)379 IntegerConstant(Literals lit, int ai) : asInt(ai)
380 {
381 StringStream s;
382 switch (lit)
383 {
384 case decimal:
385 s << asInt;
386 break;
387 case decimal_u:
388 s << asInt << "u";
389 break;
390 case decimal_U:
391 s << asInt << "U";
392 break;
393 case octal:
394 s << "0" << std::oct << asInt;
395 break;
396 case octal_u:
397 s << "0" << std::oct << asInt << "u";
398 break;
399 case octal_U:
400 s << "0" << std::oct << asInt << "U";
401 break;
402 case hex_x:
403 s << "0x" << std::hex << asInt;
404 break;
405 case hex_X:
406 s << "0X" << std::hex << asInt;
407 break;
408 case hex_u:
409 s << "0x" << std::hex << asInt << "u";
410 break;
411 case hex_u_X:
412 s << "0X" << std::hex << asInt << "u";
413 break;
414 case hex_U:
415 s << "0x" << std::hex << asInt << "U";
416 break;
417 case hex_U_X:
418 s << "0X" << std::hex << asInt << "U";
419 break;
420 case last:
421 default:
422 DE_ASSERT(0);
423 }
424
425 asString = s.str();
426 }
427
428 public:
429 String asString;
430 int asInt;
431 };
432
433 //*****************************************************************************
434 class LayoutBindingBaseCase : public TestCase, public IProgramContextSupplier
435 {
436 public:
437 LayoutBindingBaseCase(Context& context, const char* name, const char* description, StageType stage,
438 LayoutBindingParameters& samplerType, glu::GLSLVersion glslVersion);
439 virtual ~LayoutBindingBaseCase(void);
440
441 IterateResult iterate(void);
442
443 // overrideable subtests
444 virtual LayoutBindingTestResult binding_basic_default(void);
445 virtual LayoutBindingTestResult binding_basic_explicit(void);
446 virtual LayoutBindingTestResult binding_basic_multiple(void);
447 virtual LayoutBindingTestResult binding_basic_render(void);
448 virtual LayoutBindingTestResult binding_integer_constant(void);
449 virtual LayoutBindingTestResult binding_array_size(void);
450 virtual LayoutBindingTestResult binding_array_implicit(void);
451 virtual LayoutBindingTestResult binding_array_multiple(void);
452 virtual LayoutBindingTestResult binding_api_update(void);
453 virtual LayoutBindingTestResult binding_compilation_errors(void);
454 virtual LayoutBindingTestResult binding_link_errors(void);
455 virtual LayoutBindingTestResult binding_examples(void);
456 virtual LayoutBindingTestResult binding_mixed_order(void);
457
458 private:
459 // drawTest normal vs. compute
460 typedef LayoutBindingTestResult (LayoutBindingBaseCase::*LayoutBindingDrawTestPtr)(glw::GLint program, int binding);
461
462 LayoutBindingDrawTestPtr m_drawTest;
463
464 // pointer type for subtests
465 typedef LayoutBindingTestResult (LayoutBindingBaseCase::*LayoutBindingSubTestPtr)();
466
467 // test table entry
468 struct LayoutBindingSubTest
469 {
470 char const* name;
471 char const* description;
472 LayoutBindingSubTestPtr test;
473 };
474
475 // IProgramContextSupplier interface
476 protected:
getTestParameters()477 const LayoutBindingParameters& getTestParameters()
478 {
479 return m_testParams;
480 }
481
getRenderContext()482 const glu::RenderContext& getRenderContext()
483 {
484 return m_context.getRenderContext();
485 }
486
getStage()487 virtual eStageType getStage()
488 {
489 return m_stage.type;
490 }
491
getSource(eStageType stage)492 const String& getSource(eStageType stage)
493 {
494 return m_sources[stage];
495 }
496
getContext()497 Context& getContext()
498 {
499 return m_context;
500 }
501
gl()502 const glw::Functions& gl()
503 {
504 return m_context.getRenderContext().getFunctions();
505 }
506
needsPrecision() const507 bool needsPrecision() const
508 {
509 if (isContextTypeES(m_context.getRenderContext().getType()) || m_glslVersion == glu::GLSL_VERSION_450)
510 {
511 return (m_testParams.surface_type != UniformBlock) && (m_testParams.surface_type != ShaderStorageBuffer);
512 }
513 else
514 {
515 return (m_testParams.surface_type != UniformBlock) && (m_testParams.surface_type != ShaderStorageBuffer) &&
516 (m_testParams.surface_type != AtomicCounter) && (m_testParams.surface_type != Image);
517 }
518 }
519
520 protected:
makeSparseRange(int maxElement,int minElement=0) const521 std::vector<int> makeSparseRange(int maxElement, int minElement = 0) const
522 {
523 static float rangeT[] = { 0.0f, 0.1f, 0.5f, 0.6f, 0.9f, 1.0f };
524 std::vector<float> rangeTemplate = makeVector(rangeT);
525 float max = rangeTemplate.back();
526 float range = (float)((maxElement - 1) - minElement);
527
528 std::vector<int> result;
529 for (std::vector<float>::iterator it = rangeTemplate.begin(); it != rangeTemplate.end(); it++)
530 {
531 float e = *it;
532 e = (e * range) / max;
533 result.insert(result.end(), minElement + (int)e);
534 }
535 return result;
536 }
537
getGLSLVersion()538 glu::GLSLVersion getGLSLVersion()
539 {
540 return m_glslVersion;
541 }
542
isStage(eStageType stage)543 bool isStage(eStageType stage)
544 {
545 return (stage == m_stage.type);
546 }
547
setTemplateParam(eStageType stage,const char * param,const String & value)548 void setTemplateParam(eStageType stage, const char* param, const String& value)
549 {
550 m_templateParams[stage][param] = value.c_str();
551 }
552
setTemplateParam(const char * param,const String & value)553 void setTemplateParam(const char* param, const String& value)
554 {
555 setTemplateParam(m_stage.type, param, value);
556 }
557
updateTemplate(eStageType stage)558 void updateTemplate(eStageType stage)
559 {
560 m_sources[stage] = tcu::StringTemplate(m_templates[stage]).specialize(m_templateParams[stage]);
561 }
562
updateTemplate()563 void updateTemplate()
564 {
565 updateTemplate(m_stage.type);
566 }
567
568 template <class T0, class T1>
generateLog(const String & msg,T0 result,T1 expected)569 String generateLog(const String& msg, T0 result, T1 expected)
570 {
571 StringStream s;
572 s << msg << " expected: " << expected << " actual: " << result << "\n";
573 s << getSource(VertexShader) << "\n";
574 s << getSource(FragmentShader) << "\n";
575 return s.str();
576 }
577
578 private:
579 std::vector<LayoutBindingSubTest> m_tests;
580
init(void)581 void init(void)
582 {
583 m_drawTest =
584 (getStage() == ComputeShader) ? &LayoutBindingBaseCase::drawTestCompute : &LayoutBindingBaseCase::drawTest;
585
586 #define MAKE_TEST_ENTRY(__subtest_name__) { #__subtest_name__, "", &LayoutBindingBaseCase::__subtest_name__ }
587 LayoutBindingSubTest tests[] = {
588 MAKE_TEST_ENTRY(binding_basic_default), MAKE_TEST_ENTRY(binding_basic_explicit),
589 MAKE_TEST_ENTRY(binding_basic_multiple), MAKE_TEST_ENTRY(binding_basic_render),
590 MAKE_TEST_ENTRY(binding_integer_constant),
591 MAKE_TEST_ENTRY(binding_array_size), MAKE_TEST_ENTRY(binding_array_implicit),
592 MAKE_TEST_ENTRY(binding_array_multiple), MAKE_TEST_ENTRY(binding_api_update),
593 MAKE_TEST_ENTRY(binding_compilation_errors), MAKE_TEST_ENTRY(binding_link_errors),
594 MAKE_TEST_ENTRY(binding_examples), MAKE_TEST_ENTRY(binding_mixed_order)
595 };
596 m_tests = makeVector(tests);
597
598 m_uniformDeclTemplate = "${LAYOUT}${KEYWORD}${UNIFORM_TYPE}${UNIFORM_BLOCK_NAME}${UNIFORM_BLOCK}${UNIFORM_"
599 "INSTANCE_NAME}${UNIFORM_ARRAY};\n";
600
601 m_expectedColor = tcu::Vec4(0.0, 1.0f, 0.0f, 1.0f);
602
603 switch (getTestParameters().texture_type)
604 {
605 case TwoD:
606 {
607 // 2D
608 glu::ImmutableTexture2D* texture2D =
609 new glu::ImmutableTexture2D(getContext().getRenderContext(), GL_RGBA8, 2, 2);
610
611 texture2D->getRefTexture().allocLevel(0);
612 tcu::clear(texture2D->getRefTexture().getLevel(0), m_expectedColor);
613 texture2D->upload();
614
615 if (m_textures2D.find(0) != m_textures2D.end())
616 {
617 delete m_textures2D[0];
618 }
619
620 m_textures2D[0] = texture2D;
621 }
622 break;
623 case TwoDArray:
624 {
625 // 2DArray
626 glu::Texture2DArray* texture2DArray =
627 new glu::Texture2DArray(getContext().getRenderContext(), GL_RGBA8, 2, 2, 1);
628
629 texture2DArray->getRefTexture().allocLevel(0);
630 tcu::clear(texture2DArray->getRefTexture().getLevel(0), m_expectedColor);
631 texture2DArray->upload();
632
633 if (m_textures2DArray.find(0) != m_textures2DArray.end())
634 {
635 delete m_textures2DArray[0];
636 }
637
638 m_textures2DArray[0] = texture2DArray;
639 }
640 break;
641 // 3D
642 case ThreeD:
643 {
644 glu::Texture3D* texture3D = new glu::Texture3D(getContext().getRenderContext(), GL_RGBA8, 2, 2, 1);
645
646 texture3D->getRefTexture().allocLevel(0);
647 tcu::clear(texture3D->getRefTexture().getLevel(0), m_expectedColor);
648 texture3D->upload();
649
650 if (m_textures3D.find(0) != m_textures3D.end())
651 {
652 delete m_textures3D[0];
653 }
654
655 m_textures3D[0] = texture3D;
656 }
657 break;
658 case None:
659 // test case where no texture allocation is needed
660 break;
661 default:
662 DE_ASSERT(0);
663 break;
664 }
665 }
666
initDefaultVSContext()667 String initDefaultVSContext()
668 {
669 m_templates[VertexShader] = "${VERSION}"
670 "layout(location=0) in vec2 inPosition;\n"
671 "${UNIFORM_DECL}\n"
672 "flat out ${OUT_VAR_TYPE} fragColor;\n"
673 "${OPTIONAL_FUNCTION_BLOCK}\n"
674 "void main(void)\n"
675 "{\n"
676 " ${OUT_ASSIGNMENT} ${UNIFORM_ACCESS}\n"
677 " gl_Position = vec4(inPosition, 0.0, 1.0);\n"
678 "}\n";
679
680 StringMap& args = m_templateParams[VertexShader];
681 // some samplers and all images don't have default precision qualifier (sampler3D)
682 // so append a precision default in all sampler and image cases.
683 StringStream s;
684 s << glu::getGLSLVersionDeclaration(m_glslVersion) << "\n";
685 s << "precision highp float;\n";
686 if (needsPrecision())
687 {
688 s << "precision highp " << getTestParameters().uniform_type << ";\n";
689 }
690
691 args["VERSION"] = s.str();
692 args["UNIFORM_DECL"] = "";
693 args["OPTIONAL_FUNCTION_BLOCK"] = "";
694 args["UNIFORM_ACCESS"] = "";
695 args["OUT_ASSIGNMENT"] = "fragColor =";
696 args["OUT_VAR_TYPE"] = getTestParameters().vector_type;
697 args["OUT_VAR"] = "fragColor";
698 if (m_stage.type != VertexShader)
699 {
700 args["OUT_ASSIGNMENT"] = "";
701 }
702 return tcu::StringTemplate(m_templates[VertexShader]).specialize(args);
703 }
704
initDefaultFSContext()705 String initDefaultFSContext()
706 {
707 // build fragment shader
708 m_templates[FragmentShader] = "${VERSION}"
709 "layout(location=0) out ${OUT_VAR_TYPE} ${OUT_VAR};\n"
710 "flat in ${OUT_VAR_TYPE} fragColor;\n"
711 "${UNIFORM_DECL}\n"
712 "${OPTIONAL_FUNCTION_BLOCK}\n"
713 "void main(void)\n"
714 "{\n"
715 " ${OUT_ASSIGNMENT} ${UNIFORM_ACCESS}\n"
716 "}\n";
717
718 StringMap& args = m_templateParams[FragmentShader];
719 // samplers and images don't have default precision qualifier
720 StringStream s;
721 s << glu::getGLSLVersionDeclaration(m_glslVersion) << "\n";
722 s << "precision highp float;\n";
723 if (needsPrecision())
724 {
725 s << "precision highp " << getTestParameters().uniform_type << ";\n";
726 }
727 args["VERSION"] = s.str();
728 args["OUT_VAR_TYPE"] = getTestParameters().vector_type;
729 args["UNIFORM_ACCESS"] = "vec4(0.0,0.0,0.0,0.0);";
730 args["UNIFORM_DECL"] = "";
731 args["OPTIONAL_FUNCTION_BLOCK"] = "";
732 args["OUT_ASSIGNMENT"] = "outColor =";
733 args["OUT_VAR"] = "outColor";
734 // must have a linkage between stage and fragment shader
735 // that the compiler can't optimize away
736 if (FragmentShader != m_stage.type)
737 {
738 args["UNIFORM_ACCESS"] = "fragColor;";
739 }
740 return tcu::StringTemplate(m_templates[FragmentShader]).specialize(args);
741 }
742
initDefaultCSContext()743 String initDefaultCSContext()
744 {
745 // build compute shader
746 m_templates[ComputeShader] = "${VERSION}"
747 "${UNIFORM_DECL}\n"
748 "${OPTIONAL_FUNCTION_BLOCK}\n"
749 "void main(void)\n"
750 "{\n"
751 " ${OUT_VAR_TYPE} tmp = ${UNIFORM_ACCESS}\n"
752 " ${OUT_ASSIGNMENT} tmp ${OUT_END}\n"
753 "}\n";
754
755 StringMap& args = m_templateParams[ComputeShader];
756 // images don't have default precision qualifier
757 StringStream s;
758 s << glu::getGLSLVersionDeclaration(m_glslVersion) << "\n";
759 s << "layout (local_size_x = 1) in;\n"
760 "precision highp float;\n";
761 if (needsPrecision())
762 {
763 s << "precision highp " << getTestParameters().uniform_type << ";\n";
764 }
765
766 // bindings are per uniform type...
767 if (getTestParameters().surface_type == Image)
768 {
769 s << "layout(binding=0, std430) buffer outData {\n"
770 " "
771 << getTestParameters().vector_type << " outColor;\n"
772 "};\n";
773 args["OUT_ASSIGNMENT"] = "outColor =";
774 args["OUT_END"] = ";";
775 }
776 else
777 {
778 s << "layout(binding=0, rgba8) uniform highp writeonly image2D outImage;\n";
779 args["OUT_ASSIGNMENT"] = "imageStore(outImage, ivec2(0), ";
780 args["OUT_END"] = ");";
781 }
782 args["VERSION"] = s.str();
783 args["OUT_VAR_TYPE"] = getTestParameters().vector_type;
784 args["UNIFORM_ACCESS"] = "vec4(0.0,0.0,0.0,0.0);";
785 args["UNIFORM_DECL"] = "";
786 args["OPTIONAL_FUNCTION_BLOCK"] = "";
787
788 return tcu::StringTemplate(m_templates[ComputeShader]).specialize(args);
789 }
790
791 protected:
buildUniformDecl(const String & keyword,const String & layout,const String & uniform_type,const String & uniform_block_name,const String & uniform_block,const String & uniform_instance,const String & uniform_array) const792 String buildUniformDecl(const String& keyword, const String& layout, const String& uniform_type,
793 const String& uniform_block_name, const String& uniform_block,
794 const String& uniform_instance, const String& uniform_array) const
795 {
796 StringMap args;
797 setArg(args["LAYOUT"], layout);
798 setArg(args["KEYWORD"], keyword);
799 if (uniform_block_name.empty())
800 setArg(args["UNIFORM_TYPE"], uniform_type);
801 else
802 args["UNIFORM_TYPE"] = "";
803 if (!uniform_instance.empty() && !uniform_block_name.empty())
804 setArg(args["UNIFORM_BLOCK_NAME"], uniform_block_name + "_block");
805 else
806 setArg(args["UNIFORM_BLOCK_NAME"], uniform_block_name);
807 setArg(args["UNIFORM_BLOCK"], uniform_block);
808 if ((uniform_block_name.empty() && uniform_block.empty()) || !uniform_array.empty())
809 args["UNIFORM_INSTANCE_NAME"] = uniform_instance;
810 else
811 args["UNIFORM_INSTANCE_NAME"] = "";
812 args["UNIFORM_ARRAY"] = uniform_array;
813 return tcu::StringTemplate(m_uniformDeclTemplate).specialize(args);
814 }
815
getDefaultUniformName(int idx=0)816 virtual String getDefaultUniformName(int idx = 0)
817 {
818 StringStream s;
819 s << "uniform" << idx;
820 return s.str();
821 }
822
buildUniformName(String & var)823 virtual String buildUniformName(String& var)
824 {
825 std::ostringstream s;
826 s << var;
827 return s.str();
828 }
829
buildLayout(const String & binding)830 virtual String buildLayout(const String& binding)
831 {
832 std::ostringstream s;
833 if (!binding.empty())
834 s << "layout(binding=" << binding << ") ";
835 return s.str();
836 }
837
buildLayout(int binding)838 virtual String buildLayout(int binding)
839 {
840 std::ostringstream bindingStr;
841 bindingStr << binding;
842 return buildLayout(bindingStr.str());
843 }
844
buildAccess(const String & var)845 virtual String buildAccess(const String& var)
846 {
847 std::ostringstream s;
848 s << getTestParameters().access_function << "(" << var << "," << getTestParameters().coord_vector_type << "(0)"
849 << ")";
850 return s.str();
851 }
852
buildBlockName(const String &)853 virtual String buildBlockName(const String& /*name*/)
854 {
855 return String();
856 }
857
buildBlock(const String &,const String &=String ("float"))858 virtual String buildBlock(const String& /*name*/, const String& /*type*/ = String("float"))
859 {
860 return String();
861 }
862
buildArray(int idx)863 virtual String buildArray(int idx)
864 {
865 StringStream s;
866 s << "[" << idx << "]";
867 return s.str();
868 }
869
buildArrayAccess(int uniform,int idx)870 virtual String buildArrayAccess(int uniform, int idx)
871 {
872 StringStream s;
873 s << getDefaultUniformName(uniform) << buildArray(idx);
874 if (!buildBlockName(getDefaultUniformName()).empty())
875 {
876 s << "." << getDefaultUniformName(uniform);
877 }
878 return s.str();
879 }
880
881 // return max. binding point allowed
maxBindings()882 virtual int maxBindings()
883 {
884 int units = 0;
885
886 if (getTestParameters().surface_type == Image)
887 {
888 gl().getIntegerv(GL_MAX_IMAGE_UNITS, &units);
889 }
890 else
891 {
892 gl().getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &units);
893 }
894
895 return units;
896 }
897
898 // return max. array size allowed
maxArraySize()899 virtual int maxArraySize()
900 {
901 int units = 0;
902
903 if (getTestParameters().surface_type == Image)
904 {
905 switch (m_stage.type)
906 {
907 case VertexShader:
908 gl().getIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &units);
909 break;
910 case FragmentShader:
911 gl().getIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &units);
912 break;
913 default:
914 DE_ASSERT(0);
915 break;
916 }
917 }
918 else
919 {
920 switch (m_stage.type)
921 {
922 case VertexShader:
923 gl().getIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &units);
924 break;
925 case FragmentShader:
926 gl().getIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &units);
927 break;
928 default:
929 DE_ASSERT(0);
930 break;
931 }
932 }
933
934 return units;
935 }
936
isSupported()937 virtual bool isSupported()
938 {
939 return (maxArraySize() > 0);
940 }
941
bind(int binding)942 virtual void bind(int binding)
943 {
944 glw::GLint texTarget = 0;
945 glw::GLint texName = 0;
946
947 switch (getTestParameters().texture_type)
948 {
949 case TwoD:
950 texTarget = GL_TEXTURE_2D;
951 texName = m_textures2D[0]->getGLTexture();
952 break;
953 case TwoDArray:
954 texTarget = GL_TEXTURE_2D_ARRAY;
955 texName = m_textures2DArray[0]->getGLTexture();
956 break;
957 case ThreeD:
958 texTarget = GL_TEXTURE_3D;
959 texName = m_textures3D[0]->getGLTexture();
960 break;
961 default:
962 DE_ASSERT(0);
963 break;
964 }
965
966 switch (getTestParameters().surface_type)
967 {
968 case Texture:
969 gl().activeTexture(GL_TEXTURE0 + binding);
970 gl().bindTexture(texTarget, texName);
971 gl().texParameteri(texTarget, GL_TEXTURE_WRAP_S, glu::getGLWrapMode(tcu::Sampler::CLAMP_TO_EDGE));
972 gl().texParameteri(texTarget, GL_TEXTURE_WRAP_T, glu::getGLWrapMode(tcu::Sampler::CLAMP_TO_EDGE));
973 gl().texParameteri(texTarget, GL_TEXTURE_MIN_FILTER, glu::getGLFilterMode(tcu::Sampler::NEAREST));
974 gl().texParameteri(texTarget, GL_TEXTURE_MAG_FILTER, glu::getGLFilterMode(tcu::Sampler::NEAREST));
975 break;
976 case Image:
977 gl().bindImageTexture(binding, texName, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
978 break;
979 default:
980 DE_ASSERT(0);
981 break;
982 }
983 }
984
unbind(int binding)985 virtual void unbind(int binding)
986 {
987 glw::GLint texTarget = 0;
988
989 switch (getTestParameters().texture_type)
990 {
991 case TwoD:
992 texTarget = GL_TEXTURE_2D;
993 break;
994 case TwoDArray:
995 texTarget = GL_TEXTURE_2D_ARRAY;
996 break;
997 case ThreeD:
998 texTarget = GL_TEXTURE_3D;
999 break;
1000 default:
1001 DE_ASSERT(0);
1002 break;
1003 }
1004
1005 switch (getTestParameters().surface_type)
1006 {
1007 case Texture:
1008 gl().activeTexture(GL_TEXTURE0 + binding);
1009 gl().bindTexture(texTarget, 0);
1010 break;
1011 case Image:
1012 gl().bindImageTexture(binding, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32F);
1013 break;
1014 default:
1015 DE_ASSERT(0);
1016 break;
1017 }
1018 }
1019
1020 virtual LayoutBindingTestResult drawTest(glw::GLint program, int binding);
1021 virtual LayoutBindingTestResult drawTestCompute(glw::GLint program, int binding);
1022
1023 // allocate resources needed for all subtests, i.e. textures
setupTest()1024 virtual void setupTest()
1025 {
1026 }
1027
1028 // cleanup resources needed for all subtests
teardownTest()1029 virtual void teardownTest()
1030 {
1031 for (Texture2DMap::iterator it = m_textures2D.begin(); it != m_textures2D.end(); it++)
1032 {
1033 delete it->second;
1034 }
1035 m_textures2D.clear();
1036
1037 for (Texture2DArrayMap::iterator it = m_textures2DArray.begin(); it != m_textures2DArray.end(); it++)
1038 {
1039 delete it->second;
1040 }
1041 m_textures2DArray.clear();
1042
1043 for (Texture3DMap::iterator it = m_textures3D.begin(); it != m_textures3D.end(); it++)
1044 {
1045 delete it->second;
1046 }
1047 m_textures3D.clear();
1048 }
1049
1050 private:
1051 // appends a space to the argument (make shader source pretty)
setArg(String & arg,const String & value) const1052 void setArg(String& arg, const String& value) const
1053 {
1054 if (!value.empty())
1055 arg = value + String(" ");
1056 else
1057 arg = String();
1058 }
1059
1060 private:
1061 LayoutBindingParameters m_testParams;
1062 StageType m_stage;
1063
1064 std::map<eStageType, String> m_sources;
1065 std::map<eStageType, StringMap> m_templateParams;
1066 std::map<eStageType, const char*> m_templates;
1067
1068 Texture2DMap m_textures2D;
1069 Texture2DArrayMap m_textures2DArray;
1070 Texture3DMap m_textures3D;
1071 tcu::Vec4 m_expectedColor;
1072
1073 const char* m_uniformDeclTemplate;
1074
1075 glu::GLSLVersion m_glslVersion;
1076 };
1077
LayoutBindingBaseCase(Context & context,const char * name,const char * description,StageType stage,LayoutBindingParameters & samplerType,glu::GLSLVersion glslVersion)1078 LayoutBindingBaseCase::LayoutBindingBaseCase(Context& context, const char* name, const char* description,
1079 StageType stage, LayoutBindingParameters& samplerType,
1080 glu::GLSLVersion glslVersion)
1081 : TestCase(context, name, description)
1082 , m_drawTest(DE_NULL)
1083 , m_testParams(samplerType)
1084 , m_stage(stage)
1085 , m_uniformDeclTemplate(DE_NULL)
1086 , m_glslVersion(glslVersion)
1087 {
1088 }
1089
~LayoutBindingBaseCase(void)1090 LayoutBindingBaseCase::~LayoutBindingBaseCase(void)
1091 {
1092 teardownTest();
1093 }
1094
iterate(void)1095 LayoutBindingBaseCase::IterateResult LayoutBindingBaseCase::iterate(void)
1096 {
1097 tcu::TestLog& log = m_context.getTestContext().getLog();
1098 bool passed = true;
1099
1100 if (!isSupported())
1101 {
1102 log << tcu::TestLog::Section("NotSupported", "");
1103 log << tcu::TestLog::Message << "This test was not run as minimum requirements were not met."
1104 << tcu::TestLog::EndMessage;
1105 log << tcu::TestLog::EndSection;
1106 getContext().getTestContext().setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "NotSupported");
1107 return STOP;
1108 }
1109
1110 // init test case (create shader templates and textures)
1111 init();
1112
1113 // allocate resources for all subtests
1114 setupTest();
1115
1116 for (std::vector<LayoutBindingSubTest>::iterator it = m_tests.begin(); it != m_tests.end(); it++)
1117 {
1118 // need to reset templates and their args to a clean state before every
1119 // test to avoid bleeding.
1120 m_sources[VertexShader] = initDefaultVSContext();
1121 m_sources[FragmentShader] = initDefaultFSContext();
1122 m_sources[ComputeShader] = initDefaultCSContext();
1123
1124 LayoutBindingTestResult result = ((*this).*((*it).test))();
1125 if (!result.testPassed())
1126 {
1127 log << tcu::TestLog::Section((*it).name, (*it).description);
1128 log << tcu::TestLog::Message << result.getReason() << tcu::TestLog::EndMessage;
1129 log << tcu::TestLog::EndSection;
1130 }
1131 if (!result.runForThisContext())
1132 {
1133 log << tcu::TestLog::Section((*it).name, (*it).description);
1134 log << tcu::TestLog::Message << "This test was not run for this context as it does not apply."
1135 << tcu::TestLog::EndMessage;
1136 log << tcu::TestLog::EndSection;
1137 }
1138 passed &= result.testPassed();
1139 }
1140
1141 // cleanup resources
1142 teardownTest();
1143
1144 /*=========================================================================
1145 TEST results
1146 =========================================================================*/
1147
1148 getContext().getTestContext().setTestResult(passed ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
1149 passed ? "Pass" : "Fail");
1150
1151 return STOP;
1152 }
1153
1154 /*=========================================================================
1155 // bind resource to specified binding point and program and
1156 // dispatch a computation, read back image at (0,0)
1157 =========================================================================*/
drawTestCompute(glw::GLint program,int binding)1158 LayoutBindingTestResult LayoutBindingBaseCase::drawTestCompute(glw::GLint program, int binding)
1159 {
1160 const glw::Functions& l_gl = getContext().getRenderContext().getFunctions();
1161 bool passed = true;
1162
1163 DE_TEST_ASSERT(getStage() == ComputeShader);
1164
1165 l_gl.useProgram(program);
1166
1167 deUint32 fb_or_ssb;
1168
1169 if (getTestParameters().surface_type == Image)
1170 {
1171 bind(binding);
1172
1173 glw::GLfloat buffer[4] = { 0.1f, 0.2f, 0.3f, 0.4f };
1174 l_gl.genBuffers(1, &fb_or_ssb);
1175 l_gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, fb_or_ssb);
1176
1177 l_gl.bufferData(GL_SHADER_STORAGE_BUFFER, 4 * sizeof(glw::GLfloat), buffer, GL_DYNAMIC_COPY);
1178
1179 l_gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, fb_or_ssb);
1180
1181 l_gl.dispatchCompute(1, 1, 1);
1182 l_gl.memoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
1183
1184 tcu::Vec4 pixel =
1185 *(tcu::Vec4*)l_gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * sizeof(glw::GLfloat), GL_MAP_READ_BIT);
1186 l_gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
1187
1188 l_gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
1189 l_gl.deleteBuffers(1, &fb_or_ssb);
1190
1191 unbind(binding);
1192
1193 tcu::Vec4 expected(0.0f, 1.0f, 0.0f, 1.0f);
1194 passed = (pixel == expected);
1195 if (!passed)
1196 {
1197 return LayoutBindingTestResult(passed, generateLog(String("drawTestCompute failed"), expected, pixel));
1198 }
1199 }
1200 else
1201 {
1202 deUint32 something = 0x01020304, tex;
1203
1204 l_gl.genTextures(1, &tex);
1205 l_gl.bindTexture(GL_TEXTURE_2D, tex);
1206 l_gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1207 l_gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
1208 l_gl.texSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &something);
1209
1210 bind(binding);
1211
1212 l_gl.bindImageTexture(0, tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
1213
1214 l_gl.dispatchCompute(1, 1, 1);
1215 l_gl.memoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1216
1217 l_gl.bindImageTexture(0, 0, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
1218
1219 l_gl.genFramebuffers(1, &fb_or_ssb);
1220 l_gl.bindFramebuffer(GL_FRAMEBUFFER, fb_or_ssb);
1221 l_gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1222
1223 l_gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &something);
1224
1225 l_gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
1226 l_gl.deleteFramebuffers(1, &fb_or_ssb);
1227 l_gl.deleteTextures(1, &tex);
1228
1229 unbind(binding);
1230
1231 const deUint32 expected = 0xff00ff00;
1232 passed = (expected == something);
1233 if (!passed)
1234 {
1235 return LayoutBindingTestResult(
1236 passed, generateLog(String("drawTestCompute failed"), tcu::RGBA(expected), tcu::RGBA(something)));
1237 }
1238 }
1239
1240 return passed;
1241 }
1242
1243 /*=========================================================================
1244 // bind resource to specified binding point and program and
1245 // return result of comparison of rendered pixel at (0,0) with expected
1246 =========================================================================*/
drawTest(glw::GLint program,int binding)1247 LayoutBindingTestResult LayoutBindingBaseCase::drawTest(glw::GLint program, int binding)
1248 {
1249 const glw::Functions& GL = getContext().getRenderContext().getFunctions();
1250 const tcu::RenderTarget& renderTarget = getContext().getRenderContext().getRenderTarget();
1251 glw::GLuint viewportW = renderTarget.getWidth();
1252 glw::GLuint viewportH = renderTarget.getHeight();
1253 tcu::Surface renderedFrame(viewportW, viewportH);
1254 bool passed = true;
1255
1256 DE_TEST_ASSERT(getStage() != ComputeShader);
1257
1258 GL.viewport(0, 0, viewportW, viewportH);
1259 GL.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
1260 GL.clear(GL_COLOR_BUFFER_BIT);
1261
1262 static const float position[] = {
1263 -1.0f, -1.0f, -1.0f, +1.0f, +1.0f, -1.0f, +1.0f, +1.0f,
1264 };
1265 static const deUint16 quadIndices[] = { 0, 1, 2, 2, 1, 3 };
1266
1267 GL.useProgram(program);
1268
1269 bind(binding);
1270
1271 static const glu::VertexArrayBinding vertexArrays[] = {
1272 glu::va::Float("inPosition", 2, 4, 0, &position[0]),
1273 };
1274 glu::draw(getContext().getRenderContext(), program, DE_LENGTH_OF_ARRAY(vertexArrays), &vertexArrays[0],
1275 glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(quadIndices), &quadIndices[0]));
1276
1277 glu::readPixels(getContext().getRenderContext(), 0, 0, renderedFrame.getAccess());
1278
1279 tcu::RGBA pixel = renderedFrame.getPixel(0, 0);
1280
1281 passed = (pixel == tcu::RGBA(m_expectedColor));
1282
1283 unbind(binding);
1284
1285 if (!passed)
1286 {
1287 return LayoutBindingTestResult(passed,
1288 generateLog(String("drawTest failed"), m_expectedColor, pixel.getPacked()));
1289 }
1290
1291 return true;
1292 }
1293
1294 //== verify that binding point is default w/o layout binding
binding_basic_default()1295 LayoutBindingTestResult LayoutBindingBaseCase::binding_basic_default()
1296 {
1297 bool passed = true;
1298
1299 StringStream s;
1300 s << buildAccess(getDefaultUniformName()) << ";\n";
1301 setTemplateParam("UNIFORM_ACCESS", s.str());
1302
1303 String decl = buildUniformDecl(String(getTestParameters().keyword), buildLayout(String()),
1304 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
1305 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
1306 setTemplateParam("UNIFORM_DECL", decl);
1307 updateTemplate();
1308
1309 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
1310 passed &= program->compiledAndLinked();
1311 if (!passed)
1312 {
1313 return LayoutBindingTestResult(passed, program->getErrorLog());
1314 }
1315
1316 StringVector list;
1317 const String& u = buildBlockName(getDefaultUniformName());
1318 if (!u.empty())
1319 list.push_back(u + "_block");
1320 else
1321 list.push_back(getDefaultUniformName());
1322
1323 StringIntMap bindingPoints = program->getBindingPoints(list);
1324
1325 passed &= bindingPoints.size() == list.size() && (bindingPoints[u] == 0);
1326 if (!passed)
1327 {
1328 return LayoutBindingTestResult(passed,
1329 generateLog(String("binding point did not match default"), bindingPoints[u], 0));
1330 }
1331
1332 return true;
1333 }
1334
1335 //== verify that binding point has specified value
binding_basic_explicit()1336 LayoutBindingTestResult LayoutBindingBaseCase::binding_basic_explicit()
1337 {
1338 bool passed = true;
1339
1340 {
1341 StringStream s;
1342 s << buildAccess(getDefaultUniformName()) << ";\n";
1343 setTemplateParam("UNIFORM_ACCESS", s.str());
1344 }
1345
1346 std::vector<int> bindings = makeSparseRange(maxBindings());
1347 for (std::vector<int>::iterator it = bindings.begin(); it < bindings.end(); it++)
1348 {
1349 int binding = *it;
1350 String decl =
1351 buildUniformDecl(String(getTestParameters().keyword), buildLayout(binding),
1352 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
1353 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
1354 setTemplateParam("UNIFORM_DECL", decl);
1355 updateTemplate();
1356
1357 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
1358 passed &= program->compiledAndLinked();
1359 if (!passed)
1360 {
1361 return LayoutBindingTestResult(passed, program->getErrorLog());
1362 }
1363
1364 StringVector list;
1365 const String& s = buildBlockName(getDefaultUniformName());
1366 if (!s.empty())
1367 list.push_back(s + "_block");
1368 else
1369 list.push_back(getDefaultUniformName());
1370
1371 StringIntMap bindingPoints = program->getBindingPoints(list);
1372 passed &= bindingPoints.size() == list.size() && (binding == bindingPoints[list[0]]);
1373 if (!passed)
1374 {
1375 return LayoutBindingTestResult(
1376 passed, generateLog(String("binding point did not match default"), bindingPoints[list[0]], binding));
1377 }
1378 }
1379 return true;
1380 }
1381
1382 //== verify that binding works with multiple samplers (same binding points)
binding_basic_multiple()1383 LayoutBindingTestResult LayoutBindingBaseCase::binding_basic_multiple()
1384 {
1385 bool passed = true;
1386
1387 glw::GLint baseBindingPoint = maxBindings() - 1;
1388
1389 String decl0 = buildUniformDecl(String(getTestParameters().keyword), buildLayout(baseBindingPoint),
1390 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
1391 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
1392 String decl1 = buildUniformDecl(String(getTestParameters().keyword), buildLayout(baseBindingPoint),
1393 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName(1)),
1394 buildBlock(getDefaultUniformName(1)), getDefaultUniformName(1), String());
1395 setTemplateParam("UNIFORM_DECL", decl0 + decl1);
1396
1397 StringStream s;
1398 s << buildAccess(getDefaultUniformName()) << " + " << buildAccess(getDefaultUniformName(1)) << ";\n";
1399 setTemplateParam("UNIFORM_ACCESS", s.str());
1400 updateTemplate();
1401
1402 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
1403 passed &= program->compiledAndLinked();
1404 if (!passed)
1405 {
1406 return LayoutBindingTestResult(passed, program->getErrorLog());
1407 }
1408
1409 StringVector list;
1410 String u = buildBlockName(getDefaultUniformName());
1411 if (!u.empty())
1412 list.push_back(u + "_block");
1413 else
1414 list.push_back(getDefaultUniformName());
1415
1416 u = buildBlockName(getDefaultUniformName(1));
1417 if (!u.empty())
1418 list.push_back(u + "_block");
1419 else
1420 list.push_back(getDefaultUniformName(1));
1421
1422 StringIntMap bindingPoints = program->getBindingPoints(list);
1423 passed &= (baseBindingPoint == bindingPoints[list[0]]) && (baseBindingPoint == bindingPoints[list[1]]);
1424 if (!passed)
1425 {
1426 String err;
1427 err = generateLog(String("binding point did not match default"), bindingPoints[list[0]], baseBindingPoint);
1428 err += generateLog(String("binding point did not match default"), bindingPoints[list[1]], baseBindingPoint);
1429 return LayoutBindingTestResult(passed, err);
1430 }
1431
1432 return true;
1433 }
1434
1435 //== verify that binding point has specified value
binding_basic_render()1436 LayoutBindingTestResult LayoutBindingBaseCase::binding_basic_render()
1437 {
1438 bool passed = true;
1439
1440 StringStream s;
1441 s << buildAccess(getDefaultUniformName()) << ";\n";
1442 setTemplateParam("UNIFORM_ACCESS", s.str());
1443
1444 std::vector<int> bindings = makeSparseRange(maxBindings());
1445 for (std::vector<int>::iterator it = bindings.begin(); it < bindings.end(); it++)
1446 {
1447 int binding = *it;
1448 String decl =
1449 buildUniformDecl(String(getTestParameters().keyword), buildLayout(binding),
1450 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
1451 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
1452 setTemplateParam("UNIFORM_DECL", decl);
1453 updateTemplate();
1454
1455 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
1456 passed &= program->compiledAndLinked();
1457 if (!passed)
1458 {
1459 return LayoutBindingTestResult(passed, program->getErrorLog());
1460 }
1461
1462 LayoutBindingTestResult drawTestResult = ((*this).*(m_drawTest))(program->getProgram(), binding);
1463 if (!drawTestResult.testPassed())
1464 {
1465 return LayoutBindingTestResult(drawTestResult.testPassed(), drawTestResult.getReason());
1466 }
1467 }
1468 return true;
1469 }
1470
binding_integer_constant()1471 LayoutBindingTestResult LayoutBindingBaseCase::binding_integer_constant()
1472 {
1473 bool passed = true;
1474 std::vector<int> integers = makeSparseRange(maxBindings(), 0);
1475
1476 std::vector<IntegerConstant> integerConstants;
1477 for (int idx = 0; idx < IntegerConstant::last; idx++)
1478 {
1479 for (IntVector::iterator it = integers.begin(); it != integers.end(); it++)
1480 {
1481 integerConstants.push_back(IntegerConstant((IntegerConstant::Literals)idx, (*it)));
1482 }
1483 }
1484
1485 //== verify that binding point can be set with integer constant
1486 for (std::vector<IntegerConstant>::iterator it = integerConstants.begin(); it != integerConstants.end(); it++)
1487 {
1488 String& intConst = (*it).asString;
1489
1490 String decl =
1491 buildUniformDecl(String(getTestParameters().keyword), buildLayout(intConst),
1492 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
1493 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
1494 setTemplateParam("UNIFORM_DECL", decl);
1495
1496 StringStream s;
1497 s << buildAccess(getDefaultUniformName()) << ";\n";
1498 setTemplateParam("UNIFORM_ACCESS", s.str());
1499 updateTemplate();
1500
1501 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
1502 passed &= program->compiledAndLinked();
1503 if (!passed)
1504 {
1505 return LayoutBindingTestResult(passed, program->getErrorLog());
1506 }
1507
1508 StringVector list;
1509 const String& u = buildBlockName(getDefaultUniformName());
1510 if (!u.empty())
1511 list.push_back(u + "_block");
1512 else
1513 list.push_back(getDefaultUniformName());
1514
1515 StringIntMap bindingPoints = program->getBindingPoints(list);
1516 passed &= ((*it).asInt == bindingPoints[list[0]]);
1517 if (!passed)
1518 {
1519 return LayoutBindingTestResult(passed, generateLog(String("binding point did not match default"),
1520 bindingPoints[list[0]], (*it).asInt));
1521 }
1522 }
1523
1524 //== verify that binding point can be set with integer constant resulting from a preprocessor substitution
1525 for (std::vector<IntegerConstant>::iterator it = integerConstants.begin(); it != integerConstants.end(); it++)
1526 {
1527 String& intConst = (*it).asString;
1528
1529 StringStream s;
1530 s << "#define INT_CONST " << intConst << std::endl;
1531
1532 String decl =
1533 buildUniformDecl(String(getTestParameters().keyword), buildLayout(String("INT_CONST")),
1534 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
1535 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
1536 setTemplateParam("UNIFORM_DECL", s.str() + decl);
1537
1538 s.reset();
1539 s << buildAccess(getDefaultUniformName()) << ";\n";
1540 setTemplateParam("UNIFORM_ACCESS", s.str());
1541 updateTemplate();
1542
1543 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
1544 passed &= program->compiledAndLinked();
1545 if (!passed)
1546 {
1547 return LayoutBindingTestResult(passed, program->getErrorLog());
1548 }
1549
1550 StringVector list;
1551 const String& u = buildBlockName(getDefaultUniformName());
1552 if (!u.empty())
1553 list.push_back(u + "_block");
1554 else
1555 list.push_back(getDefaultUniformName());
1556
1557 StringIntMap bindingPoints = program->getBindingPoints(list);
1558 passed &= ((*it).asInt == bindingPoints[list[0]]);
1559 if (!passed)
1560 {
1561 return LayoutBindingTestResult(passed, generateLog(String("binding point did not match default"),
1562 bindingPoints[list[0]], (*it).asInt));
1563 }
1564 }
1565
1566 return true;
1567 }
1568
1569 //== test different sized arrays
binding_array_size(void)1570 LayoutBindingTestResult LayoutBindingBaseCase::binding_array_size(void)
1571 {
1572 bool passed = true;
1573
1574 std::vector<int> arraySizes = makeSparseRange(maxArraySize(), 1);
1575 for (std::vector<int>::iterator it = arraySizes.begin(); it < arraySizes.end(); it++)
1576 {
1577 int arraySize = *it;
1578 String decl =
1579 buildUniformDecl(String(getTestParameters().keyword), buildLayout(maxBindings() - arraySize - 1),
1580 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
1581 buildBlock(getDefaultUniformName()), getDefaultUniformName(), buildArray(arraySize));
1582 setTemplateParam("UNIFORM_DECL", decl);
1583
1584 StringStream s;
1585 for (int idx = 0; idx < arraySize; idx++)
1586 {
1587 s << (idx ? " + " : "") << buildAccess(buildArrayAccess(0, idx));
1588 }
1589 s << ";\n";
1590 setTemplateParam("UNIFORM_ACCESS", s.str());
1591 updateTemplate();
1592
1593 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
1594 passed &= program->compiledAndLinked();
1595 if (!passed)
1596 {
1597 return LayoutBindingTestResult(passed, program->getErrorLog());
1598 }
1599
1600 StringVector list;
1601 for (int idx = 0; idx < arraySize; idx++)
1602 {
1603 std::ostringstream texUnitStr;
1604 texUnitStr << getDefaultUniformName();
1605 const String& u = buildBlockName(getDefaultUniformName());
1606 if (!u.empty())
1607 texUnitStr << "_block";
1608 texUnitStr << buildArray(idx);
1609 list.push_back(texUnitStr.str());
1610 }
1611
1612 StringIntMap bindingPoints = program->getBindingPoints(list);
1613 for (int idx = 0; idx < arraySize; idx++)
1614 {
1615 passed &= (((maxBindings() - arraySize - 1) + idx) == bindingPoints[list[idx]]);
1616 if (!passed)
1617 {
1618 return LayoutBindingTestResult(passed, generateLog(String("binding point did not match default"),
1619 bindingPoints[list[idx]],
1620 (maxBindings() - arraySize - 1) + idx));
1621 }
1622 }
1623 }
1624
1625 return LayoutBindingTestResult(passed, String());
1626 }
1627
1628 //== verify first element takes binding point specified in binding and
1629 //== subsequent entries take the next consecutive units
binding_array_implicit(void)1630 LayoutBindingTestResult LayoutBindingBaseCase::binding_array_implicit(void)
1631 {
1632 bool passed = true;
1633
1634 std::vector<int> bindings = makeSparseRange(maxBindings(), 0);
1635 for (std::vector<int>::iterator it = bindings.begin(); it < bindings.end(); it++)
1636 {
1637 int baseBindingPoint = *it;
1638 int arraySize = std::min(maxBindings() - baseBindingPoint, 4);
1639
1640 String decl =
1641 buildUniformDecl(String(getTestParameters().keyword), buildLayout(baseBindingPoint),
1642 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
1643 buildBlock(getDefaultUniformName()), getDefaultUniformName(), buildArray(arraySize));
1644 setTemplateParam("UNIFORM_DECL", decl);
1645
1646 StringStream s;
1647 for (int idx = 0; idx < arraySize; idx++)
1648 {
1649 s << (idx ? " + " : "") << buildAccess(buildArrayAccess(0, idx));
1650 }
1651 s << ";\n";
1652 setTemplateParam("UNIFORM_ACCESS", s.str());
1653 updateTemplate();
1654
1655 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
1656 passed &= program->compiledAndLinked();
1657 if (!passed)
1658 {
1659 return LayoutBindingTestResult(passed, program->getErrorLog());
1660 }
1661 StringVector list;
1662 for (int idx = 0; idx < arraySize; idx++)
1663 {
1664 std::ostringstream texUnitStr;
1665 texUnitStr << getDefaultUniformName();
1666 const String& u = buildBlockName(getDefaultUniformName());
1667 if (!u.empty())
1668 texUnitStr << "_block";
1669 texUnitStr << buildArray(idx);
1670 list.push_back(texUnitStr.str());
1671 }
1672
1673 StringIntMap bindingPoints = program->getBindingPoints(list);
1674 for (int idx = 0; idx < arraySize; idx++)
1675 {
1676 passed &= ((baseBindingPoint + idx) == bindingPoints[list[idx]]);
1677 if (!passed)
1678 {
1679 return LayoutBindingTestResult(passed, generateLog(String("binding point did not match default"),
1680 bindingPoints[list[idx]], (baseBindingPoint + idx)));
1681 }
1682 }
1683 }
1684 return LayoutBindingTestResult(passed, String());
1685 }
1686
1687 //== multiple arrays :verify first element takes binding point specified in binding and
1688 //== subsequent entries take the next consecutive units
binding_array_multiple(void)1689 LayoutBindingTestResult LayoutBindingBaseCase::binding_array_multiple(void)
1690 {
1691 bool passed = true;
1692
1693 // two arrays, limit max. binding to one
1694 std::vector<int> bindings = makeSparseRange(maxBindings() - 2, 0);
1695 for (std::vector<int>::iterator it = bindings.begin(); it < bindings.end(); it++)
1696 {
1697 int baseBindingPoint = *it;
1698
1699 // total distance from current binding point to end of binding range
1700 // split over two arrays, making sure that the array sizes don't
1701 // exceed max. array sizes per stage
1702 int arraySize = (maxBindings() - baseBindingPoint - 1) / 2;
1703 arraySize = std::min(arraySize, maxArraySize() / 2);
1704
1705 StringStream s;
1706 String decl =
1707 buildUniformDecl(String(getTestParameters().keyword), buildLayout(baseBindingPoint),
1708 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
1709 buildBlock(getDefaultUniformName()), getDefaultUniformName(), buildArray(arraySize));
1710 String another_decl =
1711 buildUniformDecl(String(getTestParameters().keyword), buildLayout(baseBindingPoint),
1712 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName(1)),
1713 buildBlock(getDefaultUniformName(1)), getDefaultUniformName(1), buildArray(arraySize));
1714 setTemplateParam("UNIFORM_DECL", decl + another_decl);
1715
1716 s.reset();
1717 for (int uniform = 0; uniform < 2; uniform++)
1718 {
1719 for (int idx = 0; idx < arraySize; idx++)
1720 {
1721 s << ((idx | uniform) ? " + " : "") << buildAccess(buildArrayAccess(uniform, idx));
1722 }
1723 }
1724 s << ";\n";
1725 setTemplateParam("UNIFORM_ACCESS", s.str());
1726 updateTemplate();
1727
1728 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
1729 passed &= program->compiledAndLinked();
1730 if (!passed)
1731 {
1732 return LayoutBindingTestResult(passed, program->getErrorLog());
1733 }
1734
1735 StringVector list;
1736 for (int uniform = 0; uniform < 2; uniform++)
1737 {
1738 list.clear();
1739 for (int idx = 0; idx < arraySize; idx++)
1740 {
1741 std::ostringstream texUnitStr;
1742 texUnitStr << getDefaultUniformName(uniform);
1743 const String& u = buildBlockName(getDefaultUniformName(uniform));
1744 if (!u.empty())
1745 texUnitStr << "_block";
1746 texUnitStr << buildArray(idx);
1747 list.push_back(texUnitStr.str());
1748 }
1749
1750 StringIntMap bindingPoints = program->getBindingPoints(list);
1751 for (int idx = 0; idx < arraySize; idx++)
1752 {
1753 passed &= ((baseBindingPoint + idx) == bindingPoints[list[idx]]);
1754 if (!passed)
1755 {
1756 return LayoutBindingTestResult(passed,
1757 generateLog(String("binding point did not match default"),
1758 bindingPoints[list[idx]], (baseBindingPoint + idx)));
1759 }
1760 }
1761 }
1762 }
1763 return LayoutBindingTestResult(passed, String());
1764 }
1765
1766 //== verify that explicit binding point can be changed via API
binding_api_update(void)1767 LayoutBindingTestResult LayoutBindingBaseCase::binding_api_update(void)
1768 {
1769 bool passed = true;
1770
1771 String decl = buildUniformDecl(String(getTestParameters().keyword), buildLayout(1),
1772 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
1773 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
1774 setTemplateParam("UNIFORM_DECL", decl);
1775
1776 StringStream s;
1777 s << buildAccess(getDefaultUniformName()) << ";\n";
1778 setTemplateParam("UNIFORM_ACCESS", s.str());
1779 updateTemplate();
1780
1781 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
1782 passed &= program->compiledAndLinked();
1783 if (!passed)
1784 {
1785 return LayoutBindingTestResult(passed, program->getErrorLog());
1786 }
1787
1788 StringVector list;
1789 const String& u = buildBlockName(getDefaultUniformName());
1790 if (!u.empty())
1791 list.push_back(u + "_block");
1792 else
1793 list.push_back(getDefaultUniformName());
1794
1795 StringIntMap bindingPoints = program->getBindingPoints(list);
1796
1797 gl().useProgram(program->getProgram());
1798 program->setBindingPoints(list, maxBindings() - 1);
1799 gl().useProgram(0);
1800
1801 bindingPoints = program->getBindingPoints(list);
1802
1803 passed &= bindingPoints[list[0]] == (maxBindings() - 1);
1804 if (!passed)
1805 {
1806 return LayoutBindingTestResult(passed, generateLog(String("binding point did not match default"),
1807 bindingPoints[list[0]], maxBindings() - 1));
1808 }
1809
1810 return LayoutBindingTestResult(passed, String());
1811 }
1812
binding_compilation_errors(void)1813 LayoutBindingTestResult LayoutBindingBaseCase::binding_compilation_errors(void)
1814 {
1815 bool passed = true;
1816 String decl;
1817
1818 // verify "uniform float var;" doesn't compile
1819 {
1820 StringStream s;
1821 s << getTestParameters().vector_type << "(0.0);";
1822
1823 setTemplateParam("UNIFORM_ACCESS", s.str());
1824 s.reset();
1825 s << "layout(binding=0) "
1826 << "uniform float tex0;";
1827 setTemplateParam("UNIFORM_DECL", s.str());
1828 updateTemplate();
1829
1830 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
1831 passed &= !program->compiledAndLinked();
1832 if (!passed)
1833 {
1834 return LayoutBindingTestResult(passed, program->getErrorLog(true));
1835 }
1836 }
1837
1838 // verify that non-constant integer expression in binding fails
1839 {
1840 decl = buildUniformDecl(String(getTestParameters().keyword), buildLayout(String("0.0")),
1841 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
1842 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
1843 setTemplateParam("UNIFORM_DECL", decl);
1844 updateTemplate();
1845
1846 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
1847 passed &= !program->compiledAndLinked();
1848 if (!passed)
1849 {
1850 return LayoutBindingTestResult(passed, program->getErrorLog(true));
1851 }
1852 }
1853
1854 {
1855 decl = buildUniformDecl(String(getTestParameters().keyword), buildLayout(String("-1")),
1856 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
1857 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
1858 setTemplateParam("UNIFORM_DECL", decl);
1859 updateTemplate();
1860
1861 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
1862 passed &= !program->compiledAndLinked();
1863 if (!passed)
1864 {
1865 return LayoutBindingTestResult(passed, program->getErrorLog(true));
1866 }
1867 }
1868 {
1869 decl = buildUniformDecl(String(getTestParameters().keyword), buildLayout(maxBindings()),
1870 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
1871 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
1872 setTemplateParam("UNIFORM_DECL", decl);
1873 updateTemplate();
1874
1875 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
1876 passed &= !program->compiledAndLinked();
1877 if (!passed)
1878 {
1879 return LayoutBindingTestResult(passed, program->getErrorLog(true));
1880 }
1881 }
1882 {
1883 decl = buildUniformDecl(String(getTestParameters().keyword), buildLayout(maxBindings()),
1884 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
1885 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
1886 setTemplateParam("UNIFORM_DECL", decl);
1887
1888 StringStream s;
1889 s << "vec4(0.0);\n";
1890 setTemplateParam("UNIFORM_ACCESS", s.str());
1891 updateTemplate();
1892
1893 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
1894 passed &= !program->compiledAndLinked();
1895 if (!passed)
1896 {
1897 return LayoutBindingTestResult(passed, program->getErrorLog(true));
1898 }
1899 }
1900 return LayoutBindingTestResult(passed, String());
1901 }
1902
binding_link_errors(void)1903 LayoutBindingTestResult LayoutBindingBaseCase::binding_link_errors(void)
1904 {
1905 bool passed = true;
1906
1907 // same sampler with different binding in two compilation units
1908 if (isStage(VertexShader))
1909 {
1910 String decl =
1911 buildUniformDecl(String(getTestParameters().keyword), buildLayout(1),
1912 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
1913 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
1914 setTemplateParam(VertexShader, "UNIFORM_DECL", decl);
1915
1916 setTemplateParam(VertexShader, "OUT_ASSIGNMENT", String("fragColor ="));
1917
1918 StringStream s;
1919 s << buildAccess(getDefaultUniformName()) << ";\n";
1920 setTemplateParam(VertexShader, "UNIFORM_ACCESS", s.str());
1921 updateTemplate(VertexShader);
1922
1923 decl = buildUniformDecl(String(getTestParameters().keyword), buildLayout(3),
1924 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
1925 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
1926 setTemplateParam(FragmentShader, "UNIFORM_DECL", decl);
1927
1928 s.reset();
1929 s << "fragColor + " << buildAccess(getDefaultUniformName()) << ";\n";
1930 setTemplateParam(FragmentShader, "UNIFORM_ACCESS", s.str());
1931 updateTemplate(FragmentShader);
1932
1933 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
1934 passed = !program->compiledAndLinked();
1935 if (!passed)
1936 {
1937 return LayoutBindingTestResult(passed, program->getErrorLog(true));
1938 }
1939 }
1940
1941 return LayoutBindingTestResult(passed, String());
1942 }
1943
1944 // this subtest is generically empty. Overwritten in test cases as needed.
binding_examples(void)1945 LayoutBindingTestResult LayoutBindingBaseCase::binding_examples(void)
1946 {
1947 return true;
1948 }
1949
1950 // just for image and atomic counter cases
binding_mixed_order(void)1951 LayoutBindingTestResult LayoutBindingBaseCase::binding_mixed_order(void)
1952 {
1953 return true;
1954 }
1955
1956 //=========================================================================
1957 // test case Sampler layout binding
1958 //=========================================================================
1959 class SamplerLayoutBindingCase : public LayoutBindingBaseCase
1960
1961 {
1962 public:
1963 SamplerLayoutBindingCase(Context& context, const char* name, const char* description, StageType stage,
1964 LayoutBindingParameters& samplerType, glu::GLSLVersion glslVersion);
1965 ~SamplerLayoutBindingCase(void);
1966
1967 private:
1968 /*virtual*/
createProgram()1969 LayoutBindingProgram* createProgram()
1970 {
1971 return new LayoutBindingProgram(*this);
1972 }
1973
1974 /*virtual*/
getDefaultUniformName(int idx=0)1975 String getDefaultUniformName(int idx = 0)
1976 {
1977 StringStream s;
1978
1979 s << "sampler" << idx;
1980 return s.str();
1981 }
1982
1983 /*virtual*/
buildLayout(const String & binding)1984 String buildLayout(const String& binding)
1985 {
1986 std::ostringstream s;
1987 if (!binding.empty())
1988 s << "layout(binding=" << binding << ") ";
1989 return s.str();
1990 }
1991
maxBindings()1992 virtual int maxBindings()
1993 {
1994 int units = 0;
1995 gl().getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &units);
1996 return units;
1997 }
1998
1999 // return max. array size allowed
maxArraySize()2000 virtual int maxArraySize()
2001 {
2002 int units = 0;
2003
2004 switch (getStage())
2005 {
2006 case VertexShader:
2007 gl().getIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &units);
2008 break;
2009 case FragmentShader:
2010 gl().getIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &units);
2011 break;
2012 case ComputeShader:
2013 gl().getIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &units);
2014 break;
2015 default:
2016 DE_ASSERT(0);
2017 break;
2018 }
2019
2020 return units;
2021 }
2022 };
2023
SamplerLayoutBindingCase(Context & context,const char * name,const char * description,StageType stage,LayoutBindingParameters & samplerType,glu::GLSLVersion glslVersion)2024 SamplerLayoutBindingCase::SamplerLayoutBindingCase(Context& context, const char* name, const char* description,
2025 StageType stage, LayoutBindingParameters& samplerType,
2026 glu::GLSLVersion glslVersion)
2027 : LayoutBindingBaseCase(context, name, description, stage, samplerType, glslVersion)
2028 {
2029 }
2030
~SamplerLayoutBindingCase(void)2031 SamplerLayoutBindingCase::~SamplerLayoutBindingCase(void)
2032 {
2033 }
2034
2035 //=========================================================================
2036 // test case Image layout binding
2037 //=========================================================================
2038 class ImageLayoutBindingCase : public LayoutBindingBaseCase
2039
2040 {
2041 public:
2042 ImageLayoutBindingCase(Context& context, const char* name, const char* description, StageType stage,
2043 LayoutBindingParameters& samplerType, glu::GLSLVersion glslVersion);
2044 ~ImageLayoutBindingCase(void);
2045
2046 private:
2047 class ImageLayoutBindingProgram : public LayoutBindingProgram
2048 {
2049 public:
ImageLayoutBindingProgram(IProgramContextSupplier & contextSupplier)2050 ImageLayoutBindingProgram(IProgramContextSupplier& contextSupplier) : LayoutBindingProgram(contextSupplier)
2051 {
2052 }
2053 };
2054
2055 private:
2056 // IProgramContextSupplier
2057 /*virtual*/
createProgram()2058 LayoutBindingProgram* createProgram()
2059 {
2060 return new ImageLayoutBindingProgram(*this);
2061 }
2062
2063 private:
2064 /*virtual*/
getDefaultUniformName(int idx=0)2065 String getDefaultUniformName(int idx = 0)
2066 {
2067 StringStream s;
2068 s << "image" << idx;
2069 return s.str();
2070 }
2071
2072 /*virtual*/
buildLayout(const String & binding)2073 String buildLayout(const String& binding)
2074 {
2075 std::ostringstream s;
2076 if (!binding.empty())
2077 s << "layout(binding=" << binding << ", rgba8) readonly ";
2078 else
2079 s << "layout(rgba8) readonly ";
2080 return s.str();
2081 }
2082
2083 /*virtual*/
maxBindings()2084 int maxBindings()
2085 {
2086 int units = 0;
2087 gl().getIntegerv(GL_MAX_IMAGE_UNITS, &units);
2088 return units;
2089 }
2090
2091 /*virtual*/
maxArraySize()2092 int maxArraySize()
2093 {
2094 int units = 0;
2095 switch (getStage())
2096 {
2097 case VertexShader:
2098 gl().getIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &units);
2099 break;
2100 case FragmentShader:
2101 gl().getIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &units);
2102 break;
2103 case ComputeShader:
2104 gl().getIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &units);
2105 break;
2106 default:
2107 DE_ASSERT(0);
2108 break;
2109 }
2110 return units;
2111 }
2112
2113 private:
2114 //virtual LayoutBindingTestResult binding_basic_default (void);
2115 //virtual LayoutBindingTestResult binding_basic_explicit (void);
2116 //virtual LayoutBindingTestResult binding_basic_multiple (void);
2117 //virtual LayoutBindingTestResult binding_basic_render (void);
2118 //virtual LayoutBindingTestResult binding_integer_constant (void);
2119 //virtual LayoutBindingTestResult binding_array_size (void);
2120 //virtual LayoutBindingTestResult binding_array_implicit (void);
2121 //virtual LayoutBindingTestResult binding_array_multiple (void);
2122 /*virtual*/
binding_api_update(void)2123 LayoutBindingTestResult binding_api_update(void)
2124 {
2125 // only for GL
2126 if (getGLSLVersion() == glu::GLSL_VERSION_310_ES)
2127 return LayoutBindingTestResult(true, String(), true);
2128
2129 return LayoutBindingBaseCase::binding_api_update();
2130 }
2131 //virtual LayoutBindingTestResult binding_compilation_errors (void);
2132 //virtual LayoutBindingTestResult binding_link_errors (void);
2133 //virtual LayoutBindingTestResult binding_link_examples (void);
2134 /*virtual*/
binding_mixed_order(void)2135 LayoutBindingTestResult binding_mixed_order(void)
2136 {
2137 bool passed = true;
2138
2139 {
2140 StringStream s;
2141 s << buildAccess(getDefaultUniformName()) << ";\n";
2142 setTemplateParam("UNIFORM_ACCESS", s.str());
2143
2144 String decl =
2145 buildUniformDecl(String(getTestParameters().keyword), String("layout(binding=0, rgba8) readonly"),
2146 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
2147 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
2148 setTemplateParam("UNIFORM_DECL", decl);
2149 updateTemplate();
2150
2151 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
2152 passed &= program->compiledAndLinked();
2153 if (!passed)
2154 {
2155 return LayoutBindingTestResult(passed, program->getErrorLog());
2156 }
2157 }
2158 {
2159 String decl =
2160 buildUniformDecl(String(getTestParameters().keyword), String("layout(r32f, binding=0) readonly"),
2161 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
2162 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
2163 setTemplateParam("UNIFORM_DECL", decl);
2164 updateTemplate();
2165
2166 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
2167 passed &= program->compiledAndLinked();
2168 if (!passed)
2169 {
2170 return LayoutBindingTestResult(passed, program->getErrorLog());
2171 }
2172 }
2173
2174 return true;
2175 }
2176 };
2177
ImageLayoutBindingCase(Context & context,const char * name,const char * description,StageType stage,LayoutBindingParameters & samplerType,glu::GLSLVersion glslVersion)2178 ImageLayoutBindingCase::ImageLayoutBindingCase(Context& context, const char* name, const char* description,
2179 StageType stage, LayoutBindingParameters& samplerType,
2180 glu::GLSLVersion glslVersion)
2181 : LayoutBindingBaseCase(context, name, description, stage, samplerType, glslVersion)
2182 {
2183 }
2184
~ImageLayoutBindingCase(void)2185 ImageLayoutBindingCase::~ImageLayoutBindingCase(void)
2186 {
2187 }
2188
2189 //=========================================================================
2190 // test case Atomic counter binding
2191 //=========================================================================
2192 class AtomicCounterLayoutBindingCase : public LayoutBindingBaseCase
2193
2194 {
2195 public:
2196 AtomicCounterLayoutBindingCase(Context& context, const char* name, const char* description, StageType stage,
2197 LayoutBindingParameters& samplerType, glu::GLSLVersion glslVersion);
~AtomicCounterLayoutBindingCase(void)2198 ~AtomicCounterLayoutBindingCase(void)
2199 {
2200 }
2201
2202 private:
2203 class AtomicCounterLayoutBindingProgram : public LayoutBindingProgram
2204 {
2205 public:
AtomicCounterLayoutBindingProgram(IProgramContextSupplier & contextSupplier)2206 AtomicCounterLayoutBindingProgram(IProgramContextSupplier& contextSupplier)
2207 : LayoutBindingProgram(contextSupplier)
2208 {
2209 }
2210
2211 private:
2212 /*virtual*/
getBindingPoints(StringVector args) const2213 StringIntMap getBindingPoints(StringVector args) const
2214 {
2215 StringIntMap bindingPoints;
2216
2217 for (StringVector::iterator it = args.begin(); it != args.end(); it++)
2218 {
2219 glw::GLuint idx = gl().getProgramResourceIndex(getProgram(), GL_UNIFORM, (*it).c_str());
2220 if (idx != GL_INVALID_INDEX)
2221 {
2222 glw::GLenum param = GL_ATOMIC_COUNTER_BUFFER_INDEX;
2223 glw::GLint atomic_counter_buffer_idx = -1;
2224 gl().getProgramResourceiv(getProgram(), GL_UNIFORM, idx, 1, ¶m, 1, NULL,
2225 &atomic_counter_buffer_idx);
2226 bool hasNoError = (GL_NO_ERROR == gl().getError()) && (-1 != atomic_counter_buffer_idx);
2227 if (!hasNoError)
2228 continue;
2229
2230 param = GL_BUFFER_BINDING;
2231 glw::GLint value = -1;
2232 gl().getProgramResourceiv(getProgram(), GL_ATOMIC_COUNTER_BUFFER, atomic_counter_buffer_idx, 1,
2233 ¶m, 1, NULL, &value);
2234 hasNoError = (GL_NO_ERROR == gl().getError()) && (-1 != value);
2235 if (!hasNoError)
2236 continue;
2237
2238 bindingPoints[*it] = value;
2239 }
2240 }
2241 return bindingPoints;
2242 }
2243
2244 /*virtual*/
getOffsets(StringVector args) const2245 StringIntMap getOffsets(StringVector args) const
2246 {
2247 StringIntMap bindingPoints;
2248
2249 for (StringVector::iterator it = args.begin(); it != args.end(); it++)
2250 {
2251 glw::GLuint idx = gl().getProgramResourceIndex(getProgram(), GL_UNIFORM, (*it).c_str());
2252 if (idx != GL_INVALID_INDEX)
2253 {
2254 glw::GLenum param = GL_OFFSET;
2255 glw::GLint value = -1;
2256 gl().getProgramResourceiv(getProgram(), GL_UNIFORM, idx, 1, ¶m, 1, NULL, &value);
2257 bool hasNoError = (GL_NO_ERROR == gl().getError());
2258 if (hasNoError)
2259 {
2260 bindingPoints[*it] = value;
2261 }
2262 }
2263 }
2264 return bindingPoints;
2265 }
2266 };
2267
2268 private:
2269 // IProgramContextSupplier
2270 /*virtual*/
createProgram()2271 LayoutBindingProgram* createProgram()
2272 {
2273 return new AtomicCounterLayoutBindingProgram(*this);
2274 }
2275
2276 private:
2277 /*virtual*/
getDefaultUniformName(int idx=0)2278 String getDefaultUniformName(int idx = 0)
2279 {
2280 StringStream s;
2281 s << "atomic" << idx;
2282 return s.str();
2283 }
2284
2285 /*virtual*/
buildAccess(const String & var)2286 String buildAccess(const String& var)
2287 {
2288 std::ostringstream s;
2289 s << "vec4(float(atomicCounter(" << var << ")), 1.0, 0.0, 1.0)";
2290 return s.str();
2291 }
2292
maxBindings()2293 int maxBindings()
2294 {
2295 int units = 0;
2296 gl().getIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &units);
2297 return units;
2298 }
2299
2300 // return max. array size allowed
maxArraySize()2301 int maxArraySize()
2302 {
2303 int units = 0;
2304 switch (getStage())
2305 {
2306 case FragmentShader:
2307 gl().getIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTERS, &units);
2308 break;
2309 case VertexShader:
2310 gl().getIntegerv(GL_MAX_VERTEX_ATOMIC_COUNTERS, &units);
2311 break;
2312 case ComputeShader:
2313 gl().getIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTERS, &units);
2314 break;
2315 default:
2316 DE_ASSERT(0);
2317 break;
2318 }
2319 return units;
2320 }
2321
2322 //=========================================================================
2323 // sub-tests overrides
2324 //=========================================================================
2325 private:
binding_basic_default(void)2326 LayoutBindingTestResult binding_basic_default(void)
2327 {
2328 return true;
2329 }
2330 //virtual LayoutBindingTestResult binding_basic_explicit (void);
2331 //virtual LayoutBindingTestResult binding_basic_multiple (void);
binding_basic_render(void)2332 LayoutBindingTestResult binding_basic_render(void)
2333 {
2334 return true;
2335 }
2336 //virtual LayoutBindingTestResult binding_integer_constant (void);
2337 /*virtual*/
binding_array_size(void)2338 LayoutBindingTestResult binding_array_size(void)
2339 {
2340 bool passed = true;
2341
2342 //== test different sized arrays
2343 std::vector<int> arraySizes = makeSparseRange(maxArraySize(), 1);
2344 for (std::vector<int>::iterator it = arraySizes.begin(); it < arraySizes.end(); it++)
2345 {
2346 int arraySize = *it;
2347 StringStream s;
2348 s << "[" << arraySize << "]";
2349 String decl =
2350 buildUniformDecl(String(getTestParameters().keyword), buildLayout(0),
2351 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
2352 buildBlock(getDefaultUniformName()), getDefaultUniformName(), buildArray(arraySize));
2353 setTemplateParam("UNIFORM_DECL", decl);
2354
2355 s.reset();
2356 // build a function that accesses the whole array
2357 s << "float accumulate(void)\n";
2358 s << "{\n";
2359 s << " float acc = 0.0;\n";
2360 s << " for(int i=0; i < " << arraySize << " ; i++)\n";
2361 s << " acc = float(atomicCounter(" << getDefaultUniformName() << "[i]));\n";
2362 s << " return acc;\n";
2363 s << "}\n";
2364
2365 setTemplateParam("OPTIONAL_FUNCTION_BLOCK", s.str());
2366
2367 s.reset();
2368 s << "vec4(accumulate(), 1.0, 0.0, 1.0);\n";
2369 setTemplateParam("UNIFORM_ACCESS", s.str());
2370 updateTemplate();
2371
2372 setTemplateParam("OPTIONAL_FUNCTION_BLOCK", String());
2373
2374 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
2375 passed &= program->compiledAndLinked();
2376 if (!passed)
2377 {
2378 return LayoutBindingTestResult(passed, program->getErrorLog());
2379 }
2380
2381 StringVector list;
2382 std::ostringstream texUnitStr;
2383 texUnitStr << getDefaultUniformName() << "[0]";
2384 list.push_back(texUnitStr.str());
2385
2386 StringIntMap bindingPoints = program->getBindingPoints(list);
2387 passed &= (0 == bindingPoints[list[0]]);
2388 if (!passed)
2389 {
2390 return LayoutBindingTestResult(
2391 passed, generateLog(String("binding point did not match default"), bindingPoints[list[0]], 1));
2392 }
2393 }
2394
2395 return LayoutBindingTestResult(passed, String());
2396 }
binding_array_implicit(void)2397 LayoutBindingTestResult binding_array_implicit(void)
2398 {
2399 return true;
2400 }
binding_array_multiple(void)2401 LayoutBindingTestResult binding_array_multiple(void)
2402 {
2403 return true;
2404 }
binding_api_update(void)2405 LayoutBindingTestResult binding_api_update(void)
2406 {
2407 return true;
2408 }
2409 //virtual LayoutBindingTestResult binding_compilation_errors (void);
2410 //virtual LayoutBindingTestResult binding_link_errors (void);
2411
binding_examples_many_bindings(void)2412 LayoutBindingTestResult binding_examples_many_bindings(void)
2413 {
2414 int max_bindings = 0;
2415
2416 if (isStage(VertexShader))
2417 {
2418 gl().getIntegerv(GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS, &max_bindings);
2419 }
2420 else if (isStage(FragmentShader))
2421 {
2422 gl().getIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS, &max_bindings);
2423 }
2424 else
2425 {
2426 gl().getIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS, &max_bindings);
2427 }
2428
2429 // example 1 in atomic counter CTS spec ac-binding-examples
2430 {
2431 bool passed = true;
2432 StringStream s;
2433 s << buildAccess(getDefaultUniformName()) << ";\n";
2434 setTemplateParam("UNIFORM_ACCESS", s.str());
2435
2436 s.reset();
2437 s << "layout(binding=2, offset=4) uniform atomic_uint;\n";
2438 s << "layout(binding=2) uniform atomic_uint " << getDefaultUniformName() << ";\n";
2439 setTemplateParam("UNIFORM_DECL", s.str());
2440 updateTemplate();
2441
2442 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
2443 passed &= program->compiledAndLinked();
2444 if (!passed)
2445 {
2446 return LayoutBindingTestResult(passed, program->getErrorLog());
2447 }
2448
2449 StringVector list;
2450 list.push_back(getDefaultUniformName());
2451
2452 StringIntMap offsets = program->getOffsets(list);
2453 passed &= (4 == offsets[list[0]]);
2454 if (!passed)
2455 {
2456 return LayoutBindingTestResult(
2457 passed, generateLog(String("offset did not match requested"), offsets[list[0]], 1));
2458 }
2459 }
2460
2461 // example 2 in atomic counter CTS spec ac-binding-examples
2462 if (max_bindings >= 2)
2463 {
2464 bool passed = true;
2465 StringStream s;
2466 s << buildAccess(getDefaultUniformName()) << "\n";
2467 s << "+" << buildAccess(getDefaultUniformName(1)) << "\n";
2468 s << "+" << buildAccess(getDefaultUniformName(2)) << "\n";
2469 s << "+" << buildAccess(getDefaultUniformName(3)) << ";\n";
2470 setTemplateParam("UNIFORM_ACCESS", s.str());
2471
2472 s.reset();
2473 s << "layout(binding=3, offset=4) uniform atomic_uint " << getDefaultUniformName() << ";\n";
2474 s << "layout(binding=2) uniform atomic_uint " << getDefaultUniformName(1) << ";\n";
2475 s << "layout(binding=3) uniform atomic_uint " << getDefaultUniformName(2) << ";\n";
2476 s << "layout(binding=2) uniform atomic_uint " << getDefaultUniformName(3) << ";\n";
2477 setTemplateParam("UNIFORM_DECL", s.str());
2478 updateTemplate();
2479
2480 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
2481 passed &= program->compiledAndLinked();
2482 if (!passed)
2483 {
2484 return LayoutBindingTestResult(passed, program->getErrorLog());
2485 }
2486
2487 StringVector list;
2488 list.push_back(getDefaultUniformName());
2489 list.push_back(getDefaultUniformName(1));
2490 list.push_back(getDefaultUniformName(2));
2491 list.push_back(getDefaultUniformName(3));
2492
2493 StringIntMap offsets = program->getOffsets(list);
2494 IntVector expected;
2495 expected.insert(expected.end(), 4);
2496 expected.insert(expected.end(), 0);
2497 expected.insert(expected.end(), 8);
2498 expected.insert(expected.end(), 4);
2499 for (unsigned int idx = 0; idx < list.size(); idx++)
2500 {
2501 passed &= (expected[idx] == offsets[list[idx]]);
2502 if (!passed)
2503 {
2504 return LayoutBindingTestResult(
2505 passed, generateLog(String("offset of") + String(list[idx]) + String("did not match requested"),
2506 offsets[list[idx]], 4));
2507 }
2508 }
2509 }
2510
2511 // example 3 in atomic counter CTS spec ac-binding-examples
2512 {
2513 bool passed = true;
2514 StringStream s;
2515 s << buildAccess(getDefaultUniformName()) << ";\n";
2516 setTemplateParam("UNIFORM_ACCESS", s.str());
2517
2518 s.reset();
2519 s << "layout(binding=2, offset=4) uniform atomic_uint;\n";
2520 s << "layout(offset=8) uniform atomic_uint " << getDefaultUniformName() << ";\n";
2521 setTemplateParam("UNIFORM_DECL", s.str());
2522 updateTemplate();
2523
2524 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
2525 passed &= program->compiledAndLinked();
2526 if (passed)
2527 {
2528 return LayoutBindingTestResult(!passed, String("should not compile"));
2529 }
2530 }
2531
2532 // example 4 in atomic counter CTS spec ac-binding-examples
2533 {
2534 bool passed = true;
2535 StringStream s;
2536 s << buildAccess(getDefaultUniformName()) << ";\n";
2537 setTemplateParam("UNIFORM_ACCESS", s.str());
2538
2539 s.reset();
2540 s << "layout(offset=4) uniform atomic_uint " << getDefaultUniformName() << ";\n";
2541 setTemplateParam("UNIFORM_DECL", s.str());
2542 updateTemplate();
2543
2544 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
2545 passed &= program->compiledAndLinked();
2546 if (passed)
2547 {
2548 return LayoutBindingTestResult(!passed, String("should not compile"));
2549 }
2550 }
2551
2552 // example 5 in atomic counter CTS spec ac-binding-examples
2553 // first check working example, then amend it with an error
2554 if (max_bindings >= 2)
2555 {
2556 for (int pass = 0; pass < 2; pass++)
2557 {
2558 bool passed = true;
2559
2560 StringStream s;
2561 s << buildAccess(getDefaultUniformName()) << "\n";
2562 if (pass)
2563 {
2564 s << "+" << buildAccess(getDefaultUniformName(1)) << "\n";
2565 s << "+" << buildAccess(getDefaultUniformName(2)) << ";\n";
2566 }
2567 else
2568 {
2569 s << "+" << buildAccess(getDefaultUniformName(1)) << ";\n";
2570 }
2571 setTemplateParam("UNIFORM_ACCESS", s.str());
2572
2573 s.reset();
2574 s << "layout(binding=1, offset=0) uniform atomic_uint " << getDefaultUniformName() << ";\n";
2575 s << "layout(binding=2, offset=0) uniform atomic_uint " << getDefaultUniformName(1) << ";\n";
2576 if (pass)
2577 s << "layout(binding=1, offset=0) uniform atomic_uint " << getDefaultUniformName(2) << ";\n";
2578 setTemplateParam("UNIFORM_DECL", s.str());
2579 updateTemplate();
2580
2581 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
2582 passed &= program->compiledAndLinked();
2583 if (pass != 0)
2584 {
2585 if (passed)
2586 {
2587 return LayoutBindingTestResult(passed, program->getErrorLog());
2588 }
2589 }
2590 else
2591 {
2592 if (!passed)
2593 {
2594 return LayoutBindingTestResult(passed, String("should not compile"));
2595 }
2596 }
2597 }
2598 }
2599
2600 // example 6 in atomic counter CTS spec ac-binding-examples
2601 // first check working example, then amend it with an error
2602 if (max_bindings >= 2)
2603 {
2604 for (int pass = 0; pass < 2; pass++)
2605 {
2606 bool passed = true;
2607
2608 StringStream s;
2609 s << buildAccess(getDefaultUniformName()) << "\n";
2610 if (pass)
2611 {
2612 s << "+" << buildAccess(getDefaultUniformName(1)) << "\n";
2613 s << "+" << buildAccess(getDefaultUniformName(2)) << ";\n";
2614 }
2615 else
2616 {
2617 s << "+" << buildAccess(getDefaultUniformName(1)) << ";\n";
2618 }
2619 setTemplateParam("UNIFORM_ACCESS", s.str());
2620
2621 s.reset();
2622 s << "layout(binding=1, offset=0) uniform atomic_uint " << getDefaultUniformName() << ";\n";
2623 s << "layout(binding=2, offset=0) uniform atomic_uint " << getDefaultUniformName(1) << ";\n";
2624 if (pass)
2625 s << "layout(binding=1, offset=2) uniform atomic_uint " << getDefaultUniformName(2) << ";\n";
2626 setTemplateParam("UNIFORM_DECL", s.str());
2627 updateTemplate();
2628
2629 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
2630 passed &= program->compiledAndLinked();
2631 if (pass != 0)
2632 {
2633 if (passed)
2634 {
2635 return LayoutBindingTestResult(passed, program->getErrorLog());
2636 }
2637 }
2638 else
2639 {
2640 if (!passed)
2641 {
2642 return LayoutBindingTestResult(passed, String("should not compile"));
2643 }
2644 }
2645 }
2646 }
2647
2648 return true;
2649 }
2650
binding_examples_one_binding(void)2651 LayoutBindingTestResult binding_examples_one_binding(void)
2652 {
2653 // example 1 in atomic counter CTS spec ac-binding-examples
2654 {
2655 bool passed = true;
2656 StringStream s;
2657 s << buildAccess(getDefaultUniformName()) << ";\n";
2658 setTemplateParam("UNIFORM_ACCESS", s.str());
2659
2660 s.reset();
2661 s << "layout(binding=0, offset=4) uniform atomic_uint;\n";
2662 s << "layout(binding=0) uniform atomic_uint " << getDefaultUniformName() << ";\n";
2663 setTemplateParam("UNIFORM_DECL", s.str());
2664 updateTemplate();
2665
2666 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
2667 passed &= program->compiledAndLinked();
2668 if (!passed)
2669 {
2670 return LayoutBindingTestResult(passed, program->getErrorLog());
2671 }
2672
2673 StringVector list;
2674 list.push_back(getDefaultUniformName());
2675
2676 StringIntMap offsets = program->getOffsets(list);
2677 passed &= (4 == offsets[list[0]]);
2678 if (!passed)
2679 {
2680 return LayoutBindingTestResult(
2681 passed, generateLog(String("offset did not match requested"), offsets[list[0]], 1));
2682 }
2683 }
2684
2685 // example 2 in atomic counter CTS spec ac-binding-examples
2686 {
2687 bool passed = true;
2688 StringStream s;
2689 s << buildAccess(getDefaultUniformName()) << "\n";
2690 s << "+" << buildAccess(getDefaultUniformName(1)) << "\n";
2691 s << "+" << buildAccess(getDefaultUniformName(2)) << "\n";
2692 s << "+" << buildAccess(getDefaultUniformName(3)) << ";\n";
2693 setTemplateParam("UNIFORM_ACCESS", s.str());
2694
2695 s.reset();
2696 s << "layout(binding=0, offset=4) uniform atomic_uint " << getDefaultUniformName() << ";\n";
2697 s << "layout(binding=0) uniform atomic_uint " << getDefaultUniformName(1) << ";\n";
2698 s << "layout(binding=0) uniform atomic_uint " << getDefaultUniformName(2) << ";\n";
2699 s << "layout(binding=0) uniform atomic_uint " << getDefaultUniformName(3) << ";\n";
2700 setTemplateParam("UNIFORM_DECL", s.str());
2701 updateTemplate();
2702
2703 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
2704 passed &= program->compiledAndLinked();
2705 if (!passed)
2706 {
2707 return LayoutBindingTestResult(passed, program->getErrorLog());
2708 }
2709
2710 StringVector list;
2711 list.push_back(getDefaultUniformName());
2712 list.push_back(getDefaultUniformName(1));
2713 list.push_back(getDefaultUniformName(2));
2714 list.push_back(getDefaultUniformName(3));
2715
2716 StringIntMap offsets = program->getOffsets(list);
2717 IntVector expected;
2718 expected.insert(expected.end(), 4);
2719 expected.insert(expected.end(), 8);
2720 expected.insert(expected.end(), 12);
2721 expected.insert(expected.end(), 16);
2722 for (unsigned int idx = 0; idx < list.size(); idx++)
2723 {
2724 passed &= (expected[idx] == offsets[list[idx]]);
2725 if (!passed)
2726 {
2727 return LayoutBindingTestResult(
2728 passed, generateLog(String("offset of") + String(list[idx]) + String("did not match requested"),
2729 offsets[list[idx]], expected[idx]));
2730 }
2731 }
2732 }
2733
2734 // example 3 in atomic counter CTS spec ac-binding-examples
2735 {
2736 bool passed = true;
2737 StringStream s;
2738 s << buildAccess(getDefaultUniformName()) << ";\n";
2739 setTemplateParam("UNIFORM_ACCESS", s.str());
2740
2741 s.reset();
2742 s << "layout(binding=0, offset=4) uniform atomic_uint;\n";
2743 s << "layout(offset=8) uniform atomic_uint " << getDefaultUniformName() << ";\n";
2744 setTemplateParam("UNIFORM_DECL", s.str());
2745 updateTemplate();
2746
2747 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
2748 passed &= program->compiledAndLinked();
2749 if (passed)
2750 {
2751 return LayoutBindingTestResult(!passed, String("should not compile"));
2752 }
2753 }
2754
2755 // example 4 in atomic counter CTS spec ac-binding-examples
2756 {
2757 bool passed = true;
2758 StringStream s;
2759 s << buildAccess(getDefaultUniformName()) << ";\n";
2760 setTemplateParam("UNIFORM_ACCESS", s.str());
2761
2762 s.reset();
2763 s << "layout(offset=4) uniform atomic_uint " << getDefaultUniformName() << ";\n";
2764 setTemplateParam("UNIFORM_DECL", s.str());
2765 updateTemplate();
2766
2767 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
2768 passed &= program->compiledAndLinked();
2769 if (passed)
2770 {
2771 return LayoutBindingTestResult(!passed, String("should not compile"));
2772 }
2773 }
2774
2775 // example 5 in atomic counter CTS spec ac-binding-examples
2776 // first check working example, then amend it with an error
2777 for (int pass = 0; pass < 2; pass++)
2778 {
2779 bool passed = true;
2780
2781 StringStream s;
2782
2783 if (pass)
2784 {
2785 s << buildAccess(getDefaultUniformName()) << "\n";
2786 s << "+" << buildAccess(getDefaultUniformName(1)) << ";\n";
2787 }
2788 else
2789 {
2790 s << buildAccess(getDefaultUniformName()) << ";\n";
2791 }
2792 setTemplateParam("UNIFORM_ACCESS", s.str());
2793
2794 s.reset();
2795 s << "layout(binding=0, offset=0) uniform atomic_uint " << getDefaultUniformName() << ";\n";
2796 if (pass)
2797 s << "layout(binding=0, offset=0) uniform atomic_uint " << getDefaultUniformName(1) << ";\n";
2798 setTemplateParam("UNIFORM_DECL", s.str());
2799 updateTemplate();
2800
2801 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
2802 passed &= program->compiledAndLinked();
2803 if (pass != 0)
2804 {
2805 if (passed)
2806 {
2807 return LayoutBindingTestResult(passed, program->getErrorLog());
2808 }
2809 }
2810 else
2811 {
2812 if (!passed)
2813 {
2814 return LayoutBindingTestResult(passed, String("should not compile"));
2815 }
2816 }
2817 }
2818
2819 // example 6 in atomic counter CTS spec ac-binding-examples
2820 // first check working example, then amend it with an error
2821 for (int pass = 0; pass < 2; pass++)
2822 {
2823 bool passed = true;
2824
2825 StringStream s;
2826 if (pass)
2827 {
2828 s << buildAccess(getDefaultUniformName()) << "\n";
2829 s << "+" << buildAccess(getDefaultUniformName(1)) << ";\n";
2830 }
2831 else
2832 {
2833 s << buildAccess(getDefaultUniformName()) << ";\n";
2834 }
2835 setTemplateParam("UNIFORM_ACCESS", s.str());
2836
2837 s.reset();
2838 s << "layout(binding=0, offset=0) uniform atomic_uint " << getDefaultUniformName() << ";\n";
2839 if (pass)
2840 s << "layout(binding=0, offset=2) uniform atomic_uint " << getDefaultUniformName(1) << ";\n";
2841 setTemplateParam("UNIFORM_DECL", s.str());
2842 updateTemplate();
2843
2844 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
2845 passed &= program->compiledAndLinked();
2846 if (pass != 0)
2847 {
2848 if (passed)
2849 {
2850 return LayoutBindingTestResult(passed, program->getErrorLog());
2851 }
2852 }
2853 else
2854 {
2855 if (!passed)
2856 {
2857 return LayoutBindingTestResult(passed, String("should not compile"));
2858 }
2859 }
2860 }
2861
2862 return true;
2863 }
2864
2865 /*virtual*/
binding_examples(void)2866 LayoutBindingTestResult binding_examples(void)
2867 {
2868 if (maxBindings() >= 4)
2869 {
2870 return binding_examples_many_bindings();
2871 }
2872 else
2873 {
2874 return binding_examples_one_binding();
2875 }
2876 }
2877
2878 /*virtual*/
binding_mixed_order(void)2879 LayoutBindingTestResult binding_mixed_order(void)
2880 {
2881 bool passed = true;
2882
2883 {
2884 StringStream s;
2885 s << buildAccess(getDefaultUniformName()) << ";\n";
2886 setTemplateParam("UNIFORM_ACCESS", s.str());
2887
2888 String decl =
2889 buildUniformDecl(String(getTestParameters().keyword), String("layout(binding=0, offset=0)"),
2890 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
2891 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
2892 setTemplateParam("UNIFORM_DECL", decl);
2893 updateTemplate();
2894
2895 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
2896 passed &= program->compiledAndLinked();
2897 if (!passed)
2898 {
2899 return LayoutBindingTestResult(passed, program->getErrorLog());
2900 }
2901 }
2902 {
2903 String decl =
2904 buildUniformDecl(String(getTestParameters().keyword), String("layout(offset=0, binding=0)"),
2905 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
2906 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
2907 setTemplateParam("UNIFORM_DECL", decl);
2908 updateTemplate();
2909
2910 LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
2911 passed &= program->compiledAndLinked();
2912 if (!passed)
2913 {
2914 return LayoutBindingTestResult(passed, program->getErrorLog());
2915 }
2916 }
2917
2918 return true;
2919 }
2920 };
2921
AtomicCounterLayoutBindingCase(Context & context,const char * name,const char * description,StageType stage,LayoutBindingParameters & samplerType,glu::GLSLVersion glslVersion)2922 AtomicCounterLayoutBindingCase::AtomicCounterLayoutBindingCase(Context& context, const char* name,
2923 const char* description, StageType stage,
2924 LayoutBindingParameters& samplerType,
2925 glu::GLSLVersion glslVersion)
2926 : LayoutBindingBaseCase(context, name, description, stage, samplerType, glslVersion)
2927 {
2928 }
2929
2930 //=========================================================================
2931 // test case Uniform blocks binding
2932 //=========================================================================
2933 class UniformBlocksLayoutBindingCase : public LayoutBindingBaseCase
2934
2935 {
2936 public:
2937 UniformBlocksLayoutBindingCase(Context& context, const char* name, const char* description, StageType stage,
2938 LayoutBindingParameters& samplerType, glu::GLSLVersion glslVersion);
2939 ~UniformBlocksLayoutBindingCase(void);
2940
2941 private:
2942 class UniformBlocksLayoutBindingProgram : public LayoutBindingProgram
2943 {
2944 public:
UniformBlocksLayoutBindingProgram(IProgramContextSupplier & contextSupplier)2945 UniformBlocksLayoutBindingProgram(IProgramContextSupplier& contextSupplier)
2946 : LayoutBindingProgram(contextSupplier)
2947 {
2948 }
2949
~UniformBlocksLayoutBindingProgram()2950 ~UniformBlocksLayoutBindingProgram()
2951 {
2952 }
2953
2954 private:
2955 /*virtual*/
getBindingPoints(StringVector args) const2956 StringIntMap getBindingPoints(StringVector args) const
2957 {
2958 StringIntMap bindingPoints;
2959
2960 for (StringVector::iterator it = args.begin(); it != args.end(); it++)
2961 {
2962 glw::GLuint idx = gl().getProgramResourceIndex(getProgram(), GL_UNIFORM_BLOCK, (*it).c_str());
2963 if (idx != glw::GLuint(-1))
2964 {
2965 glw::GLenum param = GL_BUFFER_BINDING;
2966 glw::GLint value = -1;
2967 gl().getProgramResourceiv(getProgram(), GL_UNIFORM_BLOCK, idx, 1, ¶m, 1, NULL, &value);
2968 bool hasNoError = (GL_NO_ERROR == gl().getError());
2969 if (hasNoError)
2970 {
2971 bindingPoints[*it] = value;
2972 }
2973 }
2974 }
2975
2976 return bindingPoints;
2977 }
2978
2979 /*virtual*/
setBindingPoints(StringVector list,glw::GLint bindingPoint) const2980 bool setBindingPoints(StringVector list, glw::GLint bindingPoint) const
2981 {
2982 bool bNoError = true;
2983
2984 for (StringVector::iterator it = list.begin(); it != list.end(); it++)
2985 {
2986 glw::GLuint blockIndex = gl().getUniformBlockIndex(getProgram(), (*it).c_str());
2987 if (blockIndex == GL_INVALID_INDEX)
2988
2989 {
2990 return false;
2991 }
2992 gl().uniformBlockBinding(getProgram(), blockIndex, bindingPoint);
2993 }
2994 return bNoError;
2995 }
2996 };
2997
2998 private:
2999 // IProgramContextSupplier
3000 /*virtual*/
createProgram()3001 LayoutBindingProgram* createProgram()
3002 {
3003 return new UniformBlocksLayoutBindingProgram(*this);
3004 }
3005
3006 private:
3007 /*virtual*/
buildBlockName(const String & name)3008 String buildBlockName(const String& name)
3009 {
3010
3011 return name;
3012 }
3013
3014 /*virtual*/
buildBlock(const String & name,const String & type)3015 String buildBlock(const String& name, const String& type)
3016 {
3017
3018 std::ostringstream s;
3019 s << "{";
3020 s << type << " " << name << "_a; ";
3021 s << type << " " << name << "_b; ";
3022 s << "}";
3023 return s.str();
3024 }
3025
3026 /*virtual*/
buildAccess(const String & var)3027 String buildAccess(const String& var)
3028 {
3029 std::ostringstream s;
3030 s << "vec4(0.0, " << var << "_a, 0.0, 1.0) + vec4(0.0, " << var << "_b, 0.0, 1.0)";
3031 return s.str();
3032 }
3033
3034 /*virtual*/
buildLayout(const String & binding)3035 String buildLayout(const String& binding)
3036 {
3037 std::ostringstream s;
3038 if (!binding.empty())
3039 s << "layout(binding=" << binding << ", std140) ";
3040 else
3041 s << "layout(std140) ";
3042 return s.str();
3043 }
3044
3045 /*virtual*/
maxBindings()3046 int maxBindings()
3047 {
3048 int units = 0;
3049 gl().getIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &units);
3050 return units;
3051 }
3052
3053 // return max. array size allowed
3054 /*virtual*/
maxArraySize()3055 int maxArraySize()
3056 {
3057 int units = 0;
3058 switch (getStage())
3059 {
3060 case FragmentShader:
3061 gl().getIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS, &units);
3062 break;
3063 case VertexShader:
3064 gl().getIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS, &units);
3065 break;
3066 case ComputeShader:
3067 gl().getIntegerv(GL_MAX_COMPUTE_UNIFORM_BLOCKS, &units);
3068 break;
3069 default:
3070 DE_ASSERT(0);
3071 break;
3072 }
3073 return units;
3074 }
3075
3076 /*virtual*/
bind(int binding)3077 void bind(int binding)
3078 {
3079 gl().bindBufferBase(GL_UNIFORM_BUFFER, binding, m_buffername);
3080 }
3081
3082 /*virtual*/
unbind(int binding)3083 void unbind(int binding)
3084 {
3085 gl().bindBufferBase(GL_UNIFORM_BUFFER, binding, 0);
3086 }
3087
3088 /*virtual*/
setupTest(void)3089 void setupTest(void)
3090 {
3091 const float f[2] = { 0.25f, 0.75f };
3092 gl().genBuffers(1, &m_buffername);
3093 gl().bindBuffer(GL_UNIFORM_BUFFER, m_buffername);
3094 gl().bufferData(GL_UNIFORM_BUFFER, sizeof(f), f, GL_STATIC_DRAW);
3095 }
3096
3097 /*virtual*/
teardownTest(void)3098 void teardownTest(void)
3099 {
3100 gl().bindBuffer(GL_UNIFORM_BUFFER, 0);
3101 gl().deleteBuffers(1, &m_buffername);
3102 }
3103
3104 private:
3105 glw::GLuint m_buffername;
3106 };
3107
UniformBlocksLayoutBindingCase(Context & context,const char * name,const char * description,StageType stage,LayoutBindingParameters & samplerType,glu::GLSLVersion glslVersion)3108 UniformBlocksLayoutBindingCase::UniformBlocksLayoutBindingCase(Context& context, const char* name,
3109 const char* description, StageType stage,
3110 LayoutBindingParameters& samplerType,
3111 glu::GLSLVersion glslVersion)
3112 : LayoutBindingBaseCase(context, name, description, stage, samplerType, glslVersion), m_buffername(0)
3113 {
3114 }
3115
~UniformBlocksLayoutBindingCase()3116 UniformBlocksLayoutBindingCase::~UniformBlocksLayoutBindingCase()
3117 {
3118 }
3119
3120 //*****************************************************************************
3121
3122 //=========================================================================
3123 // test case Shader storage buffer binding
3124 //=========================================================================
3125 class ShaderStorageBufferLayoutBindingCase : public LayoutBindingBaseCase
3126 {
3127 public:
3128 ShaderStorageBufferLayoutBindingCase(Context& context, const char* name, const char* description, StageType stage,
3129 LayoutBindingParameters& samplerType, glu::GLSLVersion glslVersion);
3130 ~ShaderStorageBufferLayoutBindingCase(void);
3131
3132 private:
3133 class ShaderStorageBufferLayoutBindingProgram : public LayoutBindingProgram
3134 {
3135 public:
ShaderStorageBufferLayoutBindingProgram(IProgramContextSupplier & contextSupplier)3136 ShaderStorageBufferLayoutBindingProgram(IProgramContextSupplier& contextSupplier)
3137 : LayoutBindingProgram(contextSupplier)
3138 {
3139 }
3140
~ShaderStorageBufferLayoutBindingProgram()3141 ~ShaderStorageBufferLayoutBindingProgram()
3142 {
3143 }
3144 //*******************************************************************************
3145 // overwritten virtual methods
3146 private:
3147 /*virtual*/
getBindingPoints(StringVector args) const3148 StringIntMap getBindingPoints(StringVector args) const
3149 {
3150 StringIntMap bindingPoints;
3151
3152 for (StringVector::iterator it = args.begin(); it != args.end(); it++)
3153 {
3154 glw::GLuint idx = gl().getProgramResourceIndex(getProgram(), GL_SHADER_STORAGE_BLOCK, (*it).c_str());
3155 if (idx != GL_INVALID_INDEX)
3156 {
3157 glw::GLenum param = GL_BUFFER_BINDING;
3158 glw::GLint value = -1;
3159 gl().getProgramResourceiv(getProgram(), GL_SHADER_STORAGE_BLOCK, idx, 1, ¶m, 1, NULL, &value);
3160 bool hasNoError = (GL_NO_ERROR == gl().getError());
3161 if (hasNoError)
3162 {
3163 bindingPoints[*it] = value;
3164 }
3165 }
3166 }
3167
3168 return bindingPoints;
3169 }
3170
3171 /*virtual*/
setBindingPoints(StringVector list,glw::GLint bindingPoint) const3172 bool setBindingPoints(StringVector list, glw::GLint bindingPoint) const
3173 {
3174 for (StringVector::iterator it = list.begin(); it != list.end(); it++)
3175 {
3176 glw::GLuint blockIndex =
3177 gl().getProgramResourceIndex(getProgram(), GL_SHADER_STORAGE_BLOCK, (*it).c_str());
3178 if (blockIndex == GL_INVALID_INDEX)
3179 {
3180 return false;
3181 }
3182 gl().shaderStorageBlockBinding(getProgram(), blockIndex, bindingPoint);
3183 }
3184 return true;
3185 }
3186 };
3187
3188 private:
3189 // IProgramContextSupplier
3190 /*virtual*/
createProgram()3191 LayoutBindingProgram* createProgram()
3192 {
3193 return new ShaderStorageBufferLayoutBindingProgram(*this);
3194 }
3195
3196 private:
3197 /*virtual*/
buildLayout(const String & binding)3198 String buildLayout(const String& binding)
3199 {
3200 std::ostringstream s;
3201 if (!binding.empty())
3202 s << "layout(binding=" << binding << ", std430) ";
3203 else
3204 s << "layout(std430) ";
3205 return s.str();
3206 }
3207
3208 /*virtual*/
getDefaultUniformName(int idx=0)3209 String getDefaultUniformName(int idx = 0)
3210 {
3211 StringStream s;
3212
3213 s << "buffer" << idx;
3214 return s.str();
3215 }
3216 /*virtual*/
buildBlockName(const String & name)3217 String buildBlockName(const String& name)
3218 {
3219 return name;
3220 }
3221
3222 /*virtual*/
buildBlock(const String & name,const String & type)3223 String buildBlock(const String& name, const String& type)
3224 {
3225 std::ostringstream s;
3226 s << "{";
3227 s << type << " " << name << "_a[2];\n";
3228 s << "}";
3229 return s.str();
3230 }
3231
3232 /*virtual*/
buildAccess(const String & var)3233 String buildAccess(const String& var)
3234 {
3235 std::ostringstream s;
3236 s << "vec4(0.0, " << var << "_a[0] + " << var << "_a[1], 0.0, 1.0)";
3237 return s.str();
3238 }
3239
maxBindings()3240 int maxBindings()
3241 {
3242 int units = 0;
3243 gl().getIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &units);
3244 return units;
3245 }
3246
3247 // return max. array size allowed
maxArraySize()3248 int maxArraySize()
3249 {
3250 int units = 0;
3251 switch (getStage())
3252 {
3253 case FragmentShader:
3254 gl().getIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &units);
3255 break;
3256 case VertexShader:
3257 gl().getIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &units);
3258 break;
3259 case ComputeShader:
3260 gl().getIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &units);
3261 break;
3262 default:
3263 DE_ASSERT(0);
3264 break;
3265 }
3266 return units;
3267 }
3268
3269 /*virtual*/
bind(int binding)3270 void bind(int binding)
3271 {
3272 gl().bindBufferBase(GL_SHADER_STORAGE_BUFFER, binding, m_buffername);
3273 }
3274
3275 /*virtual*/
unbind(int binding)3276 void unbind(int binding)
3277 {
3278 gl().bindBufferBase(GL_SHADER_STORAGE_BUFFER, binding, 0);
3279 }
3280
3281 /*virtual*/
setupTest(void)3282 void setupTest(void)
3283 {
3284 const float f[2] = { 0.25f, 0.75f };
3285 gl().genBuffers(1, &m_buffername);
3286 gl().bindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffername);
3287 gl().bufferData(GL_SHADER_STORAGE_BUFFER, sizeof(f), f, GL_STATIC_DRAW);
3288 }
3289
3290 /*virtual*/
teardownTest(void)3291 void teardownTest(void)
3292 {
3293 gl().bindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
3294 gl().deleteBuffers(1, &m_buffername);
3295 }
3296
3297 //=========================================================================
3298 // sub-tests overrides
3299 //=========================================================================
3300 private:
3301 private:
3302 //virtual LayoutBindingTestResult binding_basic_default (void);
3303 //virtual LayoutBindingTestResult binding_basic_explicit (void);
3304 //virtual LayoutBindingTestResult binding_basic_multiple (void);
3305 //virtual LayoutBindingTestResult binding_basic_render (void);
3306 //virtual LayoutBindingTestResult binding_integer_constant (void);
3307 //virtual LayoutBindingTestResult binding_array_size (void);
3308 //virtual LayoutBindingTestResult binding_array_implicit (void);
3309 //virtual LayoutBindingTestResult binding_array_multiple (void);
3310 /*virtual*/
binding_api_update(void)3311 LayoutBindingTestResult binding_api_update(void)
3312 {
3313 // only for GL
3314 if (getGLSLVersion() == glu::GLSL_VERSION_310_ES)
3315 return LayoutBindingTestResult(true, String(), true);
3316
3317 return LayoutBindingBaseCase::binding_api_update();
3318 }
3319 //virtual LayoutBindingTestResult binding_compilation_errors (void);
3320 //virtual LayoutBindingTestResult binding_link_errors (void);
3321 //virtual LayoutBindingTestResult binding_examples (void);
3322
3323 private:
3324 glw::GLuint m_buffername;
3325 };
3326
ShaderStorageBufferLayoutBindingCase(Context & context,const char * name,const char * description,StageType stage,LayoutBindingParameters & samplerType,glu::GLSLVersion glslVersion)3327 ShaderStorageBufferLayoutBindingCase::ShaderStorageBufferLayoutBindingCase(Context& context, const char* name,
3328 const char* description, StageType stage,
3329 LayoutBindingParameters& samplerType,
3330 glu::GLSLVersion glslVersion)
3331 : LayoutBindingBaseCase(context, name, description, stage, samplerType, glslVersion), m_buffername(0)
3332 {
3333 }
3334
~ShaderStorageBufferLayoutBindingCase()3335 ShaderStorageBufferLayoutBindingCase::~ShaderStorageBufferLayoutBindingCase()
3336 {
3337 }
3338
3339 //*****************************************************************************
3340
LayoutBindingTests(Context & context,glu::GLSLVersion glslVersion)3341 LayoutBindingTests::LayoutBindingTests(Context& context, glu::GLSLVersion glslVersion)
3342 : TestCaseGroup(context, "layout_binding", "Layout Binding LayoutBindingSubTest"), m_glslVersion(glslVersion)
3343 {
3344 }
3345
~LayoutBindingTests(void)3346 LayoutBindingTests::~LayoutBindingTests(void)
3347 {
3348 }
3349
3350 StageType LayoutBindingTests::stageTypes[] = {
3351 { "ComputeShader", ComputeShader },
3352 { "FragmentShader", FragmentShader },
3353 { "VertexShader", VertexShader },
3354 };
3355
3356 // uniform_type must match vector_type, i.e. isampler2D=>ivec4
3357 LayoutBindingParameters LayoutBindingTests::test_args[] = {
3358 { "uniform", Texture, TwoD, "vec4", "sampler2D", "vec2", "texture" },
3359 { "uniform", Texture, ThreeD, "vec4", "sampler3D", "vec3", "texture" },
3360 { "uniform", Texture, TwoDArray, "vec4", "sampler2DArray", "vec3", "texture" },
3361 { "uniform", Image, TwoD, "vec4", "image2D", "ivec2", "imageLoad" },
3362 { "uniform", AtomicCounter, TwoD, "vec4", "atomic_uint", "vec3", "atomic" },
3363 { "uniform", UniformBlock, None, "vec4", "block", "vec3", "block" },
3364 { "buffer", ShaderStorageBuffer, None, "vec4", "buffer", "vec3", "atomicAdd" },
3365 };
3366
3367 // create test name which must be unique or dEQP framework will throw
3368 // example: sampler2D_layout_binding_vec4_texture_0
createTestName(const StageType & stageType,const LayoutBindingParameters & testArgs)3369 String LayoutBindingTests::createTestName(const StageType& stageType, const LayoutBindingParameters& testArgs)
3370 {
3371 StringStream s;
3372 s << testArgs.uniform_type;
3373 s << "_layout_binding_";
3374 s << testArgs.access_function << "_";
3375 s << stageType.name;
3376 return s.str();
3377 }
3378
init(void)3379 void LayoutBindingTests::init(void)
3380 {
3381 std::vector<StageType> stages = makeVector(stageTypes);
3382 std::vector<LayoutBindingParameters> samplers = makeVector(test_args);
3383 for (std::vector<StageType>::iterator stagesIter = stages.begin(); stagesIter != stages.end(); stagesIter++)
3384 {
3385 for (std::vector<LayoutBindingParameters>::iterator testArgsIter = samplers.begin();
3386 testArgsIter != samplers.end(); testArgsIter++)
3387 {
3388 String testName = createTestName(*stagesIter, *testArgsIter);
3389 switch ((*testArgsIter).surface_type)
3390 {
3391 case Texture:
3392 addChild(new SamplerLayoutBindingCase(m_context, testName.c_str(),
3393 "test sampler layout binding functionality", *stagesIter,
3394 *testArgsIter, m_glslVersion));
3395 break;
3396 case Image:
3397 addChild(new ImageLayoutBindingCase(m_context, testName.c_str(),
3398 "test image layout binding functionality", *stagesIter,
3399 *testArgsIter, m_glslVersion));
3400 break;
3401 case AtomicCounter:
3402 addChild(new AtomicCounterLayoutBindingCase(m_context, testName.c_str(),
3403 "test atomic counters layout binding functionality",
3404 *stagesIter, *testArgsIter, m_glslVersion));
3405 break;
3406 case UniformBlock:
3407 addChild(new UniformBlocksLayoutBindingCase(m_context, testName.c_str(),
3408 "test uniform block layout binding functionality",
3409 *stagesIter, *testArgsIter, m_glslVersion));
3410 break;
3411 case ShaderStorageBuffer:
3412 addChild(new ShaderStorageBufferLayoutBindingCase(
3413 m_context, testName.c_str(), "test shader storage buffer layout binding functionality", *stagesIter,
3414 *testArgsIter, m_glslVersion));
3415 break;
3416 default:
3417 DE_ASSERT(0);
3418 break;
3419 }
3420 }
3421 }
3422 }
3423
3424 } // glcts
3425