• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &param, 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 											  &param, 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, &param, 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, &param, 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, &param, 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