148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos/*-------------------------------------------------------------------------
248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * OpenGL Conformance Test Suite
348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * -----------------------------
448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos *
548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * Copyright (c) 2014-2016 The Khronos Group Inc.
648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos *
748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * Licensed under the Apache License, Version 2.0 (the "License");
848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * you may not use this file except in compliance with the License.
948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * You may obtain a copy of the License at
1048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos *
1148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos *      http://www.apache.org/licenses/LICENSE-2.0
1248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos *
1348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * Unless required by applicable law or agreed to in writing, software
1448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * distributed under the License is distributed on an "AS IS" BASIS,
1548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * See the License for the specific language governing permissions and
1748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * limitations under the License.
1848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos *
1984322c9402f810da3cd80b52e9f9ef72150a9004Alexander Galazin */ /*!
2048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * \file
2148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos * \brief
2284322c9402f810da3cd80b52e9f9ef72150a9004Alexander Galazin */ /*-------------------------------------------------------------------*/
2348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "es31cLayoutBindingTests.hpp"
2448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
2548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "tcuRenderTarget.hpp"
2648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "tcuStringTemplate.hpp"
2748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "tcuSurface.hpp"
2848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "tcuTestLog.hpp"
2948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "tcuTexture.hpp"
3048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "tcuTextureUtil.hpp"
3148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
3248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "deRandom.hpp"
3348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "deStringUtil.hpp"
3448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
3548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "glwDefs.hpp"
3648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "glwEnums.hpp"
3748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "glwFunctions.hpp"
3848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
3948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "gluDrawUtil.hpp"
4048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "gluPixelTransfer.hpp"
4148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "gluShaderProgram.hpp"
4248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "gluTexture.hpp"
4348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos#include "gluTextureUtil.hpp"
4448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
4548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosnamespace glcts
4648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
4748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
4848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos//=========================================================================
4948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos//= typedefs
5048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos//=========================================================================
5148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulostypedef std::string String;
5248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulostypedef std::map<String, String>		 StringMap;
5348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulostypedef std::map<String, glw::GLint>	 StringIntMap;
5448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulostypedef std::map<glw::GLint, glw::GLint> IntIntMap;
5548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulostypedef std::vector<String> StringVector;
5648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulostypedef std::vector<int>	IntVector;
5748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
5848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulostypedef std::map<int, glu::Texture2D*>		Texture2DMap;
5948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulostypedef std::map<int, glu::Texture2DArray*> Texture2DArrayMap;
6048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulostypedef std::map<int, glu::Texture3D*>		Texture3DMap;
6148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
6248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos//=========================================================================
6348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos//= utility classes
6448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos//=========================================================================
6548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
6648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos//= string stream that saves some typing
6748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass StringStream : public std::ostringstream
6848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
6948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
7048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void reset()
7148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
7248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		clear();
7348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		str("");
7448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
7548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
7648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
7748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass LayoutBindingProgram;
7848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
7948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass IProgramContextSupplier
8048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
8148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
8248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual ~IProgramContextSupplier()
8348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
8448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
8548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual Context&					   getContext()		   = 0;
8648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual const LayoutBindingParameters& getTestParameters() = 0;
8748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual eStageType					   getStage()		   = 0;
8848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual const String& getSource(eStageType stage)		   = 0;
8948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual LayoutBindingProgram* createProgram()			   = 0;
9048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
9148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
9248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass LayoutBindingProgram
9348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
9448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
9548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	LayoutBindingProgram(IProgramContextSupplier& contextSupplier)
9648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		: m_contextSupplier(contextSupplier)
9748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		, m_context(contextSupplier.getContext().getRenderContext())
9848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		, m_stage(contextSupplier.getStage())
9948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		, m_testParams(contextSupplier.getTestParameters())
10048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		, m_gl(contextSupplier.getContext().getRenderContext().getFunctions())
10148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
10248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (getStage() != ComputeShader)
10348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			m_program = new glu::ShaderProgram(
10448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				m_context, glu::makeVtxFragSources(m_contextSupplier.getSource(VertexShader).c_str(),
10548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos												   m_contextSupplier.getSource(FragmentShader).c_str()));
10648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else
107f1f97c069517c894a72fcc720da5e5bb5eb7226bAlexander Galazin			m_program = new glu::ShaderProgram(
108f1f97c069517c894a72fcc720da5e5bb5eb7226bAlexander Galazin				m_context,
109f1f97c069517c894a72fcc720da5e5bb5eb7226bAlexander Galazin				glu::ProgramSources() << glu::ComputeSource(m_contextSupplier.getSource(ComputeShader).c_str()));
11048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
11148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual ~LayoutBindingProgram()
11248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
11348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		delete m_program;
11448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
11548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
11648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	class LayoutBindingProgramAutoPtr
11748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
11848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	public:
11948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		LayoutBindingProgramAutoPtr(IProgramContextSupplier& contextSupplier)
12048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
12148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			m_program = contextSupplier.createProgram();
12248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
12348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		~LayoutBindingProgramAutoPtr()
12448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
12548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			delete m_program;
12648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
12748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		LayoutBindingProgram* operator->()
12848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
12948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return m_program;
13048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
13148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
13248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	private:
13348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		LayoutBindingProgram* m_program;
13448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	};
13548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
13648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	String getErrorLog(bool dumpShaders = false)
13748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
13848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringStream errLog;
13948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
14048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (getStage() != ComputeShader)
14148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
14248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			const glu::ShaderInfo& fragmentShaderInfo = m_program->getShaderInfo(glu::SHADERTYPE_FRAGMENT);
14348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			const glu::ShaderInfo& vertexShaderInfo   = m_program->getShaderInfo(glu::SHADERTYPE_VERTEX);
14448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
14548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (!fragmentShaderInfo.compileOk || !m_program->getProgramInfo().linkOk || dumpShaders)
14648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
14748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				errLog << "### dump of " << stageToName(FragmentShader) << "###\n";
14848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				String msg((dumpShaders ? "Fragment shader should not have compiled" :
14948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos										  "Vertex shader compile failed while testing "));
15048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				errLog << "Fragment shader compile failed while testing " << stageToName(getStage()) << ": "
15148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					   << fragmentShaderInfo.infoLog << "\n";
15248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				errLog << m_contextSupplier.getSource(FragmentShader);
15348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
15448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (!vertexShaderInfo.compileOk || !m_program->getProgramInfo().linkOk || dumpShaders)
15548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
15648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				errLog << "### dump of " << stageToName(VertexShader) << "###\n";
15748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				String msg((dumpShaders ? "Vertex shader should not have compiled" :
15848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos										  "Vertex shader compile failed while testing "));
15948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				errLog << msg << stageToName(getStage()) << ": " << vertexShaderInfo.infoLog << "\n";
16048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				errLog << m_contextSupplier.getSource(VertexShader);
16148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
16248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
16348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else
16448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
16548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			const glu::ShaderInfo& computeShaderInfo = m_program->getShaderInfo(glu::SHADERTYPE_COMPUTE);
16648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
16748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (!computeShaderInfo.compileOk || !m_program->getProgramInfo().linkOk || dumpShaders)
16848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
16948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				errLog << "### dump of " << stageToName(ComputeShader) << "###\n";
17048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				String msg((dumpShaders ? "Compute shader should not have compiled" :
17148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos										  "Compute shader compile failed while testing "));
17248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				errLog << msg << stageToName(ComputeShader) << ": " << computeShaderInfo.infoLog << "\n";
17348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				errLog << m_contextSupplier.getSource(ComputeShader);
17448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
17548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
17648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!m_program->getProgramInfo().linkOk)
17748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
17848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			getStage();
17948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			errLog << "Linking failed while testing " << stageToName(getStage()) << ": "
18048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				   << m_program->getProgramInfo().infoLog << "\n";
18148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			errLog << "### other stages ###\n";
18248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			switch (getStage())
18348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
18448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			case FragmentShader:
18548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				errLog << "### dump of " << stageToName(VertexShader) << "###\n";
18648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				errLog << m_contextSupplier.getSource(VertexShader);
18748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				break;
18848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			case VertexShader:
18948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				errLog << "### dump of " << stageToName(FragmentShader) << "###\n";
19048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				errLog << stageToName(FragmentShader) << "\n";
19148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				errLog << m_contextSupplier.getSource(FragmentShader);
19248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				break;
19348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			case ComputeShader:
19448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				errLog << "### dump of " << stageToName(ComputeShader) << "###\n";
19548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				errLog << stageToName(ComputeShader) << "\n";
19648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				errLog << m_contextSupplier.getSource(ComputeShader);
19748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				break;
19848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			default:
19948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				DE_ASSERT(0);
20048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				break;
20148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
20248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
20348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return errLog.str();
20448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
20548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
20648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
20748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	IProgramContextSupplier& m_contextSupplier;
20848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
20948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	const glu::RenderContext&	  m_context;
21048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	const eStageType			   m_stage;		 // shader stage currently tested
21148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	const LayoutBindingParameters& m_testParams; // parameters for shader generation (table at end of file)
21248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	const glw::Functions&		   m_gl;
21348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
21448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	glu::ShaderProgram* m_program;
21548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
21648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
21748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	StringIntMap getUniformLocations(StringVector args) const
21848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
21948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringVector::iterator it;
22048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringIntMap		   locations;
22148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		bool				   passed = true;
22248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
22348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (it = args.begin(); it != args.end(); it++)
22448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
22548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			const char* name	 = (*it).c_str();
22648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glw::GLint  location = m_gl.getUniformLocation(getProgram(), name);
22748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			passed &= (0 <= location);
22848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (passed)
22948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
23048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				locations[name] = location;
23148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
23248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
23348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
23448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return locations;
23548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
23648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
23748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
23848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	glw::GLint getProgram() const
23948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
24048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return m_program->getProgram();
24148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
24248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
24348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	const glw::Functions& gl() const
24448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
24548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return m_gl;
24648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
24748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
24848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual eStageType getStage() const
24948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
25048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return m_stage;
25148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
25248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
25348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	String stageToName(eStageType stage) const
25448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
25548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		switch (stage)
25648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
25748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case FragmentShader:
25848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return "FragmentShader";
25948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case VertexShader:
26048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return "VertexShader";
26148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case ComputeShader:
26248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return "ComputeShader";
26348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		default:
26448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			DE_ASSERT(0);
26548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
26648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
26748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return String();
26848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
26948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
27048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool error() const
27148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
27248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return (m_gl.getError() == GL_NO_ERROR);
27348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
27448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
27548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool compiledAndLinked() const
27648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
27748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (getStage() != ComputeShader)
27848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return m_program->getShaderInfo(glu::SHADERTYPE_FRAGMENT).compileOk &&
27948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				   m_program->getShaderInfo(glu::SHADERTYPE_FRAGMENT).compileOk && m_program->getProgramInfo().linkOk;
28048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
28148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return m_program->getShaderInfo(glu::SHADERTYPE_COMPUTE).compileOk && m_program->getProgramInfo().linkOk;
28248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
28348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
28448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual StringIntMap getBindingPoints(StringVector args) const
28548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
28648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringIntMap bindingPoints;
28748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
28848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringIntMap locations = getUniformLocations(args);
28948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!locations.empty())
29048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
29148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glw::GLint bindingPoint;
29248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (StringIntMap::iterator it = locations.begin(); it != locations.end(); it++)
29348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
29448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				glw::GLint location = it->second;
29548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				m_gl.getUniformiv(getProgram(), location, &bindingPoint);
29648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				bool hasNoError = (GL_NO_ERROR == m_gl.getError());
29748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (hasNoError)
29848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
29948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					bindingPoints[it->first] = bindingPoint;
30048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
30148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
30248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
30348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return bindingPoints;
30448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
30548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
30648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual bool setBindingPoints(StringVector list, glw::GLint bindingPoint) const
30748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
30848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		bool bNoError = true;
30948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
31048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringIntMap locations = getUniformLocations(list);
31148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!locations.empty())
31248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
31348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (StringIntMap::iterator it = locations.begin(); it != locations.end(); it++)
31448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
31548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				m_gl.uniform1i(it->second, bindingPoint);
31648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				bNoError &= (GL_NO_ERROR == m_gl.getError());
31748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
31848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
31948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return bNoError;
32048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
32148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
32248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual StringIntMap getOffsets(StringVector /*args*/) const
32348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
32448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return StringIntMap();
32548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
32648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
32748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
32848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass LayoutBindingTestResult
32948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
33048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
33148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	LayoutBindingTestResult(bool passed = true, const String& reason = String(), bool notRunforThisContext = false)
33248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		: m_passed(passed), m_notRunForThisContext(notRunforThisContext), m_reason(reason)
33348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
33448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
33548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
33648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
33748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool testPassed() const
33848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
33948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return m_passed;
34048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
34148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
34248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	String getReason() const
34348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
34448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return m_reason;
34548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
34648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
34748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool runForThisContext() const
34848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
34948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return !m_notRunForThisContext;
35048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
35148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
35248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
35348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool   m_passed;
35448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool   m_notRunForThisContext;
35548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	String m_reason;
35648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
35748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
35848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass IntegerConstant
35948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
36048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
36148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	enum Literals
36248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
36348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		decimal = 0,
36448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		decimal_u,
36548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		decimal_U,
36648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		octal,
36748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		octal_u,
36848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		octal_U,
36948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		hex_x,
37048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		hex_X,
37148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		hex_u,
37248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		hex_u_X,
37348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		hex_U,
37448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		hex_U_X,
37548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		last
37648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	};
37748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
37848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
37948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	IntegerConstant(Literals lit, int ai) : asInt(ai)
38048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
38148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringStream s;
38248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		switch (lit)
38348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
38448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case decimal:
38548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << asInt;
38648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
38748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case decimal_u:
38848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << asInt << "u";
38948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
39048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case decimal_U:
39148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << asInt << "U";
39248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
39348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case octal:
39448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "0" << std::oct << asInt;
39548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
39648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case octal_u:
39748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "0" << std::oct << asInt << "u";
39848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
39948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case octal_U:
40048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "0" << std::oct << asInt << "U";
40148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
40248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case hex_x:
40348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "0x" << std::hex << asInt;
40448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
40548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case hex_X:
40648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "0X" << std::hex << asInt;
40748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
40848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case hex_u:
40948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "0x" << std::hex << asInt << "u";
41048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
41148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case hex_u_X:
41248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "0X" << std::hex << asInt << "u";
41348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
41448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case hex_U:
41548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "0x" << std::hex << asInt << "U";
41648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
41748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case hex_U_X:
41848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "0X" << std::hex << asInt << "U";
41948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
42048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case last:
42148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		default:
42248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			DE_ASSERT(0);
42348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
42448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
42548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		asString = s.str();
42648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
42748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
42848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
42948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	String asString;
43048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	int	asInt;
43148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
43248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
43348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos//*****************************************************************************
43448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass LayoutBindingBaseCase : public TestCase, public IProgramContextSupplier
43548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
43648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
43748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	LayoutBindingBaseCase(Context& context, const char* name, const char* description, StageType stage,
43848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						  LayoutBindingParameters& samplerType, glu::GLSLVersion glslVersion);
43948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual ~LayoutBindingBaseCase(void);
44048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
44148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	IterateResult iterate(void);
44248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
44348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	// overrideable subtests
44448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual LayoutBindingTestResult binding_basic_default(void);
44548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual LayoutBindingTestResult binding_basic_explicit(void);
44648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual LayoutBindingTestResult binding_basic_multiple(void);
44748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual LayoutBindingTestResult binding_basic_render(void);
44848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual LayoutBindingTestResult binding_integer_constant(void);
44948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual LayoutBindingTestResult binding_integer_constant_expression(void);
45048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual LayoutBindingTestResult binding_array_size(void);
45148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual LayoutBindingTestResult binding_array_implicit(void);
45248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual LayoutBindingTestResult binding_array_multiple(void);
45348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual LayoutBindingTestResult binding_api_update(void);
45448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual LayoutBindingTestResult binding_compilation_errors(void);
45548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual LayoutBindingTestResult binding_link_errors(void);
45648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual LayoutBindingTestResult binding_examples(void);
45748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual LayoutBindingTestResult binding_mixed_order(void);
45848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
45948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
46048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	// drawTest normal vs. compute
46148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	typedef LayoutBindingTestResult (LayoutBindingBaseCase::*LayoutBindingDrawTestPtr)(glw::GLint program, int binding);
46248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
46348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	LayoutBindingDrawTestPtr m_drawTest;
46448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
46548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	// pointer type for subtests
46648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	typedef LayoutBindingTestResult (LayoutBindingBaseCase::*LayoutBindingSubTestPtr)();
46748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
46848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	// test table entry
46948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	struct LayoutBindingSubTest
47048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
47148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		char const*				name;
47248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		char const*				description;
47348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		LayoutBindingSubTestPtr test;
47448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	};
47548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
47648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	// IProgramContextSupplier interface
47748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprotected:
47848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	const LayoutBindingParameters& getTestParameters()
47948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
48048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return m_testParams;
48148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
48248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
48348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	const glu::RenderContext& getRenderContext()
48448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
48548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return m_context.getRenderContext();
48648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
48748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
48848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual eStageType getStage()
48948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
49048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return m_stage.type;
49148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
49248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
49348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	const String& getSource(eStageType stage)
49448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
49548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return m_sources[stage];
49648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
49748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
49848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	Context& getContext()
49948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
50048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return m_context;
50148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
50248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
50348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	const glw::Functions& gl()
50448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
50548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return m_context.getRenderContext().getFunctions();
50648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
50748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
50848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool needsPrecision() const
50948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
51048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (isContextTypeES(m_context.getRenderContext().getType()) || m_glslVersion == glu::GLSL_VERSION_450)
51148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
51248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return (m_testParams.surface_type != UniformBlock) && (m_testParams.surface_type != ShaderStorageBuffer);
51348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
51448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else
51548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
51648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return (m_testParams.surface_type != UniformBlock) && (m_testParams.surface_type != ShaderStorageBuffer) &&
51748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				   (m_testParams.surface_type != AtomicCounter) && (m_testParams.surface_type != Image);
51848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
51948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
52048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
52148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprotected:
52248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	std::vector<int> makeSparseRange(int maxElement, int minElement = 0) const
52348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
52448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		static float	   rangeT[]		 = { 0.0f, 0.1f, 0.5f, 0.6f, 0.9f, 1.0f };
52548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<float> rangeTemplate = makeVector(rangeT);
52648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		float			   max			 = rangeTemplate.back();
52748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		float			   range		 = (float)((maxElement - 1) - minElement);
52848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
52948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<int> result;
53048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (std::vector<float>::iterator it = rangeTemplate.begin(); it != rangeTemplate.end(); it++)
53148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
53248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			float e = *it;
53348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			e		= (e * range) / max;
53448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			result.insert(result.end(), minElement + (int)e);
53548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
53648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return result;
53748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
53848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
53948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	glu::GLSLVersion getGLSLVersion()
54048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
54148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return m_glslVersion;
54248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
54348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
54448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool isStage(eStageType stage)
54548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
54648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return (stage == m_stage.type);
54748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
54848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
54948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void setTemplateParam(eStageType stage, const char* param, const String& value)
55048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
55148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		m_templateParams[stage][param] = value.c_str();
55248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
55348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
55448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void setTemplateParam(const char* param, const String& value)
55548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
55648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		setTemplateParam(m_stage.type, param, value);
55748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
55848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
55948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void updateTemplate(eStageType stage)
56048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
56148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		m_sources[stage] = tcu::StringTemplate(m_templates[stage]).specialize(m_templateParams[stage]);
56248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
56348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
56448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void updateTemplate()
56548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
56648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		updateTemplate(m_stage.type);
56748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
56848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
56948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	template <class T0, class T1>
57048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	String generateLog(const String& msg, T0 result, T1 expected)
57148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
57248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringStream s;
57348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << msg << " expected: " << expected << " actual: " << result << "\n";
57448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << getSource(VertexShader) << "\n";
57548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << getSource(FragmentShader) << "\n";
57648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return s.str();
57748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
57848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
57948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
58048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	std::vector<LayoutBindingSubTest> m_tests;
58148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
58248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void init(void)
58348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
58448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		m_drawTest =
58548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			(getStage() == ComputeShader) ? &LayoutBindingBaseCase::drawTestCompute : &LayoutBindingBaseCase::drawTest;
58648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
587e44185d03e3c8d5d2944a35f0115c8dd8ebbb186Alexander Galazin#define MAKE_TEST_ENTRY(__subtest_name__) { #__subtest_name__, "", &LayoutBindingBaseCase::__subtest_name__ }
58848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		LayoutBindingSubTest tests[] = {
58948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			MAKE_TEST_ENTRY(binding_basic_default),		 MAKE_TEST_ENTRY(binding_basic_explicit),
59048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			MAKE_TEST_ENTRY(binding_basic_multiple),	 MAKE_TEST_ENTRY(binding_basic_render),
59148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			MAKE_TEST_ENTRY(binding_integer_constant),   MAKE_TEST_ENTRY(binding_integer_constant_expression),
59248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			MAKE_TEST_ENTRY(binding_array_size),		 MAKE_TEST_ENTRY(binding_array_implicit),
59348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			MAKE_TEST_ENTRY(binding_array_multiple),	 MAKE_TEST_ENTRY(binding_api_update),
59448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			MAKE_TEST_ENTRY(binding_compilation_errors), MAKE_TEST_ENTRY(binding_link_errors),
59548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			MAKE_TEST_ENTRY(binding_examples),			 MAKE_TEST_ENTRY(binding_mixed_order)
59648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		};
59748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		m_tests = makeVector(tests);
59848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
59948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		m_uniformDeclTemplate = "${LAYOUT}${KEYWORD}${UNIFORM_TYPE}${UNIFORM_BLOCK_NAME}${UNIFORM_BLOCK}${UNIFORM_"
60048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								"INSTANCE_NAME}${UNIFORM_ARRAY};\n";
60148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
60248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		m_expectedColor = tcu::Vec4(0.0, 1.0f, 0.0f, 1.0f);
60348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
60448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		switch (getTestParameters().texture_type)
60548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
60648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case TwoD:
60748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
60848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			// 2D
60948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glu::ImmutableTexture2D* texture2D =
61048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				new glu::ImmutableTexture2D(getContext().getRenderContext(), GL_RGBA8, 2, 2);
61148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
61248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			texture2D->getRefTexture().allocLevel(0);
61348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			tcu::clear(texture2D->getRefTexture().getLevel(0), m_expectedColor);
61448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			texture2D->upload();
61548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
61648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (m_textures2D.find(0) != m_textures2D.end())
61748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
61848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				delete m_textures2D[0];
61948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
62048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
62148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			m_textures2D[0] = texture2D;
62248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
62348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		break;
62448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case TwoDArray:
62548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
62648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			// 2DArray
62748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glu::Texture2DArray* texture2DArray =
62848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				new glu::Texture2DArray(getContext().getRenderContext(), GL_RGBA8, 2, 2, 1);
62948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
63048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			texture2DArray->getRefTexture().allocLevel(0);
63148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			tcu::clear(texture2DArray->getRefTexture().getLevel(0), m_expectedColor);
63248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			texture2DArray->upload();
63348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
63448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (m_textures2DArray.find(0) != m_textures2DArray.end())
63548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
63648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				delete m_textures2DArray[0];
63748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
63848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
63948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			m_textures2DArray[0] = texture2DArray;
64048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
64148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		break;
64248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// 3D
64348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case ThreeD:
64448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
64548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			glu::Texture3D* texture3D = new glu::Texture3D(getContext().getRenderContext(), GL_RGBA8, 2, 2, 1);
64648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
64748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			texture3D->getRefTexture().allocLevel(0);
64848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			tcu::clear(texture3D->getRefTexture().getLevel(0), m_expectedColor);
64948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			texture3D->upload();
65048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
65148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (m_textures3D.find(0) != m_textures3D.end())
65248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
65348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				delete m_textures3D[0];
65448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
65548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
65648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			m_textures3D[0] = texture3D;
65748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
65848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		break;
65948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case None:
66048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			// test case where no texture allocation is needed
66148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
66248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		default:
66348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			DE_ASSERT(0);
66448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
66548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
66648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
66748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
66848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	String initDefaultVSContext()
66948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
67048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		m_templates[VertexShader] = "${VERSION}"
67148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									"layout(location=0) in vec2 inPosition;\n"
67248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									"${UNIFORM_DECL}\n"
67348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									"flat out ${OUT_VAR_TYPE} fragColor;\n"
67448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									"${OPTIONAL_FUNCTION_BLOCK}\n"
67548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									"void main(void)\n"
67648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									"{\n"
67748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									"  ${OUT_ASSIGNMENT} ${UNIFORM_ACCESS}\n"
67848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									"  gl_Position = vec4(inPosition, 0.0, 1.0);\n"
67948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									"}\n";
68048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
68148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringMap& args = m_templateParams[VertexShader];
68248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// some samplers and all images don't have default precision qualifier (sampler3D)
68348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// so append a precision default in all sampler and image cases.
68448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringStream s;
68548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << glu::getGLSLVersionDeclaration(m_glslVersion) << "\n";
68648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << "precision highp float;\n";
68748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (needsPrecision())
68848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
68948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "precision highp " << getTestParameters().uniform_type << ";\n";
69048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
69148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
69248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		args["VERSION"]					= s.str();
69348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		args["UNIFORM_DECL"]			= "";
69448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		args["OPTIONAL_FUNCTION_BLOCK"] = "";
69548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		args["UNIFORM_ACCESS"]			= "";
69648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		args["OUT_ASSIGNMENT"]			= "fragColor =";
69748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		args["OUT_VAR_TYPE"]			= getTestParameters().vector_type;
69848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		args["OUT_VAR"]					= "fragColor";
69948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (m_stage.type != VertexShader)
70048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
70148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			args["OUT_ASSIGNMENT"] = "";
70248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
70348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return tcu::StringTemplate(m_templates[VertexShader]).specialize(args);
70448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
70548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
70648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	String initDefaultFSContext()
70748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
70848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// build fragment shader
70948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		m_templates[FragmentShader] = "${VERSION}"
71048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									  "layout(location=0) out ${OUT_VAR_TYPE} ${OUT_VAR};\n"
71148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									  "flat in ${OUT_VAR_TYPE} fragColor;\n"
71248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									  "${UNIFORM_DECL}\n"
71348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									  "${OPTIONAL_FUNCTION_BLOCK}\n"
71448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									  "void main(void)\n"
71548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									  "{\n"
71648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									  "  ${OUT_ASSIGNMENT} ${UNIFORM_ACCESS}\n"
71748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									  "}\n";
71848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
71948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringMap& args = m_templateParams[FragmentShader];
72048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// samplers and images don't have default precision qualifier
72148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringStream s;
72248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << glu::getGLSLVersionDeclaration(m_glslVersion) << "\n";
72348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << "precision highp float;\n";
72448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (needsPrecision())
72548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
72648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "precision highp " << getTestParameters().uniform_type << ";\n";
72748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
72848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		args["VERSION"]					= s.str();
72948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		args["OUT_VAR_TYPE"]			= getTestParameters().vector_type;
73048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		args["UNIFORM_ACCESS"]			= "vec4(0.0,0.0,0.0,0.0);";
73148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		args["UNIFORM_DECL"]			= "";
73248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		args["OPTIONAL_FUNCTION_BLOCK"] = "";
73348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		args["OUT_ASSIGNMENT"]			= "outColor =";
73448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		args["OUT_VAR"]					= "outColor";
73548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// must have a linkage between stage and fragment shader
73648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// that the compiler can't optimize away
73748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (FragmentShader != m_stage.type)
73848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
73948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			args["UNIFORM_ACCESS"] = "fragColor;";
74048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
74148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return tcu::StringTemplate(m_templates[FragmentShader]).specialize(args);
74248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
74348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
74448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	String initDefaultCSContext()
74548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
74648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// build compute shader
74748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		m_templates[ComputeShader] = "${VERSION}"
74848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									 "${UNIFORM_DECL}\n"
74948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									 "${OPTIONAL_FUNCTION_BLOCK}\n"
75048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									 "void main(void)\n"
75148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									 "{\n"
75248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									 "  ${OUT_VAR_TYPE} tmp = ${UNIFORM_ACCESS}\n"
75348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									 "  ${OUT_ASSIGNMENT} tmp ${OUT_END}\n"
75448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									 "}\n";
75548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
75648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringMap& args = m_templateParams[ComputeShader];
75748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// images don't have default precision qualifier
75848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringStream s;
75948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << glu::getGLSLVersionDeclaration(m_glslVersion) << "\n";
76048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << "layout (local_size_x = 1) in;\n"
76148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			 "precision highp float;\n";
76248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (needsPrecision())
76348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
76448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "precision highp " << getTestParameters().uniform_type << ";\n";
76548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
76648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
76748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// bindings are per uniform type...
76848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (getTestParameters().surface_type == Image)
76948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
77048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "layout(binding=0, std430) buffer outData {\n"
77148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				 "    "
77248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			  << getTestParameters().vector_type << " outColor;\n"
77348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos													"};\n";
77448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			args["OUT_ASSIGNMENT"] = "outColor =";
77548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			args["OUT_END"]		   = ";";
77648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
77748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else
77848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
77948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "layout(binding=0, rgba8) uniform highp writeonly image2D outImage;\n";
78048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			args["OUT_ASSIGNMENT"] = "imageStore(outImage, ivec2(0), ";
78148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			args["OUT_END"]		   = ");";
78248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
78348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		args["VERSION"]					= s.str();
78448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		args["OUT_VAR_TYPE"]			= getTestParameters().vector_type;
78548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		args["UNIFORM_ACCESS"]			= "vec4(0.0,0.0,0.0,0.0);";
78648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		args["UNIFORM_DECL"]			= "";
78748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		args["OPTIONAL_FUNCTION_BLOCK"] = "";
78848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
78948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return tcu::StringTemplate(m_templates[ComputeShader]).specialize(args);
79048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
79148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
79248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprotected:
79348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	String buildUniformDecl(const String& keyword, const String& layout, const String& uniform_type,
79448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							const String& uniform_block_name, const String& uniform_block,
79548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							const String& uniform_instance, const String& uniform_array) const
79648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
79748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringMap args;
79848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		setArg(args["LAYOUT"], layout);
79948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		setArg(args["KEYWORD"], keyword);
80048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (uniform_block_name.empty())
80148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setArg(args["UNIFORM_TYPE"], uniform_type);
80248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else
80348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			args["UNIFORM_TYPE"] = "";
80448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!uniform_instance.empty() && !uniform_block_name.empty())
80548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setArg(args["UNIFORM_BLOCK_NAME"], uniform_block_name + "_block");
80648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else
80748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setArg(args["UNIFORM_BLOCK_NAME"], uniform_block_name);
80848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		setArg(args["UNIFORM_BLOCK"], uniform_block);
80948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if ((uniform_block_name.empty() && uniform_block.empty()) || !uniform_array.empty())
81048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			args["UNIFORM_INSTANCE_NAME"] = uniform_instance;
81148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else
81248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			args["UNIFORM_INSTANCE_NAME"] = "";
81348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		args["UNIFORM_ARRAY"]			  = uniform_array;
81448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return tcu::StringTemplate(m_uniformDeclTemplate).specialize(args);
81548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
81648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
81748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual String getDefaultUniformName(int idx = 0)
81848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
81948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringStream s;
82048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << "uniform" << idx;
82148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return s.str();
82248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
82348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
82448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual String buildUniformName(String& var)
82548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
82648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::ostringstream s;
82748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << var;
82848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return s.str();
82948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
83048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
83148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual String buildLayout(const String& binding)
83248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
83348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::ostringstream s;
83448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!binding.empty())
83548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "layout(binding=" << binding << ") ";
83648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return s.str();
83748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
83848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
83948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual String buildLayout(int binding)
84048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
84148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::ostringstream bindingStr;
84248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		bindingStr << binding;
84348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return buildLayout(bindingStr.str());
84448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
84548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
84648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual String buildAccess(const String& var)
84748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
84848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::ostringstream s;
84948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << getTestParameters().access_function << "(" << var << "," << getTestParameters().coord_vector_type << "(0)"
85048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		  << ")";
85148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return s.str();
85248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
85348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
85448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual String buildBlockName(const String& /*name*/)
85548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
85648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return String();
85748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
85848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
85948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual String buildBlock(const String& /*name*/, const String& /*type*/ = String("float"))
86048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
86148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return String();
86248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
86348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
86448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual String buildArray(int idx)
86548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
86648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringStream s;
86748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << "[" << idx << "]";
86848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return s.str();
86948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
87048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
87148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual String buildArrayAccess(int uniform, int idx)
87248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
87348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringStream s;
87448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << getDefaultUniformName(uniform) << buildArray(idx);
87548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!buildBlockName(getDefaultUniformName()).empty())
87648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
87748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "." << getDefaultUniformName(uniform);
87848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
87948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return s.str();
88048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
88148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
88248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	// return max. binding point allowed
88348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual int maxBindings()
88448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
88548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		int units = 0;
88648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
88748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (getTestParameters().surface_type == Image)
88848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
88948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl().getIntegerv(GL_MAX_IMAGE_UNITS, &units);
89048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
89148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else
89248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
89348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl().getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &units);
89448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
89548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
89648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return units;
89748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
89848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
89948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	// return max. array size allowed
90048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual int maxArraySize()
90148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
90248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		int units = 0;
90348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
90448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (getTestParameters().surface_type == Image)
90548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
90648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			switch (m_stage.type)
90748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
90848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			case VertexShader:
90948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				gl().getIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &units);
91048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				break;
91148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			case FragmentShader:
91248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				gl().getIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &units);
91348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				break;
91448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			default:
91548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				DE_ASSERT(0);
91648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				break;
91748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
91848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
91948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else
92048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
92148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			switch (m_stage.type)
92248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
92348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			case VertexShader:
92448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				gl().getIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &units);
92548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				break;
92648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			case FragmentShader:
92748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				gl().getIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &units);
92848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				break;
92948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			default:
93048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				DE_ASSERT(0);
93148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				break;
93248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
93348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
93448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
93548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return units;
93648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
93748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
93848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual bool isSupported()
93948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
94048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return (maxArraySize() > 0);
94148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
94248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
94348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual void bind(int binding)
94448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
94548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glw::GLint texTarget = 0;
94648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glw::GLint texName   = 0;
94748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
94848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		switch (getTestParameters().texture_type)
94948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
95048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case TwoD:
95148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			texTarget = GL_TEXTURE_2D;
95248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			texName   = m_textures2D[0]->getGLTexture();
95348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
95448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case TwoDArray:
95548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			texTarget = GL_TEXTURE_2D_ARRAY;
95648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			texName   = m_textures2DArray[0]->getGLTexture();
95748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
95848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case ThreeD:
95948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			texTarget = GL_TEXTURE_3D;
96048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			texName   = m_textures3D[0]->getGLTexture();
96148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
96248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		default:
96348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			DE_ASSERT(0);
96448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
96548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
96648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
96748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		switch (getTestParameters().surface_type)
96848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
96948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case Texture:
97048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl().activeTexture(GL_TEXTURE0 + binding);
97148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl().bindTexture(texTarget, texName);
97248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl().texParameteri(texTarget, GL_TEXTURE_WRAP_S, glu::getGLWrapMode(tcu::Sampler::CLAMP_TO_EDGE));
97348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl().texParameteri(texTarget, GL_TEXTURE_WRAP_T, glu::getGLWrapMode(tcu::Sampler::CLAMP_TO_EDGE));
97448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl().texParameteri(texTarget, GL_TEXTURE_MIN_FILTER, glu::getGLFilterMode(tcu::Sampler::NEAREST));
97548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl().texParameteri(texTarget, GL_TEXTURE_MAG_FILTER, glu::getGLFilterMode(tcu::Sampler::NEAREST));
97648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
97748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case Image:
97848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl().bindImageTexture(binding, texName, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
97948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
98048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		default:
98148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			DE_ASSERT(0);
98248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
98348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
98448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
98548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
98648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual void unbind(int binding)
98748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
98848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glw::GLint texTarget = 0;
98948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
99048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		switch (getTestParameters().texture_type)
99148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
99248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case TwoD:
99348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			texTarget = GL_TEXTURE_2D;
99448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
99548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case TwoDArray:
99648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			texTarget = GL_TEXTURE_2D_ARRAY;
99748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
99848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case ThreeD:
99948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			texTarget = GL_TEXTURE_3D;
100048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
100148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		default:
100248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			DE_ASSERT(0);
100348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
100448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
100548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
100648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		switch (getTestParameters().surface_type)
100748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
100848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case Texture:
100948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl().activeTexture(GL_TEXTURE0 + binding);
101048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl().bindTexture(texTarget, 0);
101148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
101248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case Image:
101348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl().bindImageTexture(binding, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32F);
101448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
101548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		default:
101648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			DE_ASSERT(0);
101748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
101848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
101948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
102048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
102148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual LayoutBindingTestResult drawTest(glw::GLint program, int binding);
102248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual LayoutBindingTestResult drawTestCompute(glw::GLint program, int binding);
102348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
102448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	// allocate resources needed for all subtests, i.e. textures
102548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual void setupTest()
102648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
102748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
102848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
102948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	// cleanup resources needed for all subtests
103048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual void teardownTest()
103148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
103248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (Texture2DMap::iterator it = m_textures2D.begin(); it != m_textures2D.end(); it++)
103348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
103448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			delete it->second;
103548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
103648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		m_textures2D.clear();
103748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
103848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (Texture2DArrayMap::iterator it = m_textures2DArray.begin(); it != m_textures2DArray.end(); it++)
103948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
104048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			delete it->second;
104148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
104248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		m_textures2DArray.clear();
104348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
104448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (Texture3DMap::iterator it = m_textures3D.begin(); it != m_textures3D.end(); it++)
104548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
104648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			delete it->second;
104748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
104848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		m_textures3D.clear();
104948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
105048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
105148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
105248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	// appends a space to the argument (make shader source pretty)
105348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void setArg(String& arg, const String& value) const
105448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
105548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!value.empty())
105648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			arg = value + String(" ");
105748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else
105848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			arg = String();
105948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
106048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
106148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
106248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	LayoutBindingParameters m_testParams;
106348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	StageType				m_stage;
106448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
106548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	std::map<eStageType, String>	  m_sources;
106648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	std::map<eStageType, StringMap>   m_templateParams;
106748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	std::map<eStageType, const char*> m_templates;
106848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
106948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	Texture2DMap	  m_textures2D;
107048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	Texture2DArrayMap m_textures2DArray;
107148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	Texture3DMap	  m_textures3D;
107248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	tcu::Vec4		  m_expectedColor;
107348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
107448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	const char* m_uniformDeclTemplate;
107548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
107648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	glu::GLSLVersion m_glslVersion;
107748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
107848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
107948087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosLayoutBindingBaseCase::LayoutBindingBaseCase(Context& context, const char* name, const char* description,
108048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos											 StageType stage, LayoutBindingParameters& samplerType,
108148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos											 glu::GLSLVersion glslVersion)
108248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	: TestCase(context, name, description)
108348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	, m_drawTest(DE_NULL)
108448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	, m_testParams(samplerType)
108548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	, m_stage(stage)
108648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	, m_uniformDeclTemplate(DE_NULL)
108748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	, m_glslVersion(glslVersion)
108848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
108948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
109048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
109148087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosLayoutBindingBaseCase::~LayoutBindingBaseCase(void)
109248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
109348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	teardownTest();
109448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
109548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
109648087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosLayoutBindingBaseCase::IterateResult LayoutBindingBaseCase::iterate(void)
109748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
109848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	tcu::TestLog& log	= m_context.getTestContext().getLog();
109948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool		  passed = true;
110048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
110148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	if (!isSupported())
110248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
110348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		log << tcu::TestLog::Section("NotSupported", "");
110448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		log << tcu::TestLog::Message << "This test was not run as minimum requirements were not met."
110548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			<< tcu::TestLog::EndMessage;
110648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		log << tcu::TestLog::EndSection;
110748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		getContext().getTestContext().setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "NotSupported");
110848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return STOP;
110948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
111048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
111148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	// init test case (create shader templates and textures)
111248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	init();
111348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
111448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	// allocate resources for all subtests
111548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	setupTest();
111648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
111748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	for (std::vector<LayoutBindingSubTest>::iterator it = m_tests.begin(); it != m_tests.end(); it++)
111848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
111948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// need to reset templates and their args to a clean state before every
112048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// test to avoid bleeding.
112148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		m_sources[VertexShader]   = initDefaultVSContext();
112248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		m_sources[FragmentShader] = initDefaultFSContext();
112348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		m_sources[ComputeShader]  = initDefaultCSContext();
112448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
112548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		LayoutBindingTestResult result = ((*this).*((*it).test))();
112648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!result.testPassed())
112748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
112848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			log << tcu::TestLog::Section((*it).name, (*it).description);
112948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			log << tcu::TestLog::Message << result.getReason() << tcu::TestLog::EndMessage;
113048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			log << tcu::TestLog::EndSection;
113148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
113248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!result.runForThisContext())
113348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
113448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			log << tcu::TestLog::Section((*it).name, (*it).description);
113548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			log << tcu::TestLog::Message << "This test was not run for this context as it does not apply."
113648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				<< tcu::TestLog::EndMessage;
113748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			log << tcu::TestLog::EndSection;
113848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
113948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		passed &= result.testPassed();
114048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
114148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
114248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	// cleanup resources
114348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	teardownTest();
114448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
114548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*=========================================================================
114648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	 TEST results
114748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	 =========================================================================*/
114848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
114948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	getContext().getTestContext().setTestResult(passed ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
115048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos												passed ? "Pass" : "Fail");
115148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
115248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	return STOP;
115348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
115448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
115548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos/*=========================================================================
115648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos // bind resource to specified binding point and program and
115748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos // dispatch a computation, read back image at (0,0)
115848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos =========================================================================*/
115948087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosLayoutBindingTestResult LayoutBindingBaseCase::drawTestCompute(glw::GLint program, int binding)
116048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
116148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	const glw::Functions& l_gl   = getContext().getRenderContext().getFunctions();
116248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool				  passed = true;
116348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
116448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	DE_TEST_ASSERT(getStage() == ComputeShader);
116548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
116648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	l_gl.useProgram(program);
116748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
116848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	deUint32 fb_or_ssb;
116948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
117048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	if (getTestParameters().surface_type == Image)
117148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
117248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		bind(binding);
117348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
117448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glw::GLfloat buffer[4] = { 0.1f, 0.2f, 0.3f, 0.4f };
117548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		l_gl.genBuffers(1, &fb_or_ssb);
117648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		l_gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, fb_or_ssb);
117748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
117848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		l_gl.bufferData(GL_SHADER_STORAGE_BUFFER, 4 * sizeof(glw::GLfloat), buffer, GL_DYNAMIC_COPY);
117948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
118048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		l_gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, fb_or_ssb);
118148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
118248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		l_gl.dispatchCompute(1, 1, 1);
118348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		l_gl.memoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
118448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
118548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		tcu::Vec4 pixel =
118648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			*(tcu::Vec4*)l_gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 4 * sizeof(glw::GLfloat), GL_MAP_READ_BIT);
118748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		l_gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
118848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
118948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		l_gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
119048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		l_gl.deleteBuffers(1, &fb_or_ssb);
119148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
119248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		unbind(binding);
119348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
119448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		tcu::Vec4 expected(0.0f, 1.0f, 0.0f, 1.0f);
119548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		passed = (pixel == expected);
119648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!passed)
119748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
119848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return LayoutBindingTestResult(passed, generateLog(String("drawTestCompute failed"), expected, pixel));
119948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
120048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
120148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	else
120248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
120348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		deUint32 something = 0x01020304, tex;
120448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
120548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		l_gl.genTextures(1, &tex);
120648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		l_gl.bindTexture(GL_TEXTURE_2D, tex);
120748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		l_gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
120848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		l_gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1);
120948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		l_gl.texSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &something);
121048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
121148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		bind(binding);
121248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
121348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		l_gl.bindImageTexture(0, tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
121448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
121548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		l_gl.dispatchCompute(1, 1, 1);
121648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		l_gl.memoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
121748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
121848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		l_gl.bindImageTexture(0, 0, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
121948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
122048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		l_gl.genFramebuffers(1, &fb_or_ssb);
122148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		l_gl.bindFramebuffer(GL_FRAMEBUFFER, fb_or_ssb);
122248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		l_gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
122348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
122448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		l_gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &something);
122548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
122648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		l_gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
122748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		l_gl.deleteFramebuffers(1, &fb_or_ssb);
122848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		l_gl.deleteTextures(1, &tex);
122948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
123048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		unbind(binding);
123148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
123248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const deUint32 expected = 0xff00ff00;
123348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		passed					= (expected == something);
123448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!passed)
123548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
123648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return LayoutBindingTestResult(
123748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				passed, generateLog(String("drawTestCompute failed"), tcu::RGBA(expected), tcu::RGBA(something)));
123848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
123948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
124048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
124148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	return passed;
124248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
124348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
124448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos/*=========================================================================
124548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos // bind resource to specified binding point and program and
124648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos // return result of comparison of rendered pixel at (0,0) with expected
124748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos =========================================================================*/
124848087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosLayoutBindingTestResult LayoutBindingBaseCase::drawTest(glw::GLint program, int binding)
124948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
125048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	const glw::Functions&	GL			  = getContext().getRenderContext().getFunctions();
125148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	const tcu::RenderTarget& renderTarget = getContext().getRenderContext().getRenderTarget();
125248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	glw::GLuint				 viewportW	= renderTarget.getWidth();
125348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	glw::GLuint				 viewportH	= renderTarget.getHeight();
125448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	tcu::Surface			 renderedFrame(viewportW, viewportH);
125548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool					 passed = true;
125648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
125748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	DE_TEST_ASSERT(getStage() != ComputeShader);
125848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
125948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	GL.viewport(0, 0, viewportW, viewportH);
126048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	GL.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
126148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	GL.clear(GL_COLOR_BUFFER_BIT);
126248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
126348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	static const float position[] = {
126448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		-1.0f, -1.0f, -1.0f, +1.0f, +1.0f, -1.0f, +1.0f, +1.0f,
126548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	};
126648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	static const deUint16 quadIndices[] = { 0, 1, 2, 2, 1, 3 };
126748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
126848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	GL.useProgram(program);
126948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
127048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bind(binding);
127148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
127248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	static const glu::VertexArrayBinding vertexArrays[] = {
127348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		glu::va::Float("inPosition", 2, 4, 0, &position[0]),
127448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	};
127548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	glu::draw(getContext().getRenderContext(), program, DE_LENGTH_OF_ARRAY(vertexArrays), &vertexArrays[0],
127648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			  glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(quadIndices), &quadIndices[0]));
127748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
127848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	glu::readPixels(getContext().getRenderContext(), 0, 0, renderedFrame.getAccess());
127948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
128048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	tcu::RGBA pixel = renderedFrame.getPixel(0, 0);
128148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
128248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	passed = (pixel == tcu::RGBA(m_expectedColor));
128348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
128448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	unbind(binding);
128548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
128648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	if (!passed)
128748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
128848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return LayoutBindingTestResult(passed,
128948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									   generateLog(String("drawTest failed"), m_expectedColor, pixel.getPacked()));
129048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
129148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
129248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	return true;
129348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
129448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
129548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos//== verify that binding point is default w/o layout binding
129648087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosLayoutBindingTestResult LayoutBindingBaseCase::binding_basic_default()
129748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
129848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool passed = true;
129948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
130048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	StringStream s;
130148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	s << buildAccess(getDefaultUniformName()) << ";\n";
130248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	setTemplateParam("UNIFORM_ACCESS", s.str());
130348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
130448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	String decl = buildUniformDecl(String(getTestParameters().keyword), buildLayout(String()),
130548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								   String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
130648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								   buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
130748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	setTemplateParam("UNIFORM_DECL", decl);
130848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	updateTemplate();
130948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
131048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
131148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	passed &= program->compiledAndLinked();
131248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	if (!passed)
131348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
131448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return LayoutBindingTestResult(passed, program->getErrorLog());
131548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
131648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
131748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	StringVector  list;
131848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	const String& u = buildBlockName(getDefaultUniformName());
131948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	if (!u.empty())
132048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		list.push_back(u + "_block");
132148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	else
132248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		list.push_back(getDefaultUniformName());
132348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
132448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	StringIntMap bindingPoints = program->getBindingPoints(list);
132548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
132648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	passed &= bindingPoints.size() == list.size() && (bindingPoints[u] == 0);
132748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	if (!passed)
132848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
132948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return LayoutBindingTestResult(passed,
133048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									   generateLog(String("binding point did not match default"), bindingPoints[u], 0));
133148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
133248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
133348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	return true;
133448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
133548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
133648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos//== verify that binding point has specified value
133748087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosLayoutBindingTestResult LayoutBindingBaseCase::binding_basic_explicit()
133848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
133948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool passed = true;
134048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
134148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
134248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringStream s;
134348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << buildAccess(getDefaultUniformName()) << ";\n";
134448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		setTemplateParam("UNIFORM_ACCESS", s.str());
134548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
134648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
134748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	std::vector<int> bindings = makeSparseRange(maxBindings());
134848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	for (std::vector<int>::iterator it = bindings.begin(); it < bindings.end(); it++)
134948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
135048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		int	binding = *it;
135148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		String decl =
135248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			buildUniformDecl(String(getTestParameters().keyword), buildLayout(binding),
135348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
135448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
135548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		setTemplateParam("UNIFORM_DECL", decl);
135648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		updateTemplate();
135748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
135848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
135948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		passed &= program->compiledAndLinked();
136048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!passed)
136148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
136248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return LayoutBindingTestResult(passed, program->getErrorLog());
136348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
136448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
136548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringVector  list;
136648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const String& s = buildBlockName(getDefaultUniformName());
136748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!s.empty())
136848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			list.push_back(s + "_block");
136948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else
137048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			list.push_back(getDefaultUniformName());
137148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
137248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringIntMap bindingPoints = program->getBindingPoints(list);
137348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		passed &= bindingPoints.size() == list.size() && (binding == bindingPoints[list[0]]);
137448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!passed)
137548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
137648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return LayoutBindingTestResult(
137748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				passed, generateLog(String("binding point did not match default"), bindingPoints[list[0]], binding));
137848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
137948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
138048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	return true;
138148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
138248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
138348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos//== verify that binding works with multiple samplers (same binding points)
138448087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosLayoutBindingTestResult LayoutBindingBaseCase::binding_basic_multiple()
138548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
138648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool passed = true;
138748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
138848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	glw::GLint baseBindingPoint = maxBindings() - 1;
138948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
139048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	String decl0 = buildUniformDecl(String(getTestParameters().keyword), buildLayout(baseBindingPoint),
139148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
139248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
139348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	String decl1 = buildUniformDecl(String(getTestParameters().keyword), buildLayout(baseBindingPoint),
139448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName(1)),
139548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos									buildBlock(getDefaultUniformName(1)), getDefaultUniformName(1), String());
139648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	setTemplateParam("UNIFORM_DECL", decl0 + decl1);
139748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
139848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	StringStream s;
139948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	s << buildAccess(getDefaultUniformName()) << " + " << buildAccess(getDefaultUniformName(1)) << ";\n";
140048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	setTemplateParam("UNIFORM_ACCESS", s.str());
140148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	updateTemplate();
140248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
140348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
140448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	passed &= program->compiledAndLinked();
140548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	if (!passed)
140648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
140748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return LayoutBindingTestResult(passed, program->getErrorLog());
140848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
140948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
141048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	StringVector list;
141148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	String		 u = buildBlockName(getDefaultUniformName());
141248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	if (!u.empty())
141348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		list.push_back(u + "_block");
141448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	else
141548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		list.push_back(getDefaultUniformName());
141648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
141748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	u = buildBlockName(getDefaultUniformName(1));
141848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	if (!u.empty())
141948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		list.push_back(u + "_block");
142048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	else
142148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		list.push_back(getDefaultUniformName(1));
142248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
142348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	StringIntMap bindingPoints = program->getBindingPoints(list);
142448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	passed &= (baseBindingPoint == bindingPoints[list[0]]) && (baseBindingPoint == bindingPoints[list[1]]);
142548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	if (!passed)
142648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
142748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		String err;
142848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		err = generateLog(String("binding point did not match default"), bindingPoints[list[0]], baseBindingPoint);
142948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		err += generateLog(String("binding point did not match default"), bindingPoints[list[1]], baseBindingPoint);
143048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return LayoutBindingTestResult(passed, err);
143148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
143248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
143348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	return true;
143448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
143548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
143648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos//== verify that binding point has specified value
143748087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosLayoutBindingTestResult LayoutBindingBaseCase::binding_basic_render()
143848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
143948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool passed = true;
144048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
144148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	StringStream s;
144248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	s << buildAccess(getDefaultUniformName()) << ";\n";
144348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	setTemplateParam("UNIFORM_ACCESS", s.str());
144448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
144548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	std::vector<int> bindings = makeSparseRange(maxBindings());
144648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	for (std::vector<int>::iterator it = bindings.begin(); it < bindings.end(); it++)
144748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
144848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		int	binding = *it;
144948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		String decl =
145048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			buildUniformDecl(String(getTestParameters().keyword), buildLayout(binding),
145148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
145248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
145348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		setTemplateParam("UNIFORM_DECL", decl);
145448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		updateTemplate();
145548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
145648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
145748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		passed &= program->compiledAndLinked();
145848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!passed)
145948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
146048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return LayoutBindingTestResult(passed, program->getErrorLog());
146148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
146248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
146348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		LayoutBindingTestResult drawTestResult = ((*this).*(m_drawTest))(program->getProgram(), binding);
146448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!drawTestResult.testPassed())
146548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
146648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return LayoutBindingTestResult(drawTestResult.testPassed(), drawTestResult.getReason());
146748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
146848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
146948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	return true;
147048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
147148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
147248087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosLayoutBindingTestResult LayoutBindingBaseCase::binding_integer_constant()
147348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
147448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool			 passed   = true;
147548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	std::vector<int> integers = makeSparseRange(maxBindings(), 0);
147648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
147748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	std::vector<IntegerConstant> integerConstants;
147848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	for (int idx = 0; idx < IntegerConstant::last; idx++)
147948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
148048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (IntVector::iterator it = integers.begin(); it != integers.end(); it++)
148148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
148248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			integerConstants.push_back(IntegerConstant((IntegerConstant::Literals)idx, (*it)));
148348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
148448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
148548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
148648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//== verify that binding point can be set with integer constant
148748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	for (std::vector<IntegerConstant>::iterator it = integerConstants.begin(); it != integerConstants.end(); it++)
148848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
148948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		String& intConst = (*it).asString;
149048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
149148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		String decl =
149248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			buildUniformDecl(String(getTestParameters().keyword), buildLayout(intConst),
149348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
149448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
149548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		setTemplateParam("UNIFORM_DECL", decl);
149648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
149748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringStream s;
149848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << buildAccess(getDefaultUniformName()) << ";\n";
149948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		setTemplateParam("UNIFORM_ACCESS", s.str());
150048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		updateTemplate();
150148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
150248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
150348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		passed &= program->compiledAndLinked();
150448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!passed)
150548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
150648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return LayoutBindingTestResult(passed, program->getErrorLog());
150748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
150848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
150948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringVector  list;
151048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const String& u = buildBlockName(getDefaultUniformName());
151148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!u.empty())
151248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			list.push_back(u + "_block");
151348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else
151448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			list.push_back(getDefaultUniformName());
151548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
151648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringIntMap bindingPoints = program->getBindingPoints(list);
151748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		passed &= ((*it).asInt == bindingPoints[list[0]]);
151848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!passed)
151948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
152048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return LayoutBindingTestResult(passed, generateLog(String("binding point did not match default"),
152148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos															   bindingPoints[list[0]], (*it).asInt));
152248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
152348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
152448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
152548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//== verify that binding point can be set with integer constant resulting from a preprocessor substitution
152648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	for (std::vector<IntegerConstant>::iterator it = integerConstants.begin(); it != integerConstants.end(); it++)
152748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
152848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		String& intConst = (*it).asString;
152948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
153048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringStream s;
153148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << "#define INT_CONST " << intConst << std::endl;
153248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
153348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		String decl =
153448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			buildUniformDecl(String(getTestParameters().keyword), buildLayout(String("INT_CONST")),
153548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
153648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
153748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		setTemplateParam("UNIFORM_DECL", s.str() + decl);
153848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
153948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s.reset();
154048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << buildAccess(getDefaultUniformName()) << ";\n";
154148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		setTemplateParam("UNIFORM_ACCESS", s.str());
154248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		updateTemplate();
154348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
154448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
154548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		passed &= program->compiledAndLinked();
154648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!passed)
154748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
154848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return LayoutBindingTestResult(passed, program->getErrorLog());
154948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
155048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
155148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringVector  list;
155248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const String& u = buildBlockName(getDefaultUniformName());
155348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!u.empty())
155448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			list.push_back(u + "_block");
155548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else
155648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			list.push_back(getDefaultUniformName());
155748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
155848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringIntMap bindingPoints = program->getBindingPoints(list);
155948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		passed &= ((*it).asInt == bindingPoints[list[0]]);
156048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!passed)
156148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
156248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return LayoutBindingTestResult(passed, generateLog(String("binding point did not match default"),
156348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos															   bindingPoints[list[0]], (*it).asInt));
156448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
156548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
156648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
156748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	return true;
156848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
156948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
157048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos//== test integer constant expressions
157148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos//== only for GL
157248087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosLayoutBindingTestResult LayoutBindingBaseCase::binding_integer_constant_expression()
157348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
157448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool passed = true;
157548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	if (getGLSLVersion() == glu::GLSL_VERSION_310_ES)
157648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return LayoutBindingTestResult(passed, String(), true);
157748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
157848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	return LayoutBindingTestResult(passed, String(), true);
157948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
158048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
158148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos//== test different sized arrays
158248087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosLayoutBindingTestResult LayoutBindingBaseCase::binding_array_size(void)
158348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
158448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool passed = true;
158548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
158648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	std::vector<int> arraySizes = makeSparseRange(maxArraySize(), 1);
158748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	for (std::vector<int>::iterator it = arraySizes.begin(); it < arraySizes.end(); it++)
158848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
158948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		int	arraySize = *it;
159048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		String decl =
159148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			buildUniformDecl(String(getTestParameters().keyword), buildLayout(maxBindings() - arraySize - 1),
159248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
159348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 buildBlock(getDefaultUniformName()), getDefaultUniformName(), buildArray(arraySize));
159448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		setTemplateParam("UNIFORM_DECL", decl);
159548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
159648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringStream s;
159748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (int idx = 0; idx < arraySize; idx++)
159848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
159948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << (idx ? " + " : "") << buildAccess(buildArrayAccess(0, idx));
160048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
160148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << ";\n";
160248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		setTemplateParam("UNIFORM_ACCESS", s.str());
160348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		updateTemplate();
160448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
160548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
160648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		passed &= program->compiledAndLinked();
160748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!passed)
160848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
160948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return LayoutBindingTestResult(passed, program->getErrorLog());
161048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
161148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
161248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringVector list;
161348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (int idx = 0; idx < arraySize; idx++)
161448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
161548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			std::ostringstream texUnitStr;
161648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			texUnitStr << getDefaultUniformName();
161748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			const String& u = buildBlockName(getDefaultUniformName());
161848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (!u.empty())
161948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				texUnitStr << "_block";
162048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			texUnitStr << buildArray(idx);
162148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			list.push_back(texUnitStr.str());
162248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
162348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
162448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringIntMap bindingPoints = program->getBindingPoints(list);
162548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (int idx = 0; idx < arraySize; idx++)
162648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
162748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			passed &= (((maxBindings() - arraySize - 1) + idx) == bindingPoints[list[idx]]);
162848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (!passed)
162948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
163048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				return LayoutBindingTestResult(passed, generateLog(String("binding point did not match default"),
163148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos																   bindingPoints[list[idx]],
163248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos																   (maxBindings() - arraySize - 1) + idx));
163348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
163448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
163548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
163648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
163748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	return LayoutBindingTestResult(passed, String());
163848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
163948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
164048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos//== verify first element takes binding point specified in binding and
164148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos//== subsequent entries take the next consecutive units
164248087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosLayoutBindingTestResult LayoutBindingBaseCase::binding_array_implicit(void)
164348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
164448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool passed = true;
164548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
164648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	std::vector<int> bindings = makeSparseRange(maxBindings(), 0);
164748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	for (std::vector<int>::iterator it = bindings.begin(); it < bindings.end(); it++)
164848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
164948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		int baseBindingPoint = *it;
165048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		int arraySize		 = std::min(maxBindings() - baseBindingPoint, 4);
165148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
165248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		String decl =
165348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			buildUniformDecl(String(getTestParameters().keyword), buildLayout(baseBindingPoint),
165448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
165548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 buildBlock(getDefaultUniformName()), getDefaultUniformName(), buildArray(arraySize));
165648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		setTemplateParam("UNIFORM_DECL", decl);
165748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
165848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringStream s;
165948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (int idx = 0; idx < arraySize; idx++)
166048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
166148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << (idx ? " + " : "") << buildAccess(buildArrayAccess(0, idx));
166248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
166348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << ";\n";
166448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		setTemplateParam("UNIFORM_ACCESS", s.str());
166548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		updateTemplate();
166648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
166748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
166848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		passed &= program->compiledAndLinked();
166948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!passed)
167048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
167148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return LayoutBindingTestResult(passed, program->getErrorLog());
167248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
167348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringVector list;
167448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (int idx = 0; idx < arraySize; idx++)
167548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
167648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			std::ostringstream texUnitStr;
167748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			texUnitStr << getDefaultUniformName();
167848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			const String& u = buildBlockName(getDefaultUniformName());
167948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (!u.empty())
168048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				texUnitStr << "_block";
168148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			texUnitStr << buildArray(idx);
168248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			list.push_back(texUnitStr.str());
168348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
168448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
168548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringIntMap bindingPoints = program->getBindingPoints(list);
168648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (int idx = 0; idx < arraySize; idx++)
168748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
168848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			passed &= ((baseBindingPoint + idx) == bindingPoints[list[idx]]);
168948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (!passed)
169048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
169148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				return LayoutBindingTestResult(passed, generateLog(String("binding point did not match default"),
169248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos																   bindingPoints[list[idx]], (baseBindingPoint + idx)));
169348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
169448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
169548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
169648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	return LayoutBindingTestResult(passed, String());
169748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
169848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
169948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos//== multiple arrays :verify first element takes binding point specified in binding and
170048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos//== subsequent entries take the next consecutive units
170148087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosLayoutBindingTestResult LayoutBindingBaseCase::binding_array_multiple(void)
170248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
170348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool passed = true;
170448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
170548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	// two arrays, limit max. binding to one
170648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	std::vector<int> bindings = makeSparseRange(maxBindings() - 2, 0);
170748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	for (std::vector<int>::iterator it = bindings.begin(); it < bindings.end(); it++)
170848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
170948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		int baseBindingPoint = *it;
171048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
171148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// total distance from current binding point to end of binding range
171248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// split over two arrays, making sure that the array sizes don't
171348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// exceed max. array sizes per stage
171448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		int arraySize = (maxBindings() - baseBindingPoint - 1) / 2;
171548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		arraySize	 = std::min(arraySize, maxArraySize() / 2);
171648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
171748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringStream s;
171848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		String		 decl =
171948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			buildUniformDecl(String(getTestParameters().keyword), buildLayout(baseBindingPoint),
172048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
172148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 buildBlock(getDefaultUniformName()), getDefaultUniformName(), buildArray(arraySize));
172248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		String another_decl =
172348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			buildUniformDecl(String(getTestParameters().keyword), buildLayout(baseBindingPoint),
172448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName(1)),
172548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 buildBlock(getDefaultUniformName(1)), getDefaultUniformName(1), buildArray(arraySize));
172648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		setTemplateParam("UNIFORM_DECL", decl + another_decl);
172748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
172848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s.reset();
172948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (int uniform = 0; uniform < 2; uniform++)
173048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
173148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (int idx = 0; idx < arraySize; idx++)
173248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
173348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				s << ((idx | uniform) ? " + " : "") << buildAccess(buildArrayAccess(uniform, idx));
173448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
173548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
173648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << ";\n";
173748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		setTemplateParam("UNIFORM_ACCESS", s.str());
173848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		updateTemplate();
173948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
174048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
174148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		passed &= program->compiledAndLinked();
174248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!passed)
174348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
174448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return LayoutBindingTestResult(passed, program->getErrorLog());
174548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
174648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
174748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringVector list;
174848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (int uniform = 0; uniform < 2; uniform++)
174948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
175048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			list.clear();
175148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (int idx = 0; idx < arraySize; idx++)
175248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
175348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				std::ostringstream texUnitStr;
175448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				texUnitStr << getDefaultUniformName(uniform);
175548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				const String& u = buildBlockName(getDefaultUniformName(uniform));
175648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (!u.empty())
175748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					texUnitStr << "_block";
175848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				texUnitStr << buildArray(idx);
175948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				list.push_back(texUnitStr.str());
176048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
176148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
176248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			StringIntMap bindingPoints = program->getBindingPoints(list);
176348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (int idx = 0; idx < arraySize; idx++)
176448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
176548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				passed &= ((baseBindingPoint + idx) == bindingPoints[list[idx]]);
176648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (!passed)
176748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
176848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					return LayoutBindingTestResult(passed,
176948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos												   generateLog(String("binding point did not match default"),
177048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos															   bindingPoints[list[idx]], (baseBindingPoint + idx)));
177148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
177248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
177348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
177448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
177548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	return LayoutBindingTestResult(passed, String());
177648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
177748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
177848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos//== verify that explicit binding point can be changed via API
177948087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosLayoutBindingTestResult LayoutBindingBaseCase::binding_api_update(void)
178048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
178148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool passed = true;
178248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
178348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	String decl = buildUniformDecl(String(getTestParameters().keyword), buildLayout(1),
178448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								   String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
178548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								   buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
178648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	setTemplateParam("UNIFORM_DECL", decl);
178748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
178848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	StringStream s;
178948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	s << buildAccess(getDefaultUniformName()) << ";\n";
179048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	setTemplateParam("UNIFORM_ACCESS", s.str());
179148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	updateTemplate();
179248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
179348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
179448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	passed &= program->compiledAndLinked();
179548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	if (!passed)
179648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
179748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return LayoutBindingTestResult(passed, program->getErrorLog());
179848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
179948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
180048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	StringVector  list;
180148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	const String& u = buildBlockName(getDefaultUniformName());
180248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	if (!u.empty())
180348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		list.push_back(u + "_block");
180448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	else
180548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		list.push_back(getDefaultUniformName());
180648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
180748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	StringIntMap bindingPoints = program->getBindingPoints(list);
180848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
180948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	gl().useProgram(program->getProgram());
181048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	program->setBindingPoints(list, maxBindings() - 1);
181148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	gl().useProgram(0);
181248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
181348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bindingPoints = program->getBindingPoints(list);
181448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
181548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	passed &= bindingPoints[list[0]] == (maxBindings() - 1);
181648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	if (!passed)
181748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
181848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return LayoutBindingTestResult(passed, generateLog(String("binding point did not match default"),
181948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos														   bindingPoints[list[0]], maxBindings() - 1));
182048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
182148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
182248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	return LayoutBindingTestResult(passed, String());
182348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
182448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
182548087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosLayoutBindingTestResult LayoutBindingBaseCase::binding_compilation_errors(void)
182648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
182748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool   passed = true;
182848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	String decl;
182948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
183048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	// verify "uniform float var;" doesn't compile
183148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
183248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringStream s;
183348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << getTestParameters().vector_type << "(0.0);";
183448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
183548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		setTemplateParam("UNIFORM_ACCESS", s.str());
183648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s.reset();
183748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << "layout(binding=0) "
183848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		  << "uniform float tex0;";
183948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		setTemplateParam("UNIFORM_DECL", s.str());
184048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		updateTemplate();
184148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
184248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
184348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		passed &= !program->compiledAndLinked();
184448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!passed)
184548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
184648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return LayoutBindingTestResult(passed, program->getErrorLog(true));
184748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
184848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
184948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
185048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	// verify that non-constant integer expression in binding fails
185148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
185248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		decl = buildUniformDecl(String(getTestParameters().keyword), buildLayout(String("0.0")),
185348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
185448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
185548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		setTemplateParam("UNIFORM_DECL", decl);
185648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		updateTemplate();
185748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
185848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
185948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		passed &= !program->compiledAndLinked();
186048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!passed)
186148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
186248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return LayoutBindingTestResult(passed, program->getErrorLog(true));
186348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
186448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
186548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
186648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
186748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		decl = buildUniformDecl(String(getTestParameters().keyword), buildLayout(String("-1")),
186848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
186948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
187048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		setTemplateParam("UNIFORM_DECL", decl);
187148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		updateTemplate();
187248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
187348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
187448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		passed &= !program->compiledAndLinked();
187548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!passed)
187648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
187748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return LayoutBindingTestResult(passed, program->getErrorLog(true));
187848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
187948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
188048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
188148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		decl = buildUniformDecl(String(getTestParameters().keyword), buildLayout(maxBindings()),
188248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
188348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
188448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		setTemplateParam("UNIFORM_DECL", decl);
188548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		updateTemplate();
188648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
188748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
188848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		passed &= !program->compiledAndLinked();
188948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!passed)
189048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
189148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return LayoutBindingTestResult(passed, program->getErrorLog(true));
189248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
189348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
189448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
189548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		decl = buildUniformDecl(String(getTestParameters().keyword), buildLayout(maxBindings()),
189648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
189748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
189848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		setTemplateParam("UNIFORM_DECL", decl);
189948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
190048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringStream s;
190148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << "vec4(0.0);\n";
190248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		setTemplateParam("UNIFORM_ACCESS", s.str());
190348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		updateTemplate();
190448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
190548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
190648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		passed &= !program->compiledAndLinked();
190748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!passed)
190848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
190948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return LayoutBindingTestResult(passed, program->getErrorLog(true));
191048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
191148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
191248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	return LayoutBindingTestResult(passed, String());
191348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
191448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
191548087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosLayoutBindingTestResult LayoutBindingBaseCase::binding_link_errors(void)
191648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
191748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	bool passed = true;
191848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
191948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	// same sampler with different binding in two compilation units
192048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	if (isStage(VertexShader))
192148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
192248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		String decl =
192348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			buildUniformDecl(String(getTestParameters().keyword), buildLayout(1),
192448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
192548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
192648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		setTemplateParam(VertexShader, "UNIFORM_DECL", decl);
192748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
192848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		setTemplateParam(VertexShader, "OUT_ASSIGNMENT", String("fragColor ="));
192948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
193048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringStream s;
193148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << buildAccess(getDefaultUniformName()) << ";\n";
193248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		setTemplateParam(VertexShader, "UNIFORM_ACCESS", s.str());
193348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		updateTemplate(VertexShader);
193448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
193548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		decl = buildUniformDecl(String(getTestParameters().keyword), buildLayout(3),
193648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
193748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
193848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		setTemplateParam(FragmentShader, "UNIFORM_DECL", decl);
193948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
194048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s.reset();
194148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << "fragColor + " << buildAccess(getDefaultUniformName()) << ";\n";
194248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		setTemplateParam(FragmentShader, "UNIFORM_ACCESS", s.str());
194348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		updateTemplate(FragmentShader);
194448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
194548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
194648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		passed = !program->compiledAndLinked();
194748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!passed)
194848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
194948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return LayoutBindingTestResult(passed, program->getErrorLog(true));
195048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
195148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
195248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
195348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	return LayoutBindingTestResult(passed, String());
195448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
195548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
195648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos// this subtest is generically empty. Overwritten in test cases as needed.
195748087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosLayoutBindingTestResult LayoutBindingBaseCase::binding_examples(void)
195848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
195948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	return true;
196048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
196148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
196248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos// just for image and atomic counter cases
196348087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosLayoutBindingTestResult LayoutBindingBaseCase::binding_mixed_order(void)
196448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
196548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	return true;
196648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
196748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
196848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos//=========================================================================
196948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos// test case Sampler layout binding
197048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos//=========================================================================
197148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass SamplerLayoutBindingCase : public LayoutBindingBaseCase
197248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
197348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
197448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
197548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	SamplerLayoutBindingCase(Context& context, const char* name, const char* description, StageType stage,
197648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos							 LayoutBindingParameters& samplerType, glu::GLSLVersion glslVersion);
197748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	~SamplerLayoutBindingCase(void);
197848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
197948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
198048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
198148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	LayoutBindingProgram* createProgram()
198248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
198348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return new LayoutBindingProgram(*this);
198448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
198548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
198648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
198748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	String getDefaultUniformName(int idx = 0)
198848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
198948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringStream s;
199048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
199148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << "sampler" << idx;
199248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return s.str();
199348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
199448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
199548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
199648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	String buildLayout(const String& binding)
199748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
199848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::ostringstream s;
199948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!binding.empty())
200048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "layout(binding=" << binding << ") ";
200148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return s.str();
200248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
200348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
200448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual int maxBindings()
200548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
200648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		int units = 0;
200748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl().getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &units);
200848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return units;
200948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
201048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
201148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	// return max. array size allowed
201248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	virtual int maxArraySize()
201348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
201448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		int units = 0;
201548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
201648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		switch (getStage())
201748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
201848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case VertexShader:
201948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl().getIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &units);
202048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
202148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case FragmentShader:
202248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl().getIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &units);
202348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
202448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case ComputeShader:
202548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl().getIntegerv(GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &units);
202648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
202748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		default:
202848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			DE_ASSERT(0);
202948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
203048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
203148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
203248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return units;
203348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
203448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
203548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
203648087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosSamplerLayoutBindingCase::SamplerLayoutBindingCase(Context& context, const char* name, const char* description,
203748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos												   StageType stage, LayoutBindingParameters& samplerType,
203848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos												   glu::GLSLVersion glslVersion)
203948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	: LayoutBindingBaseCase(context, name, description, stage, samplerType, glslVersion)
204048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
204148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
204248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
204348087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosSamplerLayoutBindingCase::~SamplerLayoutBindingCase(void)
204448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
204548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
204648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
204748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos//=========================================================================
204848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos// test case Image layout binding
204948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos//=========================================================================
205048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass ImageLayoutBindingCase : public LayoutBindingBaseCase
205148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
205248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
205348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
205448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	ImageLayoutBindingCase(Context& context, const char* name, const char* description, StageType stage,
205548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						   LayoutBindingParameters& samplerType, glu::GLSLVersion glslVersion);
205648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	~ImageLayoutBindingCase(void);
205748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
205848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
205948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	class ImageLayoutBindingProgram : public LayoutBindingProgram
206048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
206148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	public:
206248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ImageLayoutBindingProgram(IProgramContextSupplier& contextSupplier) : LayoutBindingProgram(contextSupplier)
206348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
206448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
206548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	};
206648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
206748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
206848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	// IProgramContextSupplier
206948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
207048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	LayoutBindingProgram* createProgram()
207148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
207248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return new ImageLayoutBindingProgram(*this);
207348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
207448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
207548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
207648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
207748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	String getDefaultUniformName(int idx = 0)
207848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
207948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringStream s;
208048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << "image" << idx;
208148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return s.str();
208248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
208348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
208448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
208548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	String buildLayout(const String& binding)
208648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
208748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::ostringstream s;
208848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!binding.empty())
208948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "layout(binding=" << binding << ", rgba8) readonly ";
209048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else
209148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "layout(rgba8) readonly ";
209248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return s.str();
209348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
209448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
209548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
209648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	int maxBindings()
209748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
209848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		int units = 0;
209948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl().getIntegerv(GL_MAX_IMAGE_UNITS, &units);
210048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return units;
210148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
210248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
210348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
210448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	int maxArraySize()
210548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
210648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		int units = 0;
210748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		switch (getStage())
210848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
210948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case VertexShader:
211048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl().getIntegerv(GL_MAX_VERTEX_IMAGE_UNIFORMS, &units);
211148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
211248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case FragmentShader:
211348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl().getIntegerv(GL_MAX_FRAGMENT_IMAGE_UNIFORMS, &units);
211448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
211548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case ComputeShader:
211648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl().getIntegerv(GL_MAX_COMPUTE_IMAGE_UNIFORMS, &units);
211748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
211848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		default:
211948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			DE_ASSERT(0);
212048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
212148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
212248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return units;
212348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
212448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
212548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
212648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//virtual LayoutBindingTestResult        binding_basic_default               (void);
212748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//virtual LayoutBindingTestResult        binding_basic_explicit              (void);
212848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//virtual LayoutBindingTestResult        binding_basic_multiple              (void);
212948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//virtual LayoutBindingTestResult        binding_basic_render                (void);
213048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//virtual LayoutBindingTestResult        binding_integer_constant            (void);
213148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//virtual LayoutBindingTestResult        binding_integer_constant_expression (void);
213248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//virtual LayoutBindingTestResult        binding_array_size                  (void);
213348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//virtual LayoutBindingTestResult        binding_array_implicit              (void);
213448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//virtual LayoutBindingTestResult        binding_array_multiple              (void);
213548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
213648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	LayoutBindingTestResult binding_api_update(void)
213748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
213848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// only for GL
213948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (getGLSLVersion() == glu::GLSL_VERSION_310_ES)
214048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return LayoutBindingTestResult(true, String(), true);
214148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
214248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return LayoutBindingBaseCase::binding_api_update();
214348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
214448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//virtual LayoutBindingTestResult        binding_compilation_errors          (void);
214548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//virtual LayoutBindingTestResult        binding_link_errors                 (void);
214648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//virtual LayoutBindingTestResult        binding_link_examples               (void);
214748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
214848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	LayoutBindingTestResult binding_mixed_order(void)
214948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
215048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		bool passed = true;
215148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
215248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
215348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			StringStream s;
215448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << buildAccess(getDefaultUniformName()) << ";\n";
215548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setTemplateParam("UNIFORM_ACCESS", s.str());
215648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
215748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			String decl =
215848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				buildUniformDecl(String(getTestParameters().keyword), String("layout(binding=0, rgba8) readonly"),
215948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
216048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
216148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setTemplateParam("UNIFORM_DECL", decl);
216248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			updateTemplate();
216348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
216448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
216548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			passed &= program->compiledAndLinked();
216648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (!passed)
216748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
216848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				return LayoutBindingTestResult(passed, program->getErrorLog());
216948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
217048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
217148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
217248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			String decl =
217348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				buildUniformDecl(String(getTestParameters().keyword), String("layout(r32f, binding=0) readonly"),
217448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
217548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
217648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setTemplateParam("UNIFORM_DECL", decl);
217748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			updateTemplate();
217848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
217948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
218048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			passed &= program->compiledAndLinked();
218148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (!passed)
218248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
218348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				return LayoutBindingTestResult(passed, program->getErrorLog());
218448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
218548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
218648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
218748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return true;
218848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
218948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
219048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
219148087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosImageLayoutBindingCase::ImageLayoutBindingCase(Context& context, const char* name, const char* description,
219248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos											   StageType stage, LayoutBindingParameters& samplerType,
219348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos											   glu::GLSLVersion glslVersion)
219448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	: LayoutBindingBaseCase(context, name, description, stage, samplerType, glslVersion)
219548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
219648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
219748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
219848087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosImageLayoutBindingCase::~ImageLayoutBindingCase(void)
219948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
220048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
220148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
220248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos//=========================================================================
220348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos// test case Atomic counter binding
220448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos//=========================================================================
220548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass AtomicCounterLayoutBindingCase : public LayoutBindingBaseCase
220648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
220748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
220848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
220948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	AtomicCounterLayoutBindingCase(Context& context, const char* name, const char* description, StageType stage,
221048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								   LayoutBindingParameters& samplerType, glu::GLSLVersion glslVersion);
221148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	~AtomicCounterLayoutBindingCase(void)
221248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
221348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
221448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
221548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
221648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	class AtomicCounterLayoutBindingProgram : public LayoutBindingProgram
221748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
221848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	public:
221948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		AtomicCounterLayoutBindingProgram(IProgramContextSupplier& contextSupplier)
222048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			: LayoutBindingProgram(contextSupplier)
222148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
222248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
222348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
222448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	private:
222548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		/*virtual*/
222648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringIntMap getBindingPoints(StringVector args) const
222748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
222848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			StringIntMap bindingPoints;
222948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
223048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (StringVector::iterator it = args.begin(); it != args.end(); it++)
223148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
223248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				glw::GLuint idx = gl().getProgramResourceIndex(getProgram(), GL_UNIFORM, (*it).c_str());
223348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (idx != GL_INVALID_INDEX)
223448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
223548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					glw::GLenum param					  = GL_ATOMIC_COUNTER_BUFFER_INDEX;
223648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					glw::GLint  atomic_counter_buffer_idx = -1;
223748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					gl().getProgramResourceiv(getProgram(), GL_UNIFORM, idx, 1, &param, 1, NULL,
223848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos											  &atomic_counter_buffer_idx);
223948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					bool hasNoError = (GL_NO_ERROR == gl().getError()) && (-1 != atomic_counter_buffer_idx);
224048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					if (!hasNoError)
224148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						continue;
224248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
224348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					param			 = GL_BUFFER_BINDING;
224448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					glw::GLint value = -1;
224548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					gl().getProgramResourceiv(getProgram(), GL_ATOMIC_COUNTER_BUFFER, atomic_counter_buffer_idx, 1,
224648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos											  &param, 1, NULL, &value);
224748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					hasNoError = (GL_NO_ERROR == gl().getError()) && (-1 != value);
224848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					if (!hasNoError)
224948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						continue;
225048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
225148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					bindingPoints[*it] = value;
225248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
225348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
225448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return bindingPoints;
225548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
225648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
225748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		/*virtual*/
225848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringIntMap getOffsets(StringVector args) const
225948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
226048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			StringIntMap bindingPoints;
226148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
226248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (StringVector::iterator it = args.begin(); it != args.end(); it++)
226348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
226448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				glw::GLuint idx = gl().getProgramResourceIndex(getProgram(), GL_UNIFORM, (*it).c_str());
226548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (idx != GL_INVALID_INDEX)
226648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
226748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					glw::GLenum param = GL_OFFSET;
226848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					glw::GLint  value = -1;
226948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					gl().getProgramResourceiv(getProgram(), GL_UNIFORM, idx, 1, &param, 1, NULL, &value);
227048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					bool hasNoError = (GL_NO_ERROR == gl().getError());
227148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					if (hasNoError)
227248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					{
227348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						bindingPoints[*it] = value;
227448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					}
227548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
227648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
227748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return bindingPoints;
227848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
227948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	};
228048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
228148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
228248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	// IProgramContextSupplier
228348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
228448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	LayoutBindingProgram* createProgram()
228548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
228648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return new AtomicCounterLayoutBindingProgram(*this);
228748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
228848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
228948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
229048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
229148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	String getDefaultUniformName(int idx = 0)
229248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
229348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringStream s;
229448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << "atomic" << idx;
229548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return s.str();
229648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
229748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
229848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
229948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	String buildAccess(const String& var)
230048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
230148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::ostringstream s;
230248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << "vec4(float(atomicCounter(" << var << ")), 1.0, 0.0, 1.0)";
230348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return s.str();
230448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
230548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
230648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	int maxBindings()
230748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
230848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		int units = 0;
230948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl().getIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &units);
231048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return units;
231148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
231248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
231348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	// return max. array size allowed
231448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	int maxArraySize()
231548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
231648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		int units = 0;
231748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		switch (getStage())
231848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
231948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case FragmentShader:
232048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl().getIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTERS, &units);
232148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
232248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case VertexShader:
232348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl().getIntegerv(GL_MAX_VERTEX_ATOMIC_COUNTERS, &units);
232448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
232548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case ComputeShader:
232648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl().getIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTERS, &units);
232748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
232848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		default:
232948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			DE_ASSERT(0);
233048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
233148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
233248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return units;
233348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
233448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
233548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//=========================================================================
233648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	// sub-tests overrides
233748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//=========================================================================
233848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
233948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	LayoutBindingTestResult binding_basic_default(void)
234048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
234148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return true;
234248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
234348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//virtual LayoutBindingTestResult binding_basic_explicit          (void);
234448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//virtual LayoutBindingTestResult binding_basic_multiple          (void);
234548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	LayoutBindingTestResult binding_basic_render(void)
234648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
234748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return true;
234848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
234948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//virtual LayoutBindingTestResult binding_integer_constant        (void);
235048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
235148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	LayoutBindingTestResult binding_array_size(void)
235248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
235348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		bool passed = true;
235448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
235548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//== test different sized arrays
235648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::vector<int> arraySizes = makeSparseRange(maxArraySize(), 1);
235748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (std::vector<int>::iterator it = arraySizes.begin(); it < arraySizes.end(); it++)
235848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
235948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			int			 arraySize = *it;
236048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			StringStream s;
236148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "[" << arraySize << "]";
236248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			String decl =
236348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				buildUniformDecl(String(getTestParameters().keyword), buildLayout(0),
236448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
236548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								 buildBlock(getDefaultUniformName()), getDefaultUniformName(), buildArray(arraySize));
236648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setTemplateParam("UNIFORM_DECL", decl);
236748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
236848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s.reset();
236948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			// build a function that accesses the whole array
237048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "float accumulate(void)\n";
237148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "{\n";
237248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "  float acc = 0.0;\n";
237348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "  for(int i=0; i < " << arraySize << " ; i++)\n";
237448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "    acc = float(atomicCounter(" << getDefaultUniformName() << "[i]));\n";
237548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "  return acc;\n";
237648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "}\n";
237748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
237848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setTemplateParam("OPTIONAL_FUNCTION_BLOCK", s.str());
237948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
238048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s.reset();
238148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "vec4(accumulate(), 1.0, 0.0, 1.0);\n";
238248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setTemplateParam("UNIFORM_ACCESS", s.str());
238348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			updateTemplate();
238448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
238548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setTemplateParam("OPTIONAL_FUNCTION_BLOCK", String());
238648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
238748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
238848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			passed &= program->compiledAndLinked();
238948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (!passed)
239048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
239148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				return LayoutBindingTestResult(passed, program->getErrorLog());
239248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
239348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
239448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			StringVector	   list;
239548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			std::ostringstream texUnitStr;
239648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			texUnitStr << getDefaultUniformName() << "[0]";
239748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			list.push_back(texUnitStr.str());
239848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
239948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			StringIntMap bindingPoints = program->getBindingPoints(list);
240048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			passed &= (0 == bindingPoints[list[0]]);
240148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (!passed)
240248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
240348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				return LayoutBindingTestResult(
240448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					passed, generateLog(String("binding point did not match default"), bindingPoints[list[0]], 1));
240548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
240648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
240748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
240848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return LayoutBindingTestResult(passed, String());
240948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
241048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	LayoutBindingTestResult binding_array_implicit(void)
241148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
241248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return true;
241348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
241448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	LayoutBindingTestResult binding_array_multiple(void)
241548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
241648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return true;
241748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
241848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	LayoutBindingTestResult binding_api_update(void)
241948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
242048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return true;
242148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
242248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//virtual LayoutBindingTestResult binding_compilation_errors      (void);
242348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//virtual LayoutBindingTestResult binding_link_errors             (void);
242448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
242548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	LayoutBindingTestResult binding_examples_many_bindings(void)
242648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
242748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		int max_bindings = 0;
242848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
242948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (isStage(VertexShader))
243048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
243148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl().getIntegerv(GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS, &max_bindings);
243248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
243348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else if (isStage(FragmentShader))
243448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
243548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl().getIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS, &max_bindings);
243648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
243748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else
243848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
243948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl().getIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS, &max_bindings);
244048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
244148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
244248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// example 1 in atomic counter CTS spec ac-binding-examples
244348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
244448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			bool		 passed = true;
244548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			StringStream s;
244648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << buildAccess(getDefaultUniformName()) << ";\n";
244748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setTemplateParam("UNIFORM_ACCESS", s.str());
244848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
244948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s.reset();
245048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "layout(binding=2, offset=4) uniform atomic_uint;\n";
245148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "layout(binding=2) uniform atomic_uint " << getDefaultUniformName() << ";\n";
245248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setTemplateParam("UNIFORM_DECL", s.str());
245348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			updateTemplate();
245448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
245548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
245648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			passed &= program->compiledAndLinked();
245748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (!passed)
245848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
245948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				return LayoutBindingTestResult(passed, program->getErrorLog());
246048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
246148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
246248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			StringVector list;
246348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			list.push_back(getDefaultUniformName());
246448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
246548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			StringIntMap offsets = program->getOffsets(list);
246648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			passed &= (4 == offsets[list[0]]);
246748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (!passed)
246848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
246948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				return LayoutBindingTestResult(
247048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					passed, generateLog(String("offset did not match requested"), offsets[list[0]], 1));
247148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
247248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
247348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
247448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// example 2 in atomic counter CTS spec ac-binding-examples
247548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (max_bindings >= 2)
247648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
247748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			bool		 passed = true;
247848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			StringStream s;
247948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << buildAccess(getDefaultUniformName()) << ";\n";
248048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "+" << buildAccess(getDefaultUniformName(1)) << ";\n";
248148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "+" << buildAccess(getDefaultUniformName(2)) << ";\n";
248248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "+" << buildAccess(getDefaultUniformName(3)) << ";\n";
248348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setTemplateParam("UNIFORM_ACCESS", s.str());
248448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
248548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s.reset();
248648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "layout(binding=3, offset=4) uniform atomic_uint " << getDefaultUniformName() << ";\n";
248748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "layout(binding=2) uniform atomic_uint " << getDefaultUniformName(1) << ";\n";
248848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "layout(binding=3) uniform atomic_uint " << getDefaultUniformName(2) << ";\n";
248948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "layout(binding=2) uniform atomic_uint " << getDefaultUniformName(3) << ";\n";
249048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setTemplateParam("UNIFORM_DECL", s.str());
249148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			updateTemplate();
249248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
249348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
249448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			passed &= program->compiledAndLinked();
249548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (!passed)
249648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
249748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				return LayoutBindingTestResult(passed, program->getErrorLog());
249848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
249948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
250048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			StringVector list;
250148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			list.push_back(getDefaultUniformName());
250248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			list.push_back(getDefaultUniformName(1));
250348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			list.push_back(getDefaultUniformName(2));
250448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			list.push_back(getDefaultUniformName(3));
250548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
250648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			StringIntMap offsets = program->getOffsets(list);
250748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			IntVector	expected;
250848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			expected.insert(expected.end(), 4);
250948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			expected.insert(expected.end(), 0);
251048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			expected.insert(expected.end(), 8);
251148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			expected.insert(expected.end(), 4);
251248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (unsigned int idx = 0; idx < list.size(); idx++)
251348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
251448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				passed &= (expected[idx] == offsets[list[idx]]);
251548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (!passed)
251648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
251748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					return LayoutBindingTestResult(
251848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						passed, generateLog(String("offset of") + String(list[idx]) + String("did not match requested"),
251948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos											offsets[list[idx]], 4));
252048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
252148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
252248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
252348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
252448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// example 3 in atomic counter CTS spec ac-binding-examples
252548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
252648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			bool		 passed = true;
252748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			StringStream s;
252848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << buildAccess(getDefaultUniformName()) << ";\n";
252948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setTemplateParam("UNIFORM_ACCESS", s.str());
253048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
253148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s.reset();
253248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "layout(binding=2, offset=4) uniform atomic_uint;\n";
253348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "layout(offset=8) uniform atomic_uint " << getDefaultUniformName() << ";\n";
253448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setTemplateParam("UNIFORM_DECL", s.str());
253548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			updateTemplate();
253648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
253748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
253848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			passed &= program->compiledAndLinked();
253948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (passed)
254048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
254148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				return LayoutBindingTestResult(!passed, String("should not compile"));
254248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
254348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
254448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
254548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// example 4 in atomic counter CTS spec ac-binding-examples
254648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
254748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			bool		 passed = true;
254848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			StringStream s;
254948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << buildAccess(getDefaultUniformName()) << ";\n";
255048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setTemplateParam("UNIFORM_ACCESS", s.str());
255148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
255248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s.reset();
255348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "layout(offset=4) uniform atomic_uint " << getDefaultUniformName() << ";\n";
255448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setTemplateParam("UNIFORM_DECL", s.str());
255548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			updateTemplate();
255648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
255748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
255848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			passed &= program->compiledAndLinked();
255948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (passed)
256048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
256148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				return LayoutBindingTestResult(!passed, String("should not compile"));
256248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
256348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
256448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
256548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// example 5 in atomic counter CTS spec ac-binding-examples
256648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// first check working example, then amend it with an error
256748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (max_bindings >= 2)
256848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
256948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (int pass = 0; pass < 2; pass++)
257048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
257148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				bool passed = true;
257248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
257348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				StringStream s;
257448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				s << buildAccess(getDefaultUniformName()) << ";\n";
257548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				s << "+" << buildAccess(getDefaultUniformName(1)) << ";\n";
257648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (pass)
257748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					s << "+" << buildAccess(getDefaultUniformName(2)) << ";\n";
257848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				setTemplateParam("UNIFORM_ACCESS", s.str());
257948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
258048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				s.reset();
258148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				s << "layout(binding=1, offset=0) uniform atomic_uint " << getDefaultUniformName() << ";\n";
258248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				s << "layout(binding=2, offset=0) uniform atomic_uint " << getDefaultUniformName(1) << ";\n";
258348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (pass)
258448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					s << "layout(binding=1, offset=0) uniform atomic_uint " << getDefaultUniformName(2) << ";\n";
258548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				setTemplateParam("UNIFORM_DECL", s.str());
258648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				updateTemplate();
258748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
258848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
258948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				passed &= program->compiledAndLinked();
259048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (pass != 0)
259148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
259248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					if (passed)
259348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					{
259448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						return LayoutBindingTestResult(passed, program->getErrorLog());
259548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					}
259648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
259748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				else
259848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
259948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					if (!passed)
260048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					{
260148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						return LayoutBindingTestResult(passed, String("should not compile"));
260248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					}
260348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
260448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
260548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
260648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
260748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// example 6 in atomic counter CTS spec ac-binding-examples
260848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// first check working example, then amend it with an error
260948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (max_bindings >= 2)
261048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
261148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (int pass = 0; pass < 2; pass++)
261248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
261348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				bool passed = true;
261448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
261548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				StringStream s;
261648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				s << buildAccess(getDefaultUniformName()) << ";\n";
261748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				s << "+" << buildAccess(getDefaultUniformName(1)) << ";\n";
261848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (pass)
261948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					s << "+" << buildAccess(getDefaultUniformName(2)) << ";\n";
262048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				setTemplateParam("UNIFORM_ACCESS", s.str());
262148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
262248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				s.reset();
262348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				s << "layout(binding=1, offset=0) uniform atomic_uint " << getDefaultUniformName() << ";\n";
262448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				s << "layout(binding=2, offset=0) uniform atomic_uint " << getDefaultUniformName(1) << ";\n";
262548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (pass)
262648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					s << "layout(binding=1, offset=2) uniform atomic_uint " << getDefaultUniformName(2) << ";\n";
262748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				setTemplateParam("UNIFORM_DECL", s.str());
262848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				updateTemplate();
262948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
263048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
263148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				passed &= program->compiledAndLinked();
263248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (pass != 0)
263348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
263448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					if (passed)
263548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					{
263648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						return LayoutBindingTestResult(passed, program->getErrorLog());
263748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					}
263848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
263948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				else
264048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
264148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					if (!passed)
264248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					{
264348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						return LayoutBindingTestResult(passed, String("should not compile"));
264448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					}
264548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
264648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
264748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
264848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
264948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return true;
265048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
265148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
265248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	LayoutBindingTestResult binding_examples_one_binding(void)
265348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
265448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// example 1 in atomic counter CTS spec ac-binding-examples
265548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
265648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			bool		 passed = true;
265748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			StringStream s;
265848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << buildAccess(getDefaultUniformName()) << ";\n";
265948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setTemplateParam("UNIFORM_ACCESS", s.str());
266048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
266148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s.reset();
266248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "layout(binding=0, offset=4) uniform atomic_uint;\n";
266348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "layout(binding=0) uniform atomic_uint " << getDefaultUniformName() << ";\n";
266448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setTemplateParam("UNIFORM_DECL", s.str());
266548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			updateTemplate();
266648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
266748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
266848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			passed &= program->compiledAndLinked();
266948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (!passed)
267048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
267148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				return LayoutBindingTestResult(passed, program->getErrorLog());
267248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
267348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
267448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			StringVector list;
267548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			list.push_back(getDefaultUniformName());
267648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
267748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			StringIntMap offsets = program->getOffsets(list);
267848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			passed &= (4 == offsets[list[0]]);
267948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (!passed)
268048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
268148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				return LayoutBindingTestResult(
268248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					passed, generateLog(String("offset did not match requested"), offsets[list[0]], 1));
268348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
268448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
268548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
268648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// example 2 in atomic counter CTS spec ac-binding-examples
268748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
268848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			bool		 passed = true;
268948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			StringStream s;
269048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << buildAccess(getDefaultUniformName()) << ";\n";
269148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "+" << buildAccess(getDefaultUniformName(1)) << ";\n";
269248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "+" << buildAccess(getDefaultUniformName(2)) << ";\n";
269348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "+" << buildAccess(getDefaultUniformName(3)) << ";\n";
269448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setTemplateParam("UNIFORM_ACCESS", s.str());
269548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
269648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s.reset();
269748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "layout(binding=0, offset=4) uniform atomic_uint " << getDefaultUniformName() << ";\n";
269848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "layout(binding=0) uniform atomic_uint " << getDefaultUniformName(1) << ";\n";
269948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "layout(binding=0) uniform atomic_uint " << getDefaultUniformName(2) << ";\n";
270048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "layout(binding=0) uniform atomic_uint " << getDefaultUniformName(3) << ";\n";
270148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setTemplateParam("UNIFORM_DECL", s.str());
270248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			updateTemplate();
270348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
270448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
270548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			passed &= program->compiledAndLinked();
270648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (!passed)
270748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
270848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				return LayoutBindingTestResult(passed, program->getErrorLog());
270948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
271048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
271148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			StringVector list;
271248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			list.push_back(getDefaultUniformName());
271348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			list.push_back(getDefaultUniformName(1));
271448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			list.push_back(getDefaultUniformName(2));
271548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			list.push_back(getDefaultUniformName(3));
271648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
271748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			StringIntMap offsets = program->getOffsets(list);
271848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			IntVector	expected;
271948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			expected.insert(expected.end(), 4);
272048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			expected.insert(expected.end(), 8);
272148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			expected.insert(expected.end(), 12);
272248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			expected.insert(expected.end(), 16);
272348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (unsigned int idx = 0; idx < list.size(); idx++)
272448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
272548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				passed &= (expected[idx] == offsets[list[idx]]);
272648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (!passed)
272748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
272848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					return LayoutBindingTestResult(
272948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						passed, generateLog(String("offset of") + String(list[idx]) + String("did not match requested"),
273048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos											offsets[list[idx]], expected[idx]));
273148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
273248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
273348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
273448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
273548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// example 3 in atomic counter CTS spec ac-binding-examples
273648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
273748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			bool		 passed = true;
273848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			StringStream s;
273948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << buildAccess(getDefaultUniformName()) << ";\n";
274048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setTemplateParam("UNIFORM_ACCESS", s.str());
274148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
274248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s.reset();
274348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "layout(binding=0, offset=4) uniform atomic_uint;\n";
274448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "layout(offset=8) uniform atomic_uint " << getDefaultUniformName() << ";\n";
274548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setTemplateParam("UNIFORM_DECL", s.str());
274648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			updateTemplate();
274748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
274848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
274948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			passed &= program->compiledAndLinked();
275048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (passed)
275148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
275248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				return LayoutBindingTestResult(!passed, String("should not compile"));
275348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
275448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
275548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
275648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// example 4 in atomic counter CTS spec ac-binding-examples
275748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
275848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			bool		 passed = true;
275948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			StringStream s;
276048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << buildAccess(getDefaultUniformName()) << ";\n";
276148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setTemplateParam("UNIFORM_ACCESS", s.str());
276248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
276348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s.reset();
276448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "layout(offset=4) uniform atomic_uint " << getDefaultUniformName() << ";\n";
276548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setTemplateParam("UNIFORM_DECL", s.str());
276648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			updateTemplate();
276748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
276848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
276948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			passed &= program->compiledAndLinked();
277048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (passed)
277148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
277248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				return LayoutBindingTestResult(!passed, String("should not compile"));
277348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
277448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
277548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
277648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// example 5 in atomic counter CTS spec ac-binding-examples
277748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// first check working example, then amend it with an error
277848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (int pass = 0; pass < 2; pass++)
277948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
278048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			bool passed = true;
278148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
278248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			StringStream s;
278348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << buildAccess(getDefaultUniformName()) << ";\n";
278448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (pass)
278548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				s << "+" << buildAccess(getDefaultUniformName(1)) << ";\n";
278648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setTemplateParam("UNIFORM_ACCESS", s.str());
278748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
278848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s.reset();
278948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "layout(binding=0, offset=0) uniform atomic_uint " << getDefaultUniformName() << ";\n";
279048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (pass)
279148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				s << "layout(binding=0, offset=0) uniform atomic_uint " << getDefaultUniformName(1) << ";\n";
279248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setTemplateParam("UNIFORM_DECL", s.str());
279348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			updateTemplate();
279448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
279548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
279648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			passed &= program->compiledAndLinked();
279748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (pass != 0)
279848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
279948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (passed)
280048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
280148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					return LayoutBindingTestResult(passed, program->getErrorLog());
280248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
280348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
280448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			else
280548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
280648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (!passed)
280748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
280848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					return LayoutBindingTestResult(passed, String("should not compile"));
280948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
281048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
281148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
281248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
281348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// example 6 in atomic counter CTS spec ac-binding-examples
281448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// first check working example, then amend it with an error
281548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (int pass = 0; pass < 2; pass++)
281648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
281748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			bool passed = true;
281848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
281948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			StringStream s;
282048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << buildAccess(getDefaultUniformName()) << ";\n";
282148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (pass)
282248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				s << "+" << buildAccess(getDefaultUniformName(1)) << ";\n";
282348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setTemplateParam("UNIFORM_ACCESS", s.str());
282448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
282548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s.reset();
282648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "layout(binding=0, offset=0) uniform atomic_uint " << getDefaultUniformName() << ";\n";
282748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (pass)
282848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				s << "layout(binding=0, offset=2) uniform atomic_uint " << getDefaultUniformName(1) << ";\n";
282948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setTemplateParam("UNIFORM_DECL", s.str());
283048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			updateTemplate();
283148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
283248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
283348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			passed &= program->compiledAndLinked();
283448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (pass != 0)
283548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
283648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (passed)
283748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
283848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					return LayoutBindingTestResult(passed, program->getErrorLog());
283948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
284048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
284148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			else
284248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
284348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (!passed)
284448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
284548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					return LayoutBindingTestResult(passed, String("should not compile"));
284648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
284748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
284848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
284948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
285048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return true;
285148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
285248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
285348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
285448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	LayoutBindingTestResult binding_examples(void)
285548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
285648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (maxBindings() >= 4)
285748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
285848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return binding_examples_many_bindings();
285948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
286048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else
286148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
286248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return binding_examples_one_binding();
286348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
286448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
286548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
286648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
286748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	LayoutBindingTestResult binding_mixed_order(void)
286848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
286948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		bool passed = true;
287048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
287148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
287248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			StringStream s;
287348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << buildAccess(getDefaultUniformName()) << ";\n";
287448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setTemplateParam("UNIFORM_ACCESS", s.str());
287548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
287648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			String decl =
287748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				buildUniformDecl(String(getTestParameters().keyword), String("layout(binding=0, offset=0)"),
287848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
287948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
288048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setTemplateParam("UNIFORM_DECL", decl);
288148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			updateTemplate();
288248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
288348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
288448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			passed &= program->compiledAndLinked();
288548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (!passed)
288648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
288748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				return LayoutBindingTestResult(passed, program->getErrorLog());
288848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
288948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
289048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
289148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			String decl =
289248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				buildUniformDecl(String(getTestParameters().keyword), String("layout(offset=0, binding=0)"),
289348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								 String(getTestParameters().uniform_type), buildBlockName(getDefaultUniformName()),
289448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								 buildBlock(getDefaultUniformName()), getDefaultUniformName(), String());
289548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			setTemplateParam("UNIFORM_DECL", decl);
289648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			updateTemplate();
289748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
289848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			LayoutBindingProgram::LayoutBindingProgramAutoPtr program(*this);
289948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			passed &= program->compiledAndLinked();
290048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			if (!passed)
290148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
290248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				return LayoutBindingTestResult(passed, program->getErrorLog());
290348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
290448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
290548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
290648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return true;
290748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
290848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
290948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
291048087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosAtomicCounterLayoutBindingCase::AtomicCounterLayoutBindingCase(Context& context, const char* name,
291148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos															   const char* description, StageType stage,
291248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos															   LayoutBindingParameters& samplerType,
291348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos															   glu::GLSLVersion			glslVersion)
291448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	: LayoutBindingBaseCase(context, name, description, stage, samplerType, glslVersion)
291548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
291648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
291748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
291848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos//=========================================================================
291948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos// test case Uniform blocks binding
292048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos//=========================================================================
292148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass UniformBlocksLayoutBindingCase : public LayoutBindingBaseCase
292248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
292348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
292448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
292548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	UniformBlocksLayoutBindingCase(Context& context, const char* name, const char* description, StageType stage,
292648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos								   LayoutBindingParameters& samplerType, glu::GLSLVersion glslVersion);
292748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	~UniformBlocksLayoutBindingCase(void);
292848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
292948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
293048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	class UniformBlocksLayoutBindingProgram : public LayoutBindingProgram
293148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
293248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	public:
293348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		UniformBlocksLayoutBindingProgram(IProgramContextSupplier& contextSupplier)
293448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			: LayoutBindingProgram(contextSupplier)
293548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
293648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
293748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
293848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		~UniformBlocksLayoutBindingProgram()
293948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
294048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
294148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
294248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	private:
294348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		/*virtual*/
294448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringIntMap getBindingPoints(StringVector args) const
294548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
294648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			StringIntMap bindingPoints;
294748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
294848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (StringVector::iterator it = args.begin(); it != args.end(); it++)
294948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
295048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				glw::GLuint idx = gl().getProgramResourceIndex(getProgram(), GL_UNIFORM_BLOCK, (*it).c_str());
295148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (idx != glw::GLuint(-1))
295248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
295348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					glw::GLenum param = GL_BUFFER_BINDING;
295448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					glw::GLint  value = -1;
295548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					gl().getProgramResourceiv(getProgram(), GL_UNIFORM_BLOCK, idx, 1, &param, 1, NULL, &value);
295648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					bool hasNoError = (GL_NO_ERROR == gl().getError());
295748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					if (hasNoError)
295848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					{
295948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						bindingPoints[*it] = value;
296048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					}
296148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
296248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
296348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
296448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return bindingPoints;
296548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
296648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
296748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		/*virtual*/
296848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		bool setBindingPoints(StringVector list, glw::GLint bindingPoint) const
296948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
297048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			bool bNoError = true;
297148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
297248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (StringVector::iterator it = list.begin(); it != list.end(); it++)
297348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
297448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				glw::GLuint blockIndex = gl().getUniformBlockIndex(getProgram(), (*it).c_str());
297548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (blockIndex == GL_INVALID_INDEX)
297648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
297748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
297848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					return false;
297948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
298048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				gl().uniformBlockBinding(getProgram(), blockIndex, bindingPoint);
298148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
298248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return bNoError;
298348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
298448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	};
298548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
298648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
298748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	// IProgramContextSupplier
298848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
298948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	LayoutBindingProgram* createProgram()
299048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
299148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return new UniformBlocksLayoutBindingProgram(*this);
299248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
299348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
299448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
299548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
299648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	String buildBlockName(const String& name)
299748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
299848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
299948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return name;
300048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
300148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
300248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
300348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	String buildBlock(const String& name, const String& type)
300448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
300548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
300648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::ostringstream s;
300748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << "{";
300848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << type << " " << name << "_a; ";
300948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << type << " " << name << "_b; ";
301048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << "}";
301148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return s.str();
301248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
301348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
301448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
301548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	String buildAccess(const String& var)
301648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
301748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::ostringstream s;
301848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << "vec4(0.0, " << var << "_a, 0.0, 1.0) + vec4(0.0, " << var << "_b, 0.0, 1.0)";
301948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return s.str();
302048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
302148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
302248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
302348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	String buildLayout(const String& binding)
302448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
302548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::ostringstream s;
302648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!binding.empty())
302748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "layout(binding=" << binding << ", std140) ";
302848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else
302948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "layout(std140) ";
303048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return s.str();
303148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
303248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
303348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
303448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	int maxBindings()
303548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
303648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		int units = 0;
303748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl().getIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &units);
303848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return units;
303948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
304048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
304148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	// return max. array size allowed
304248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
304348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	int maxArraySize()
304448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
304548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		int units = 0;
304648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		switch (getStage())
304748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
304848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case FragmentShader:
304948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl().getIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS, &units);
305048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
305148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case VertexShader:
305248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl().getIntegerv(GL_MAX_VERTEX_UNIFORM_BLOCKS, &units);
305348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
305448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case ComputeShader:
305548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl().getIntegerv(GL_MAX_COMPUTE_UNIFORM_BLOCKS, &units);
305648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
305748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		default:
305848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			DE_ASSERT(0);
305948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
306048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
306148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return units;
306248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
306348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
306448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
306548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void bind(int binding)
306648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
306748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl().bindBufferBase(GL_UNIFORM_BUFFER, binding, m_buffername);
306848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
306948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
307048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
307148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void unbind(int binding)
307248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
307348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl().bindBufferBase(GL_UNIFORM_BUFFER, binding, 0);
307448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
307548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
307648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
307748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void setupTest(void)
307848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
307948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const float f[2] = { 0.25f, 0.75f };
308048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl().genBuffers(1, &m_buffername);
308148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl().bindBuffer(GL_UNIFORM_BUFFER, m_buffername);
308248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl().bufferData(GL_UNIFORM_BUFFER, sizeof(f), f, GL_STATIC_DRAW);
308348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
308448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
308548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
308648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void teardownTest(void)
308748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
308848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl().bindBuffer(GL_UNIFORM_BUFFER, 0);
308948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl().deleteBuffers(1, &m_buffername);
309048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
309148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
309248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
309348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	glw::GLuint m_buffername;
309448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
309548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
309648087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosUniformBlocksLayoutBindingCase::UniformBlocksLayoutBindingCase(Context& context, const char* name,
309748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos															   const char* description, StageType stage,
309848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos															   LayoutBindingParameters& samplerType,
309948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos															   glu::GLSLVersion			glslVersion)
310048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	: LayoutBindingBaseCase(context, name, description, stage, samplerType, glslVersion), m_buffername(0)
310148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
310248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
310348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
310448087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosUniformBlocksLayoutBindingCase::~UniformBlocksLayoutBindingCase()
310548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
310648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
310748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
310848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos//*****************************************************************************
310948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
311048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos//=========================================================================
311148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos// test case Shader storage buffer binding
311248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos//=========================================================================
311348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosclass ShaderStorageBufferLayoutBindingCase : public LayoutBindingBaseCase
311448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
311548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulospublic:
311648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	ShaderStorageBufferLayoutBindingCase(Context& context, const char* name, const char* description, StageType stage,
311748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos										 LayoutBindingParameters& samplerType, glu::GLSLVersion glslVersion);
311848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	~ShaderStorageBufferLayoutBindingCase(void);
311948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
312048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
312148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	class ShaderStorageBufferLayoutBindingProgram : public LayoutBindingProgram
312248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
312348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	public:
312448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		ShaderStorageBufferLayoutBindingProgram(IProgramContextSupplier& contextSupplier)
312548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			: LayoutBindingProgram(contextSupplier)
312648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
312748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
312848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
312948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		~ShaderStorageBufferLayoutBindingProgram()
313048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
313148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
313248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		//*******************************************************************************
313348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// overwritten virtual methods
313448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	private:
313548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		/*virtual*/
313648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringIntMap getBindingPoints(StringVector args) const
313748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
313848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			StringIntMap bindingPoints;
313948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
314048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (StringVector::iterator it = args.begin(); it != args.end(); it++)
314148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
314248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				glw::GLuint idx = gl().getProgramResourceIndex(getProgram(), GL_SHADER_STORAGE_BLOCK, (*it).c_str());
314348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (idx != GL_INVALID_INDEX)
314448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
314548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					glw::GLenum param = GL_BUFFER_BINDING;
314648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					glw::GLint  value = -1;
314748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					gl().getProgramResourceiv(getProgram(), GL_SHADER_STORAGE_BLOCK, idx, 1, &param, 1, NULL, &value);
314848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					bool hasNoError = (GL_NO_ERROR == gl().getError());
314948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					if (hasNoError)
315048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					{
315148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos						bindingPoints[*it] = value;
315248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					}
315348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
315448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
315548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
315648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return bindingPoints;
315748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
315848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
315948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		/*virtual*/
316048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		bool setBindingPoints(StringVector list, glw::GLint bindingPoint) const
316148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
316248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			for (StringVector::iterator it = list.begin(); it != list.end(); it++)
316348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
316448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				glw::GLuint blockIndex =
316548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					gl().getProgramResourceIndex(getProgram(), GL_SHADER_STORAGE_BLOCK, (*it).c_str());
316648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				if (blockIndex == GL_INVALID_INDEX)
316748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				{
316848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					return false;
316948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				}
317048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				gl().shaderStorageBlockBinding(getProgram(), blockIndex, bindingPoint);
317148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
317248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return true;
317348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
317448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	};
317548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
317648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
317748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	// IProgramContextSupplier
317848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
317948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	LayoutBindingProgram* createProgram()
318048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
318148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return new ShaderStorageBufferLayoutBindingProgram(*this);
318248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
318348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
318448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
318548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
318648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	String buildLayout(const String& binding)
318748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
318848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::ostringstream s;
318948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (!binding.empty())
319048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "layout(binding=" << binding << ", std430) ";
319148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		else
319248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			s << "layout(std430) ";
319348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return s.str();
319448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
319548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
319648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
319748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	String getDefaultUniformName(int idx = 0)
319848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
319948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		StringStream s;
320048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
320148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << "buffer" << idx;
320248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return s.str();
320348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
320448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
320548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	String buildBlockName(const String& name)
320648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
320748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return name;
320848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
320948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
321048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
321148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	String buildBlock(const String& name, const String& type)
321248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
321348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::ostringstream s;
321448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << "{";
321548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << type << " " << name << "_a[2];\n";
321648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << "}";
321748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return s.str();
321848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
321948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
322048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
322148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	String buildAccess(const String& var)
322248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
322348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		std::ostringstream s;
322448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		s << "vec4(0.0, " << var << "_a[0] + " << var << "_a[1], 0.0, 1.0)";
322548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return s.str();
322648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
322748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
322848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	int maxBindings()
322948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
323048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		int units = 0;
323148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl().getIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &units);
323248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return units;
323348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
323448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
323548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	// return max. array size allowed
323648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	int maxArraySize()
323748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
323848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		int units = 0;
323948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		switch (getStage())
324048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
324148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case FragmentShader:
324248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl().getIntegerv(GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, &units);
324348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
324448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case VertexShader:
324548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl().getIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &units);
324648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
324748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		case ComputeShader:
324848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			gl().getIntegerv(GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &units);
324948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
325048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		default:
325148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			DE_ASSERT(0);
325248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			break;
325348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
325448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return units;
325548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
325648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
325748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
325848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void bind(int binding)
325948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
326048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl().bindBufferBase(GL_SHADER_STORAGE_BUFFER, binding, m_buffername);
326148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
326248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
326348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
326448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void unbind(int binding)
326548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
326648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl().bindBufferBase(GL_SHADER_STORAGE_BUFFER, binding, 0);
326748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
326848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
326948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
327048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void setupTest(void)
327148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
327248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		const float f[2] = { 0.25f, 0.75f };
327348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl().genBuffers(1, &m_buffername);
327448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl().bindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffername);
327548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl().bufferData(GL_SHADER_STORAGE_BUFFER, sizeof(f), f, GL_STATIC_DRAW);
327648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
327748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
327848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
327948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	void teardownTest(void)
328048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
328148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl().bindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
328248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		gl().deleteBuffers(1, &m_buffername);
328348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
328448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
328548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//=========================================================================
328648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	// sub-tests overrides
328748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//=========================================================================
328848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
328948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
329048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//virtual LayoutBindingTestResult        binding_basic_default               (void);
329148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//virtual LayoutBindingTestResult        binding_basic_explicit              (void);
329248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//virtual LayoutBindingTestResult        binding_basic_multiple              (void);
329348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//virtual LayoutBindingTestResult        binding_basic_render                (void);
329448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//virtual LayoutBindingTestResult        binding_integer_constant            (void);
329548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//virtual LayoutBindingTestResult        binding_integer_constant_expression (void);
329648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//virtual LayoutBindingTestResult        binding_array_size                  (void);
329748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//virtual LayoutBindingTestResult        binding_array_implicit              (void);
329848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//virtual LayoutBindingTestResult        binding_array_multiple              (void);
329948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	/*virtual*/
330048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	LayoutBindingTestResult binding_api_update(void)
330148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
330248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		// only for GL
330348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		if (getGLSLVersion() == glu::GLSL_VERSION_310_ES)
330448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			return LayoutBindingTestResult(true, String(), true);
330548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
330648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		return LayoutBindingBaseCase::binding_api_update();
330748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
330848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//virtual LayoutBindingTestResult        binding_compilation_errors          (void);
330948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//virtual LayoutBindingTestResult        binding_link_errors                 (void);
331048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	//virtual LayoutBindingTestResult        binding_examples                    (void);
331148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
331248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosprivate:
331348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	glw::GLuint m_buffername;
331448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
331548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
331648087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosShaderStorageBufferLayoutBindingCase::ShaderStorageBufferLayoutBindingCase(Context& context, const char* name,
331748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos																		   const char* description, StageType stage,
331848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos																		   LayoutBindingParameters& samplerType,
331948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos																		   glu::GLSLVersion			glslVersion)
332048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	: LayoutBindingBaseCase(context, name, description, stage, samplerType, glslVersion), m_buffername(0)
332148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
332248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
332348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
332448087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosShaderStorageBufferLayoutBindingCase::~ShaderStorageBufferLayoutBindingCase()
332548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
332648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
332748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
332848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos//*****************************************************************************
332948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
333048087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosLayoutBindingTests::LayoutBindingTests(Context& context, glu::GLSLVersion glslVersion)
333148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	: TestCaseGroup(context, "layout_binding", "Layout Binding LayoutBindingSubTest"), m_glslVersion(glslVersion)
333248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
333348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
333448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
333548087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosLayoutBindingTests::~LayoutBindingTests(void)
333648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
333748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
333848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
333948087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosStageType LayoutBindingTests::stageTypes[] = {
334048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{ "ComputeShader", ComputeShader },
334148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{ "FragmentShader", FragmentShader },
334248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{ "VertexShader", VertexShader },
334348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
334448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
334548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos// uniform_type must match vector_type, i.e. isampler2D=>ivec4
334648087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosLayoutBindingParameters LayoutBindingTests::test_args[] = {
334748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{ "uniform", Texture, TwoD, "vec4", "sampler2D", "vec2", "texture" },
334848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{ "uniform", Texture, ThreeD, "vec4", "sampler3D", "vec3", "texture" },
334948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{ "uniform", Texture, TwoDArray, "vec4", "sampler2DArray", "vec3", "texture" },
335048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{ "uniform", Image, TwoD, "vec4", "image2D", "ivec2", "imageLoad" },
335148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{ "uniform", AtomicCounter, TwoD, "vec4", "atomic_uint", "vec3", "atomic" },
335248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{ "uniform", UniformBlock, None, "vec4", "block", "vec3", "block" },
335348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{ "buffer", ShaderStorageBuffer, None, "vec4", "buffer", "vec3", "atomicAdd" },
335448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos};
335548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
335648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos// create test name which must be unique or dEQP framework will throw
335748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos// example: sampler2D_layout_binding_vec4_texture_0
335848087f5f0eb08759ee763f98daf3b34becb74559Pyry HaulosString LayoutBindingTests::createTestName(const StageType& stageType, const LayoutBindingParameters& testArgs)
335948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
336048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	StringStream s;
336148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	s << testArgs.uniform_type;
336248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	s << "_layout_binding_";
336348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	s << testArgs.access_function << "_";
336448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	s << stageType.name;
336548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	return s.str();
336648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
336748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
336848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulosvoid LayoutBindingTests::init(void)
336948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos{
337048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	std::vector<StageType>				 stages   = makeVector(stageTypes);
337148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	std::vector<LayoutBindingParameters> samplers = makeVector(test_args);
337248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	for (std::vector<StageType>::iterator stagesIter = stages.begin(); stagesIter != stages.end(); stagesIter++)
337348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	{
337448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		for (std::vector<LayoutBindingParameters>::iterator testArgsIter = samplers.begin();
337548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			 testArgsIter != samplers.end(); testArgsIter++)
337648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		{
337748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			String testName = createTestName(*stagesIter, *testArgsIter);
337848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			switch ((*testArgsIter).surface_type)
337948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			{
338048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			case Texture:
338148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				addChild(new SamplerLayoutBindingCase(m_context, testName.c_str(),
338248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos													  "test sampler layout binding functionality", *stagesIter,
338348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos													  *testArgsIter, m_glslVersion));
338448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				break;
338548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			case Image:
338648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				addChild(new ImageLayoutBindingCase(m_context, testName.c_str(),
338748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos													"test image layout binding functionality", *stagesIter,
338848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos													*testArgsIter, m_glslVersion));
338948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				break;
339048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			case AtomicCounter:
339148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				addChild(new AtomicCounterLayoutBindingCase(m_context, testName.c_str(),
339248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos															"test atomic counters layout binding functionality",
339348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos															*stagesIter, *testArgsIter, m_glslVersion));
339448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				break;
339548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			case UniformBlock:
339648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				addChild(new UniformBlocksLayoutBindingCase(m_context, testName.c_str(),
339748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos															"test uniform block layout binding functionality",
339848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos															*stagesIter, *testArgsIter, m_glslVersion));
339948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				break;
340048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			case ShaderStorageBuffer:
340148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				addChild(new ShaderStorageBufferLayoutBindingCase(
340248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					m_context, testName.c_str(), "test shader storage buffer layout binding functionality", *stagesIter,
340348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos					*testArgsIter, m_glslVersion));
340448087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				break;
340548087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			default:
340648087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				DE_ASSERT(0);
340748087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos				break;
340848087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos			}
340948087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos		}
341048087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos	}
341148087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos}
341248087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos
341348087f5f0eb08759ee763f98daf3b34becb74559Pyry Haulos} // glcts
3414