/*-------------------------------------------------------------------------
 * drawElements Quality Program OpenGL (ES) Module
 * -----------------------------------------------
 *
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief Shader execution utilities.
 *//*--------------------------------------------------------------------*/

#include "glsShaderExecUtil.hpp"
#include "gluRenderContext.hpp"
#include "gluDrawUtil.hpp"
#include "gluObjectWrapper.hpp"
#include "gluShaderProgram.hpp"
#include "gluTextureUtil.hpp"
#include "gluProgramInterfaceQuery.hpp"
#include "gluPixelTransfer.hpp"
#include "gluStrUtil.hpp"
#include "tcuTestLog.hpp"
#include "glwFunctions.hpp"
#include "glwEnums.hpp"
#include "deSTLUtil.hpp"
#include "deStringUtil.hpp"
#include "deUniquePtr.hpp"
#include "deMemory.h"

#include <map>

namespace deqp
{
namespace gls
{

namespace ShaderExecUtil
{

using std::vector;

static bool isExtensionSupported (const glu::RenderContext& renderCtx, const std::string& extension)
{
	const glw::Functions&	gl		= renderCtx.getFunctions();
	int						numExts	= 0;

	gl.getIntegerv(GL_NUM_EXTENSIONS, &numExts);

	for (int ndx = 0; ndx < numExts; ndx++)
	{
		const char* curExt = (const char*)gl.getStringi(GL_EXTENSIONS, ndx);

		if (extension == curExt)
			return true;
	}

	return false;
}

static void checkExtension (const glu::RenderContext& renderCtx, const std::string& extension)
{
	if (!isExtensionSupported(renderCtx, extension))
		throw tcu::NotSupportedError(extension + " is not supported");
}

static void checkLimit (const glu::RenderContext& renderCtx, deUint32 pname, int required)
{
	const glw::Functions&	gl					= renderCtx.getFunctions();
	int						implementationLimit	= -1;
	deUint32				error;

	gl.getIntegerv(pname, &implementationLimit);
	error = gl.getError();

	if (error != GL_NO_ERROR)
		throw tcu::TestError("Failed to query " + de::toString(glu::getGettableStateStr(pname)) + " - got " + de::toString(glu::getErrorStr(error)));
	if (implementationLimit < required)
		throw tcu::NotSupportedError("Test requires " + de::toString(glu::getGettableStateStr(pname)) + " >= " + de::toString(required) + ", got " + de::toString(implementationLimit));
}

// Shader utilities

static std::string generateVertexShader (const ShaderSpec& shaderSpec, const std::string& inputPrefix, const std::string& outputPrefix)
{
	const bool			usesInout	= glu::glslVersionUsesInOutQualifiers(shaderSpec.version);
	const char*			in			= usesInout ? "in"		: "attribute";
	const char*			out			= usesInout ? "out"		: "varying";
	std::ostringstream	src;

	DE_ASSERT(!inputPrefix.empty() && !outputPrefix.empty());

	src << glu::getGLSLVersionDeclaration(shaderSpec.version) << "\n";

	if (!shaderSpec.globalDeclarations.empty())
		src << shaderSpec.globalDeclarations << "\n";

	src << in << " highp vec4 a_position;\n";

	for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input)
		src << in << " " << glu::declare(input->varType, inputPrefix + input->name) << ";\n";

	for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output)
	{
		DE_ASSERT(output->varType.isBasicType());

		if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType()))
		{
			const int				vecSize		= glu::getDataTypeScalarSize(output->varType.getBasicType());
			const glu::DataType		intBaseType	= vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
			const glu::VarType		intType		(intBaseType, glu::PRECISION_HIGHP);

			src << "flat " << out << " " << glu::declare(intType, outputPrefix + output->name) << ";\n";
		}
		else
			src << "flat " << out << " " << glu::declare(output->varType, outputPrefix + output->name) << ";\n";
	}

	src << "\n"
		<< "void main (void)\n"
		<< "{\n"
		<< "	gl_Position = a_position;\n"
		<< "	gl_PointSize = 1.0;\n\n";

	// Declare & fetch local input variables
	for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input)
		src << "\t" << glu::declare(input->varType, input->name) << " = " << inputPrefix << input->name << ";\n";

	// Declare local output variables
	for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output)
		src << "\t" << glu::declare(output->varType, output->name) << ";\n";

	// Operation - indented to correct level.
	{
		std::istringstream	opSrc	(shaderSpec.source);
		std::string			line;

		while (std::getline(opSrc, line))
			src << "\t" << line << "\n";
	}

	// Assignments to outputs.
	for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output)
	{
		if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType()))
		{
			const int				vecSize		= glu::getDataTypeScalarSize(output->varType.getBasicType());
			const glu::DataType		intBaseType	= vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;

			src << "\t" << outputPrefix << output->name << " = " << glu::getDataTypeName(intBaseType) << "(" << output->name << ");\n";
		}
		else
			src << "\t" << outputPrefix << output->name << " = " << output->name << ";\n";
	}

	src << "}\n";

	return src.str();
}

static std::string generateGeometryShader (const ShaderSpec& shaderSpec, const std::string& inputPrefix, const std::string& outputPrefix)
{
	DE_ASSERT(glu::glslVersionUsesInOutQualifiers(shaderSpec.version));
	DE_ASSERT(!inputPrefix.empty() && !outputPrefix.empty());

	std::ostringstream	src;

	src << glu::getGLSLVersionDeclaration(shaderSpec.version) << "\n";

	if (glu::glslVersionIsES(shaderSpec.version) && shaderSpec.version <= glu::GLSL_VERSION_310_ES)
		src << "#extension GL_EXT_geometry_shader : require\n";

	if (!shaderSpec.globalDeclarations.empty())
		src << shaderSpec.globalDeclarations << "\n";

	src << "layout(points) in;\n"
		<< "layout(points, max_vertices = 1) out;\n";

	for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input)
		src << "flat in " << glu::declare(input->varType, inputPrefix + input->name) << "[];\n";

	for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output)
	{
		DE_ASSERT(output->varType.isBasicType());

		if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType()))
		{
			const int				vecSize		= glu::getDataTypeScalarSize(output->varType.getBasicType());
			const glu::DataType		intBaseType	= vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
			const glu::VarType		intType		(intBaseType, glu::PRECISION_HIGHP);

			src << "flat out " << glu::declare(intType, outputPrefix + output->name) << ";\n";
		}
		else
			src << "flat out " << glu::declare(output->varType, outputPrefix + output->name) << ";\n";
	}

	src << "\n"
		<< "void main (void)\n"
		<< "{\n"
		<< "	gl_Position = gl_in[0].gl_Position;\n\n";

	// Fetch input variables
	for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input)
		src << "\t" << glu::declare(input->varType, input->name) << " = " << inputPrefix << input->name << "[0];\n";

	// Declare local output variables.
	for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output)
		src << "\t" << glu::declare(output->varType, output->name) << ";\n";

	src << "\n";

	// Operation - indented to correct level.
	{
		std::istringstream	opSrc	(shaderSpec.source);
		std::string			line;

		while (std::getline(opSrc, line))
			src << "\t" << line << "\n";
	}

	// Assignments to outputs.
	for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output)
	{
		if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType()))
		{
			const int				vecSize		= glu::getDataTypeScalarSize(output->varType.getBasicType());
			const glu::DataType		intBaseType	= vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;

			src << "\t" << outputPrefix << output->name << " = " << glu::getDataTypeName(intBaseType) << "(" << output->name << ");\n";
		}
		else
			src << "\t" << outputPrefix << output->name << " = " << output->name << ";\n";
	}

	src << "	EmitVertex();\n"
		<< "	EndPrimitive();\n"
		<< "}\n";

	return src.str();
}

static std::string generateEmptyFragmentSource (glu::GLSLVersion version)
{
	const bool			customOut		= glu::glslVersionUsesInOutQualifiers(version);
	std::ostringstream	src;

	src << glu::getGLSLVersionDeclaration(version) << "\n";

	// \todo [2013-08-05 pyry] Do we need one unused output?

	src << "void main (void)\n{\n";
	if (!customOut)
		src << "	gl_FragColor = vec4(0.0);\n";
	src << "}\n";

	return src.str();
}

static std::string generatePassthroughVertexShader (const ShaderSpec& shaderSpec, const std::string& inputPrefix, const std::string& outputPrefix)
{
	// flat qualifier is not present in earlier versions?
	DE_ASSERT(glu::glslVersionUsesInOutQualifiers(shaderSpec.version));

	std::ostringstream src;

	src << glu::getGLSLVersionDeclaration(shaderSpec.version) << "\n"
		<< "in highp vec4 a_position;\n";

	for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input)
	{
		src << "in " << glu::declare(input->varType, inputPrefix + input->name) << ";\n"
			<< "flat out " << glu::declare(input->varType, outputPrefix + input->name) << ";\n";
	}

	src << "\nvoid main (void)\n{\n"
		<< "	gl_Position = a_position;\n"
		<< "	gl_PointSize = 1.0;\n";

	for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input)
		src << "\t" << outputPrefix << input->name << " = " << inputPrefix << input->name << ";\n";

	src << "}\n";

	return src.str();
}

static void generateFragShaderOutputDecl (std::ostream& src, const ShaderSpec& shaderSpec, bool useIntOutputs, const std::map<std::string, int>& outLocationMap, const std::string& outputPrefix)
{
	DE_ASSERT(glu::glslVersionUsesInOutQualifiers(shaderSpec.version));

	for (int outNdx = 0; outNdx < (int)shaderSpec.outputs.size(); ++outNdx)
	{
		const Symbol&				output		= shaderSpec.outputs[outNdx];
		const int					location	= de::lookup(outLocationMap, output.name);
		const std::string			outVarName	= outputPrefix + output.name;
		glu::VariableDeclaration	decl		(output.varType, outVarName, glu::STORAGE_OUT, glu::INTERPOLATION_LAST, glu::Layout(location));

		TCU_CHECK_INTERNAL(output.varType.isBasicType());

		if (useIntOutputs && glu::isDataTypeFloatOrVec(output.varType.getBasicType()))
		{
			const int			vecSize			= glu::getDataTypeScalarSize(output.varType.getBasicType());
			const glu::DataType	uintBasicType	= vecSize > 1 ? glu::getDataTypeUintVec(vecSize) : glu::TYPE_UINT;
			const glu::VarType	uintType		(uintBasicType, glu::PRECISION_HIGHP);

			decl.varType = uintType;
			src << decl << ";\n";
		}
		else if (glu::isDataTypeBoolOrBVec(output.varType.getBasicType()))
		{
			const int			vecSize			= glu::getDataTypeScalarSize(output.varType.getBasicType());
			const glu::DataType	intBasicType	= vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
			const glu::VarType	intType			(intBasicType, glu::PRECISION_HIGHP);

			decl.varType = intType;
			src << decl << ";\n";
		}
		else if (glu::isDataTypeMatrix(output.varType.getBasicType()))
		{
			const int			vecSize			= glu::getDataTypeMatrixNumRows(output.varType.getBasicType());
			const int			numVecs			= glu::getDataTypeMatrixNumColumns(output.varType.getBasicType());
			const glu::DataType	uintBasicType	= glu::getDataTypeUintVec(vecSize);
			const glu::VarType	uintType		(uintBasicType, glu::PRECISION_HIGHP);

			decl.varType = uintType;
			for (int vecNdx = 0; vecNdx < numVecs; ++vecNdx)
			{
				decl.name				= outVarName + "_" + de::toString(vecNdx);
				decl.layout.location	= location + vecNdx;
				src << decl << ";\n";
			}
		}
		else
			src << decl << ";\n";
	}
}

static void generateFragShaderOutAssign (std::ostream& src, const ShaderSpec& shaderSpec, bool useIntOutputs, const std::string& valuePrefix, const std::string& outputPrefix)
{
	for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output)
	{
		if (useIntOutputs && glu::isDataTypeFloatOrVec(output->varType.getBasicType()))
			src << "	o_" << output->name << " = floatBitsToUint(" << valuePrefix << output->name << ");\n";
		else if (glu::isDataTypeMatrix(output->varType.getBasicType()))
		{
			const int	numVecs		= glu::getDataTypeMatrixNumColumns(output->varType.getBasicType());

			for (int vecNdx = 0; vecNdx < numVecs; ++vecNdx)
				if (useIntOutputs)
					src << "\t" << outputPrefix << output->name << "_" << vecNdx << " = floatBitsToUint(" << valuePrefix << output->name << "[" << vecNdx << "]);\n";
				else
					src << "\t" << outputPrefix << output->name << "_" << vecNdx << " = " << valuePrefix << output->name << "[" << vecNdx << "];\n";
		}
		else if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType()))
		{
			const int				vecSize		= glu::getDataTypeScalarSize(output->varType.getBasicType());
			const glu::DataType		intBaseType	= vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;

			src << "\t" << outputPrefix << output->name << " = " << glu::getDataTypeName(intBaseType) << "(" << valuePrefix << output->name << ");\n";
		}
		else
			src << "\t" << outputPrefix << output->name << " = " << valuePrefix << output->name << ";\n";
	}
}

static std::string generateFragmentShader (const ShaderSpec& shaderSpec, bool useIntOutputs, const std::map<std::string, int>& outLocationMap, const std::string& inputPrefix, const std::string& outputPrefix)
{
	DE_ASSERT(glu::glslVersionUsesInOutQualifiers(shaderSpec.version));

	std::ostringstream	src;

	src << glu::getGLSLVersionDeclaration(shaderSpec.version) << "\n";

	if (!shaderSpec.globalDeclarations.empty())
		src << shaderSpec.globalDeclarations << "\n";

	for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input)
		src << "flat in " << glu::declare(input->varType, inputPrefix + input->name) << ";\n";

	generateFragShaderOutputDecl(src, shaderSpec, useIntOutputs, outLocationMap, outputPrefix);

	src << "\nvoid main (void)\n{\n";

	// Declare & fetch local input variables
	for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input)
		src << "\t" << glu::declare(input->varType, input->name) << " = " << inputPrefix << input->name << ";\n";

	// Declare output variables
	for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output)
		src << "\t" << glu::declare(output->varType, output->name) << ";\n";

	// Operation - indented to correct level.
	{
		std::istringstream	opSrc	(shaderSpec.source);
		std::string			line;

		while (std::getline(opSrc, line))
			src << "\t" << line << "\n";
	}

	generateFragShaderOutAssign(src, shaderSpec, useIntOutputs, "", outputPrefix);

	src << "}\n";

	return src.str();
}

static std::string generatePassthroughFragmentShader (const ShaderSpec& shaderSpec, bool useIntOutputs, const std::map<std::string, int>& outLocationMap, const std::string& inputPrefix, const std::string& outputPrefix)
{
	DE_ASSERT(glu::glslVersionUsesInOutQualifiers(shaderSpec.version));

	std::ostringstream	src;

	src << glu::getGLSLVersionDeclaration(shaderSpec.version) << "\n";

	if (!shaderSpec.globalDeclarations.empty())
		src << shaderSpec.globalDeclarations << "\n";

	for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output)
	{
		if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType()))
		{
			const int				vecSize		= glu::getDataTypeScalarSize(output->varType.getBasicType());
			const glu::DataType		intBaseType	= vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
			const glu::VarType		intType		(intBaseType, glu::PRECISION_HIGHP);

			src << "flat in " << glu::declare(intType, inputPrefix + output->name) << ";\n";
		}
		else
			src << "flat in " << glu::declare(output->varType, inputPrefix + output->name) << ";\n";
	}

	generateFragShaderOutputDecl(src, shaderSpec, useIntOutputs, outLocationMap, outputPrefix);

	src << "\nvoid main (void)\n{\n";

	generateFragShaderOutAssign(src, shaderSpec, useIntOutputs, inputPrefix, outputPrefix);

	src << "}\n";

	return src.str();
}

// ShaderExecutor

ShaderExecutor::ShaderExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec)
	: m_renderCtx	(renderCtx)
	, m_inputs		(shaderSpec.inputs)
	, m_outputs		(shaderSpec.outputs)
{
}

ShaderExecutor::~ShaderExecutor (void)
{
}

void ShaderExecutor::useProgram (void)
{
	DE_ASSERT(isOk());
	m_renderCtx.getFunctions().useProgram(getProgram());
}

// FragmentOutExecutor

struct FragmentOutputLayout
{
	std::vector<const Symbol*>		locationSymbols;		//! Symbols by location
	std::map<std::string, int>		locationMap;			//! Map from symbol name to start location
};

class FragmentOutExecutor : public ShaderExecutor
{
public:
								FragmentOutExecutor		(const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec);
								~FragmentOutExecutor	(void);

	void						execute					(int numValues, const void* const* inputs, void* const* outputs);

protected:
	const FragmentOutputLayout	m_outputLayout;
};

static FragmentOutputLayout computeFragmentOutputLayout (const std::vector<Symbol>& symbols)
{
	FragmentOutputLayout	ret;
	int						location	= 0;

	for (std::vector<Symbol>::const_iterator it = symbols.begin(); it != symbols.end(); ++it)
	{
		const int	numLocations	= glu::getDataTypeNumLocations(it->varType.getBasicType());

		TCU_CHECK_INTERNAL(!de::contains(ret.locationMap, it->name));
		de::insert(ret.locationMap, it->name, location);
		location += numLocations;

		for (int ndx = 0; ndx < numLocations; ++ndx)
			ret.locationSymbols.push_back(&*it);
	}

	return ret;
}

inline bool hasFloatRenderTargets (const glu::RenderContext& renderCtx)
{
	glu::ContextType type = renderCtx.getType();
	return glu::isContextTypeGLCore(type);
}

FragmentOutExecutor::FragmentOutExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec)
	: ShaderExecutor	(renderCtx, shaderSpec)
	, m_outputLayout	(computeFragmentOutputLayout(m_outputs))
{
}

FragmentOutExecutor::~FragmentOutExecutor (void)
{
}

inline int queryInt (const glw::Functions& gl, deUint32 pname)
{
	int value = 0;
	gl.getIntegerv(pname, &value);
	return value;
}

static tcu::TextureFormat getRenderbufferFormatForOutput (const glu::VarType& outputType, bool useIntOutputs)
{
	const tcu::TextureFormat::ChannelOrder channelOrderMap[] =
	{
		tcu::TextureFormat::R,
		tcu::TextureFormat::RG,
		tcu::TextureFormat::RGBA,	// No RGB variants available.
		tcu::TextureFormat::RGBA
	};

	const glu::DataType					basicType		= outputType.getBasicType();
	const int							numComps		= glu::getDataTypeNumComponents(basicType);
	tcu::TextureFormat::ChannelType		channelType;

	switch (glu::getDataTypeScalarType(basicType))
	{
		case glu::TYPE_UINT:	channelType = tcu::TextureFormat::UNSIGNED_INT32;												break;
		case glu::TYPE_INT:		channelType = tcu::TextureFormat::SIGNED_INT32;													break;
		case glu::TYPE_BOOL:	channelType = tcu::TextureFormat::SIGNED_INT32;													break;
		case glu::TYPE_FLOAT:	channelType = useIntOutputs ? tcu::TextureFormat::UNSIGNED_INT32 : tcu::TextureFormat::FLOAT;	break;
		default:
			throw tcu::InternalError("Invalid output type");
	}

	DE_ASSERT(de::inRange<int>(numComps, 1, DE_LENGTH_OF_ARRAY(channelOrderMap)));

	return tcu::TextureFormat(channelOrderMap[numComps-1], channelType);
}

void FragmentOutExecutor::execute (int numValues, const void* const* inputs, void* const* outputs)
{
	const glw::Functions&			gl					= m_renderCtx.getFunctions();
	const bool						useIntOutputs		= !hasFloatRenderTargets(m_renderCtx);
	const int						maxRenderbufferSize	= queryInt(gl, GL_MAX_RENDERBUFFER_SIZE);
	const int						framebufferW		= de::min(maxRenderbufferSize, numValues);
	const int						framebufferH		= (numValues / framebufferW) + ((numValues % framebufferW != 0) ? 1 : 0);

	glu::Framebuffer				framebuffer			(m_renderCtx);
	glu::RenderbufferVector			renderbuffers		(m_renderCtx, m_outputLayout.locationSymbols.size());

	vector<glu::VertexArrayBinding>	vertexArrays;
	vector<tcu::Vec2>				positions			(numValues);

	if (framebufferH > maxRenderbufferSize)
		throw tcu::NotSupportedError("Value count is too high for maximum supported renderbuffer size");

	// Compute positions - 1px points are used to drive fragment shading.
	for (int valNdx = 0; valNdx < numValues; valNdx++)
	{
		const int		ix		= valNdx % framebufferW;
		const int		iy		= valNdx / framebufferW;
		const float		fx		= -1.0f + 2.0f*((float(ix) + 0.5f) / float(framebufferW));
		const float		fy		= -1.0f + 2.0f*((float(iy) + 0.5f) / float(framebufferH));

		positions[valNdx] = tcu::Vec2(fx, fy);
	}

	// Vertex inputs.
	vertexArrays.push_back(glu::va::Float("a_position", 2, numValues, 0, (const float*)&positions[0]));

	for (int inputNdx = 0; inputNdx < (int)m_inputs.size(); inputNdx++)
	{
		const Symbol&		symbol		= m_inputs[inputNdx];
		const std::string	attribName	= "a_" + symbol.name;
		const void*			ptr			= inputs[inputNdx];
		const glu::DataType	basicType	= symbol.varType.getBasicType();
		const int			vecSize		= glu::getDataTypeScalarSize(basicType);

		if (glu::isDataTypeFloatOrVec(basicType))
			vertexArrays.push_back(glu::va::Float(attribName, vecSize, numValues, 0, (const float*)ptr));
		else if (glu::isDataTypeIntOrIVec(basicType))
			vertexArrays.push_back(glu::va::Int32(attribName, vecSize, numValues, 0, (const deInt32*)ptr));
		else if (glu::isDataTypeUintOrUVec(basicType))
			vertexArrays.push_back(glu::va::Uint32(attribName, vecSize, numValues, 0, (const deUint32*)ptr));
		else if (glu::isDataTypeMatrix(basicType))
		{
			int		numRows	= glu::getDataTypeMatrixNumRows(basicType);
			int		numCols	= glu::getDataTypeMatrixNumColumns(basicType);
			int		stride	= numRows * numCols * (int)sizeof(float);

			for (int colNdx = 0; colNdx < numCols; ++colNdx)
				vertexArrays.push_back(glu::va::Float(attribName, colNdx, numRows, numValues, stride, ((const float*)ptr) + colNdx * numRows));
		}
		else
			DE_ASSERT(false);
	}

	// Construct framebuffer.
	gl.bindFramebuffer(GL_FRAMEBUFFER, *framebuffer);

	for (int outNdx = 0; outNdx < (int)m_outputLayout.locationSymbols.size(); ++outNdx)
	{
		const Symbol&	output			= *m_outputLayout.locationSymbols[outNdx];
		const deUint32	renderbuffer	= renderbuffers[outNdx];
		const deUint32	format			= glu::getInternalFormat(getRenderbufferFormatForOutput(output.varType, useIntOutputs));

		gl.bindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
		gl.renderbufferStorage(GL_RENDERBUFFER, format, framebufferW, framebufferH);
		gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+outNdx, GL_RENDERBUFFER, renderbuffer);
	}
	gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set up framebuffer object");
	TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);

	{
		vector<deUint32> drawBuffers(m_outputLayout.locationSymbols.size());
		for (int ndx = 0; ndx < (int)m_outputLayout.locationSymbols.size(); ndx++)
			drawBuffers[ndx] = GL_COLOR_ATTACHMENT0+ndx;
		gl.drawBuffers((int)drawBuffers.size(), &drawBuffers[0]);
		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawBuffers()");
	}

	// Render
	gl.viewport(0, 0, framebufferW, framebufferH);
	glu::draw(m_renderCtx, this->getProgram(), (int)vertexArrays.size(), &vertexArrays[0],
			  glu::pr::Points(numValues));
	GLU_EXPECT_NO_ERROR(gl.getError(), "Error in draw");

	// Read back pixels.
	{
		tcu::TextureLevel	tmpBuf;

		// \todo [2013-08-07 pyry] Some fast-paths could be added here.

		for (int outNdx = 0; outNdx < (int)m_outputs.size(); ++outNdx)
		{
			const Symbol&				output			= m_outputs[outNdx];
			const int					outSize			= output.varType.getScalarSize();
			const int					outVecSize		= glu::getDataTypeNumComponents(output.varType.getBasicType());
			const int					outNumLocs		= glu::getDataTypeNumLocations(output.varType.getBasicType());
			deUint32*					dstPtrBase		= static_cast<deUint32*>(outputs[outNdx]);
			const tcu::TextureFormat	format			= getRenderbufferFormatForOutput(output.varType, useIntOutputs);
			const tcu::TextureFormat	readFormat		(tcu::TextureFormat::RGBA, format.type);
			const int					outLocation		= de::lookup(m_outputLayout.locationMap, output.name);

			tmpBuf.setStorage(readFormat, framebufferW, framebufferH);

			for (int locNdx = 0; locNdx < outNumLocs; ++locNdx)
			{
				gl.readBuffer(GL_COLOR_ATTACHMENT0 + outLocation + locNdx);
				glu::readPixels(m_renderCtx, 0, 0, tmpBuf.getAccess());
				GLU_EXPECT_NO_ERROR(gl.getError(), "Reading pixels");

				if (outSize == 4 && outNumLocs == 1)
					deMemcpy(dstPtrBase, tmpBuf.getAccess().getDataPtr(), numValues*outVecSize*sizeof(deUint32));
				else
				{
					for (int valNdx = 0; valNdx < numValues; valNdx++)
					{
						const deUint32* srcPtr = (const deUint32*)tmpBuf.getAccess().getDataPtr() + valNdx*4;
						deUint32*		dstPtr = &dstPtrBase[outSize*valNdx + outVecSize*locNdx];
						deMemcpy(dstPtr, srcPtr, outVecSize*sizeof(deUint32));
					}
				}
			}
		}
	}

	// \todo [2013-08-07 pyry] Clear draw buffers & viewport?
	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
}

// VertexShaderExecutor

class VertexShaderExecutor : public FragmentOutExecutor
{
public:
								VertexShaderExecutor	(const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec);
								~VertexShaderExecutor	(void);

	bool						isOk					(void) const				{ return m_program.isOk();			}
	void						log						(tcu::TestLog& dst) const	{ dst << m_program;					}
	deUint32					getProgram				(void) const				{ return m_program.getProgram();	}

protected:
	const glu::ShaderProgram	m_program;
};

VertexShaderExecutor::VertexShaderExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec)
	: FragmentOutExecutor	(renderCtx, shaderSpec)
	, m_program				(renderCtx,
							 glu::ProgramSources() << glu::VertexSource(generateVertexShader(shaderSpec, "a_", "vtx_out_"))
												   << glu::FragmentSource(generatePassthroughFragmentShader(shaderSpec, !hasFloatRenderTargets(renderCtx), m_outputLayout.locationMap, "vtx_out_", "o_")))
{
}

VertexShaderExecutor::~VertexShaderExecutor (void)
{
}

// GeometryShaderExecutor

class GeometryShaderExecutor : public FragmentOutExecutor
{
public:
	static GeometryShaderExecutor*	create					(const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec);

									~GeometryShaderExecutor	(void);

	bool							isOk					(void) const				{ return m_program.isOk();			}
	void							log						(tcu::TestLog& dst) const	{ dst << m_program;					}
	deUint32						getProgram				(void) const				{ return m_program.getProgram();	}

protected:
	const glu::ShaderProgram		m_program;

private:
									GeometryShaderExecutor	(const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec);
};

GeometryShaderExecutor* GeometryShaderExecutor::create (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec)
{
	if (glu::glslVersionIsES(shaderSpec.version) && shaderSpec.version <= glu::GLSL_VERSION_310_ES
		&& !contextSupports(renderCtx.getType(), glu::ApiType::core(4, 5)))
		checkExtension(renderCtx, "GL_EXT_geometry_shader");

	return new GeometryShaderExecutor(renderCtx, shaderSpec);
}

GeometryShaderExecutor::GeometryShaderExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec)
	: FragmentOutExecutor	(renderCtx, shaderSpec)
	, m_program				(renderCtx,
							 glu::ProgramSources() << glu::VertexSource(generatePassthroughVertexShader(shaderSpec, "a_", "vtx_out_"))
												   << glu::GeometrySource(generateGeometryShader(shaderSpec, "vtx_out_", "geom_out_"))
												   << glu::FragmentSource(generatePassthroughFragmentShader(shaderSpec, !hasFloatRenderTargets(renderCtx), m_outputLayout.locationMap, "geom_out_", "o_")))
{
}

GeometryShaderExecutor::~GeometryShaderExecutor (void)
{
}

// FragmentShaderExecutor

class FragmentShaderExecutor : public FragmentOutExecutor
{
public:
								FragmentShaderExecutor	(const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec);
								~FragmentShaderExecutor	(void);

	bool						isOk					(void) const				{ return m_program.isOk();			}
	void						log						(tcu::TestLog& dst) const	{ dst << m_program;					}
	deUint32					getProgram				(void) const				{ return m_program.getProgram();	}

protected:
	const glu::ShaderProgram	m_program;
};

FragmentShaderExecutor::FragmentShaderExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec)
	: FragmentOutExecutor	(renderCtx, shaderSpec)
	, m_program				(renderCtx,
							 glu::ProgramSources() << glu::VertexSource(generatePassthroughVertexShader(shaderSpec, "a_", "vtx_out_"))
												   << glu::FragmentSource(generateFragmentShader(shaderSpec, !hasFloatRenderTargets(renderCtx), m_outputLayout.locationMap, "vtx_out_", "o_")))
{
}

FragmentShaderExecutor::~FragmentShaderExecutor (void)
{
}

// Shared utilities for compute and tess executors

static deUint32 getVecStd430ByteAlignment (glu::DataType type)
{
	switch (glu::getDataTypeScalarSize(type))
	{
		case 1:		return 4u;
		case 2:		return 8u;
		case 3:		return 16u;
		case 4:		return 16u;
		default:
			DE_ASSERT(false);
			return 0u;
	}
}

class BufferIoExecutor : public ShaderExecutor
{
public:
						BufferIoExecutor	(const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec, const glu::ProgramSources& sources);
						~BufferIoExecutor	(void);

	bool				isOk				(void) const				{ return m_program.isOk();			}
	void				log					(tcu::TestLog& dst) const	{ dst << m_program;					}
	deUint32			getProgram			(void) const				{ return m_program.getProgram();	}

protected:
	enum
	{
		INPUT_BUFFER_BINDING	= 0,
		OUTPUT_BUFFER_BINDING	= 1,
	};

	void				initBuffers			(int numValues);
	deUint32			getInputBuffer		(void) const		{ return *m_inputBuffer;					}
	deUint32			getOutputBuffer		(void) const		{ return *m_outputBuffer;					}
	deUint32			getInputStride		(void) const		{ return getLayoutStride(m_inputLayout);	}
	deUint32			getOutputStride		(void) const		{ return getLayoutStride(m_outputLayout);	}

	void				uploadInputBuffer	(const void* const* inputPtrs, int numValues);
	void				readOutputBuffer	(void* const* outputPtrs, int numValues);

	static void			declareBufferBlocks	(std::ostream& src, const ShaderSpec& spec);
	static void			generateExecBufferIo(std::ostream& src, const ShaderSpec& spec, const char* invocationNdxName);

	glu::ShaderProgram	m_program;

private:
	struct VarLayout
	{
		deUint32		offset;
		deUint32		stride;
		deUint32		matrixStride;

		VarLayout (void) : offset(0), stride(0), matrixStride(0) {}
	};

	void				resizeInputBuffer	(int newSize);
	void				resizeOutputBuffer	(int newSize);

	static void			computeVarLayout	(const std::vector<Symbol>& symbols, std::vector<VarLayout>* layout);
	static deUint32		getLayoutStride		(const vector<VarLayout>& layout);

	static void			copyToBuffer		(const glu::VarType& varType, const VarLayout& layout, int numValues, const void* srcBasePtr, void* dstBasePtr);
	static void			copyFromBuffer		(const glu::VarType& varType, const VarLayout& layout, int numValues, const void* srcBasePtr, void* dstBasePtr);

	glu::Buffer			m_inputBuffer;
	glu::Buffer			m_outputBuffer;

	vector<VarLayout>	m_inputLayout;
	vector<VarLayout>	m_outputLayout;
};

BufferIoExecutor::BufferIoExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec, const glu::ProgramSources& sources)
	: ShaderExecutor	(renderCtx, shaderSpec)
	, m_program			(renderCtx, sources)
	, m_inputBuffer		(renderCtx)
	, m_outputBuffer	(renderCtx)
{
	computeVarLayout(m_inputs, &m_inputLayout);
	computeVarLayout(m_outputs, &m_outputLayout);
}

BufferIoExecutor::~BufferIoExecutor (void)
{
}

void BufferIoExecutor::resizeInputBuffer (int newSize)
{
	const glw::Functions& gl = m_renderCtx.getFunctions();
	gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, *m_inputBuffer);
	gl.bufferData(GL_SHADER_STORAGE_BUFFER, newSize, DE_NULL, GL_STATIC_DRAW);
	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to allocate input buffer");
}

void BufferIoExecutor::resizeOutputBuffer (int newSize)
{
	const glw::Functions& gl = m_renderCtx.getFunctions();
	gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, *m_outputBuffer);
	gl.bufferData(GL_SHADER_STORAGE_BUFFER, newSize, DE_NULL, GL_STATIC_DRAW);
	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to allocate output buffer");
}

void BufferIoExecutor::initBuffers (int numValues)
{
	const deUint32		inputStride			= getLayoutStride(m_inputLayout);
	const deUint32		outputStride		= getLayoutStride(m_outputLayout);
	const int			inputBufferSize		= numValues * inputStride;
	const int			outputBufferSize	= numValues * outputStride;

	resizeInputBuffer(inputBufferSize);
	resizeOutputBuffer(outputBufferSize);
}

void BufferIoExecutor::computeVarLayout (const std::vector<Symbol>& symbols, std::vector<VarLayout>* layout)
{
	deUint32	maxAlignment	= 0;
	deUint32	curOffset		= 0;

	DE_ASSERT(layout->empty());
	layout->resize(symbols.size());

	for (size_t varNdx = 0; varNdx < symbols.size(); varNdx++)
	{
		const Symbol&		symbol		= symbols[varNdx];
		const glu::DataType	basicType	= symbol.varType.getBasicType();
		VarLayout&			layoutEntry	= (*layout)[varNdx];

		if (glu::isDataTypeScalarOrVector(basicType))
		{
			const deUint32	alignment	= getVecStd430ByteAlignment(basicType);
			const deUint32	size		= (deUint32)glu::getDataTypeScalarSize(basicType)*(int)sizeof(deUint32);

			curOffset		= (deUint32)deAlign32((int)curOffset, (int)alignment);
			maxAlignment	= de::max(maxAlignment, alignment);

			layoutEntry.offset			= curOffset;
			layoutEntry.matrixStride	= 0;

			curOffset += size;
		}
		else if (glu::isDataTypeMatrix(basicType))
		{
			const int				numVecs			= glu::getDataTypeMatrixNumColumns(basicType);
			const glu::DataType		vecType			= glu::getDataTypeFloatVec(glu::getDataTypeMatrixNumRows(basicType));
			const deUint32			vecAlignment	= getVecStd430ByteAlignment(vecType);

			curOffset		= (deUint32)deAlign32((int)curOffset, (int)vecAlignment);
			maxAlignment	= de::max(maxAlignment, vecAlignment);

			layoutEntry.offset			= curOffset;
			layoutEntry.matrixStride	= vecAlignment;

			curOffset += vecAlignment*numVecs;
		}
		else
			DE_ASSERT(false);
	}

	{
		const deUint32	totalSize	= (deUint32)deAlign32(curOffset, maxAlignment);

		for (vector<VarLayout>::iterator varIter = layout->begin(); varIter != layout->end(); ++varIter)
			varIter->stride = totalSize;
	}
}

inline deUint32 BufferIoExecutor::getLayoutStride (const vector<VarLayout>& layout)
{
	return layout.empty() ? 0 : layout[0].stride;
}

void BufferIoExecutor::copyToBuffer (const glu::VarType& varType, const VarLayout& layout, int numValues, const void* srcBasePtr, void* dstBasePtr)
{
	if (varType.isBasicType())
	{
		const glu::DataType		basicType		= varType.getBasicType();
		const bool				isMatrix		= glu::isDataTypeMatrix(basicType);
		const int				scalarSize		= glu::getDataTypeScalarSize(basicType);
		const int				numVecs			= isMatrix ? glu::getDataTypeMatrixNumColumns(basicType) : 1;
		const int				numComps		= scalarSize / numVecs;

		for (int elemNdx = 0; elemNdx < numValues; elemNdx++)
		{
			for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
			{
				const int		srcOffset		= (int)sizeof(deUint32)*(elemNdx*scalarSize + vecNdx*numComps);
				const int		dstOffset		= layout.offset + layout.stride*elemNdx + (isMatrix ? layout.matrixStride*vecNdx : 0);
				const deUint8*	srcPtr			= (const deUint8*)srcBasePtr + srcOffset;
				deUint8*		dstPtr			= (deUint8*)dstBasePtr + dstOffset;

				deMemcpy(dstPtr, srcPtr, sizeof(deUint32)*numComps);
			}
		}
	}
	else
		throw tcu::InternalError("Unsupported type");
}

void BufferIoExecutor::copyFromBuffer (const glu::VarType& varType, const VarLayout& layout, int numValues, const void* srcBasePtr, void* dstBasePtr)
{
	if (varType.isBasicType())
	{
		const glu::DataType		basicType		= varType.getBasicType();
		const bool				isMatrix		= glu::isDataTypeMatrix(basicType);
		const int				scalarSize		= glu::getDataTypeScalarSize(basicType);
		const int				numVecs			= isMatrix ? glu::getDataTypeMatrixNumColumns(basicType) : 1;
		const int				numComps		= scalarSize / numVecs;

		for (int elemNdx = 0; elemNdx < numValues; elemNdx++)
		{
			for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
			{
				const int		srcOffset		= layout.offset + layout.stride*elemNdx + (isMatrix ? layout.matrixStride*vecNdx : 0);
				const int		dstOffset		= (int)sizeof(deUint32)*(elemNdx*scalarSize + vecNdx*numComps);
				const deUint8*	srcPtr			= (const deUint8*)srcBasePtr + srcOffset;
				deUint8*		dstPtr			= (deUint8*)dstBasePtr + dstOffset;

				deMemcpy(dstPtr, srcPtr, sizeof(deUint32)*numComps);
			}
		}
	}
	else
		throw tcu::InternalError("Unsupported type");
}

void BufferIoExecutor::uploadInputBuffer (const void* const* inputPtrs, int numValues)
{
	const glw::Functions&	gl				= m_renderCtx.getFunctions();
	const deUint32			buffer			= *m_inputBuffer;
	const deUint32			inputStride		= getLayoutStride(m_inputLayout);
	const int				inputBufferSize	= inputStride*numValues;

	if (inputBufferSize == 0)
		return; // No inputs

	gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
	void* mapPtr = gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, inputBufferSize, GL_MAP_WRITE_BIT);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange()");
	TCU_CHECK(mapPtr);

	try
	{
		DE_ASSERT(m_inputs.size() == m_inputLayout.size());
		for (size_t inputNdx = 0; inputNdx < m_inputs.size(); ++inputNdx)
		{
			const glu::VarType&		varType		= m_inputs[inputNdx].varType;
			const VarLayout&		layout		= m_inputLayout[inputNdx];

			copyToBuffer(varType, layout, numValues, inputPtrs[inputNdx], mapPtr);
		}
	}
	catch (...)
	{
		gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
		throw;
	}

	gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer()");
}

void BufferIoExecutor::readOutputBuffer (void* const* outputPtrs, int numValues)
{
	const glw::Functions&	gl					= m_renderCtx.getFunctions();
	const deUint32			buffer				= *m_outputBuffer;
	const deUint32			outputStride		= getLayoutStride(m_outputLayout);
	const int				outputBufferSize	= numValues*outputStride;

	DE_ASSERT(outputBufferSize > 0); // At least some outputs are required.

	gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
	void* mapPtr = gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, outputBufferSize, GL_MAP_READ_BIT);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange()");
	TCU_CHECK(mapPtr);

	try
	{
		DE_ASSERT(m_outputs.size() == m_outputLayout.size());
		for (size_t outputNdx = 0; outputNdx < m_outputs.size(); ++outputNdx)
		{
			const glu::VarType&		varType		= m_outputs[outputNdx].varType;
			const VarLayout&		layout		= m_outputLayout[outputNdx];

			copyFromBuffer(varType, layout, numValues, mapPtr, outputPtrs[outputNdx]);
		}
	}
	catch (...)
	{
		gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
		throw;
	}

	gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer()");
}

void BufferIoExecutor::declareBufferBlocks (std::ostream& src, const ShaderSpec& spec)
{
	// Input struct
	if (!spec.inputs.empty())
	{
		glu::StructType inputStruct("Inputs");
		for (vector<Symbol>::const_iterator symIter = spec.inputs.begin(); symIter != spec.inputs.end(); ++symIter)
			inputStruct.addMember(symIter->name.c_str(), symIter->varType);
		src << glu::declare(&inputStruct) << ";\n";
	}

	// Output struct
	{
		glu::StructType outputStruct("Outputs");
		for (vector<Symbol>::const_iterator symIter = spec.outputs.begin(); symIter != spec.outputs.end(); ++symIter)
			outputStruct.addMember(symIter->name.c_str(), symIter->varType);
		src << glu::declare(&outputStruct) << ";\n";
	}

	src << "\n";

	if (!spec.inputs.empty())
	{
		src	<< "layout(binding = " << int(INPUT_BUFFER_BINDING) << ", std430) buffer InBuffer\n"
			<< "{\n"
			<< "	Inputs inputs[];\n"
			<< "};\n";
	}

	src	<< "layout(binding = " << int(OUTPUT_BUFFER_BINDING) << ", std430) buffer OutBuffer\n"
		<< "{\n"
		<< "	Outputs outputs[];\n"
		<< "};\n"
		<< "\n";
}

void BufferIoExecutor::generateExecBufferIo (std::ostream& src, const ShaderSpec& spec, const char* invocationNdxName)
{
	for (vector<Symbol>::const_iterator symIter = spec.inputs.begin(); symIter != spec.inputs.end(); ++symIter)
		src << "\t" << glu::declare(symIter->varType, symIter->name) << " = inputs[" << invocationNdxName << "]." << symIter->name << ";\n";

	for (vector<Symbol>::const_iterator symIter = spec.outputs.begin(); symIter != spec.outputs.end(); ++symIter)
		src << "\t" << glu::declare(symIter->varType, symIter->name) << ";\n";

	src << "\n";

	{
		std::istringstream	opSrc	(spec.source);
		std::string			line;

		while (std::getline(opSrc, line))
			src << "\t" << line << "\n";
	}

	src << "\n";
	for (vector<Symbol>::const_iterator symIter = spec.outputs.begin(); symIter != spec.outputs.end(); ++symIter)
		src << "\toutputs[" << invocationNdxName << "]." << symIter->name << " = " << symIter->name << ";\n";
}

// ComputeShaderExecutor

class ComputeShaderExecutor : public BufferIoExecutor
{
public:
						ComputeShaderExecutor	(const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec);
						~ComputeShaderExecutor	(void);

	void				execute					(int numValues, const void* const* inputs, void* const* outputs);

protected:
	static std::string	generateComputeShader	(const ShaderSpec& spec);

	tcu::IVec3			m_maxWorkSize;
};

std::string ComputeShaderExecutor::generateComputeShader (const ShaderSpec& spec)
{
	std::ostringstream src;

	src << glu::getGLSLVersionDeclaration(spec.version) << "\n";

	if (!spec.globalDeclarations.empty())
		src << spec.globalDeclarations << "\n";

	src << "layout(local_size_x = 1) in;\n"
		<< "\n";

	declareBufferBlocks(src, spec);

	src << "void main (void)\n"
		<< "{\n"
		<< "	uint invocationNdx = gl_NumWorkGroups.x*gl_NumWorkGroups.y*gl_WorkGroupID.z\n"
		<< "	                   + gl_NumWorkGroups.x*gl_WorkGroupID.y + gl_WorkGroupID.x;\n";

	generateExecBufferIo(src, spec, "invocationNdx");

	src << "}\n";

	return src.str();
}

ComputeShaderExecutor::ComputeShaderExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec)
	: BufferIoExecutor	(renderCtx, shaderSpec,
						 glu::ProgramSources() << glu::ComputeSource(generateComputeShader(shaderSpec)))
{
	m_maxWorkSize	= tcu::IVec3(128,128,64); // Minimum in 3plus
}

ComputeShaderExecutor::~ComputeShaderExecutor (void)
{
}

void ComputeShaderExecutor::execute (int numValues, const void* const* inputs, void* const* outputs)
{
	const glw::Functions&	gl						= m_renderCtx.getFunctions();
	const int				maxValuesPerInvocation	= m_maxWorkSize[0];
	const deUint32			inputStride				= getInputStride();
	const deUint32			outputStride			= getOutputStride();

	initBuffers(numValues);

	// Setup input buffer & copy data
	uploadInputBuffer(inputs, numValues);

	// Perform compute invocations
	{
		int curOffset = 0;
		while (curOffset < numValues)
		{
			const int numToExec = de::min(maxValuesPerInvocation, numValues-curOffset);

			if (inputStride > 0)
				gl.bindBufferRange(GL_SHADER_STORAGE_BUFFER, INPUT_BUFFER_BINDING, getInputBuffer(), curOffset*inputStride, numToExec*inputStride);

			gl.bindBufferRange(GL_SHADER_STORAGE_BUFFER, OUTPUT_BUFFER_BINDING, getOutputBuffer(), curOffset*outputStride, numToExec*outputStride);
			GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange(GL_SHADER_STORAGE_BUFFER)");

			gl.dispatchCompute(numToExec, 1, 1);
			GLU_EXPECT_NO_ERROR(gl.getError(), "glDispatchCompute()");

			curOffset += numToExec;
		}
	}

	// Read back data
	readOutputBuffer(outputs, numValues);
}

// Tessellation utils

static std::string generateVertexShaderForTess (glu::GLSLVersion version)
{
	std::ostringstream	src;

	src << glu::getGLSLVersionDeclaration(version) << "\n";

	src << "void main (void)\n{\n"
		<< "	gl_Position = vec4(gl_VertexID/2, gl_VertexID%2, 0.0, 1.0);\n"
		<< "}\n";

	return src.str();
}

void checkTessSupport (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec, glu::ShaderType stage)
{
	const int numBlockRequired = 2; // highest binding is always 1 (output) i.e. count == 2

	if (glu::glslVersionIsES(shaderSpec.version) && shaderSpec.version <= glu::GLSL_VERSION_310_ES
		&& !contextSupports(renderCtx.getType(), glu::ApiType::core(4, 5)))
		checkExtension(renderCtx, "GL_EXT_tessellation_shader");

	if (stage == glu::SHADERTYPE_TESSELLATION_CONTROL)
		checkLimit(renderCtx, GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS, numBlockRequired);
	else if (stage == glu::SHADERTYPE_TESSELLATION_EVALUATION)
		checkLimit(renderCtx, GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS, numBlockRequired);
	else
		DE_ASSERT(false);
}

// TessControlExecutor

class TessControlExecutor : public BufferIoExecutor
{
public:
	static TessControlExecutor*	create						(const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec);

								~TessControlExecutor		(void);

	void						execute						(int numValues, const void* const* inputs, void* const* outputs);


protected:
	static std::string			generateTessControlShader	(const ShaderSpec& shaderSpec);

private:
								TessControlExecutor			(const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec);
};

TessControlExecutor* TessControlExecutor::create (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec)
{
	checkTessSupport(renderCtx, shaderSpec, glu::SHADERTYPE_TESSELLATION_CONTROL);

	return new TessControlExecutor(renderCtx, shaderSpec);
}

std::string TessControlExecutor::generateTessControlShader (const ShaderSpec& shaderSpec)
{
	std::ostringstream src;

	src << glu::getGLSLVersionDeclaration(shaderSpec.version) << "\n";

	if (glu::glslVersionIsES(shaderSpec.version) && shaderSpec.version <= glu::GLSL_VERSION_310_ES)
		src << "#extension GL_EXT_tessellation_shader : require\n";

	if (!shaderSpec.globalDeclarations.empty())
		src << shaderSpec.globalDeclarations << "\n";

	src << "\nlayout(vertices = 1) out;\n\n";

	declareBufferBlocks(src, shaderSpec);

	src << "void main (void)\n{\n";

	for (int ndx = 0; ndx < 2; ndx++)
		src << "\tgl_TessLevelInner[" << ndx << "] = 1.0;\n";

	for (int ndx = 0; ndx < 4; ndx++)
		src << "\tgl_TessLevelOuter[" << ndx << "] = 1.0;\n";

	src << "\n"
		<< "\thighp uint invocationId = uint(gl_PrimitiveID);\n";

	generateExecBufferIo(src, shaderSpec, "invocationId");

	src << "}\n";

	return src.str();
}

static std::string generateEmptyTessEvalShader (glu::GLSLVersion version)
{
	std::ostringstream src;

	src << glu::getGLSLVersionDeclaration(version) << "\n";

	if (glu::glslVersionIsES(version) && version <= glu::GLSL_VERSION_310_ES)
		src << "#extension GL_EXT_tessellation_shader : require\n\n";

	src << "layout(triangles, ccw) in;\n";

	src << "\nvoid main (void)\n{\n"
		<< "\tgl_Position = vec4(gl_TessCoord.xy, 0.0, 1.0);\n"
		<< "}\n";

	return src.str();
}

TessControlExecutor::TessControlExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec)
	: BufferIoExecutor	(renderCtx, shaderSpec, glu::ProgramSources()
							<< glu::VertexSource(generateVertexShaderForTess(shaderSpec.version))
							<< glu::TessellationControlSource(generateTessControlShader(shaderSpec))
							<< glu::TessellationEvaluationSource(generateEmptyTessEvalShader(shaderSpec.version))
							<< glu::FragmentSource(generateEmptyFragmentSource(shaderSpec.version)))
{
}

TessControlExecutor::~TessControlExecutor (void)
{
}

void TessControlExecutor::execute (int numValues, const void* const* inputs, void* const* outputs)
{
	const glw::Functions&	gl	= m_renderCtx.getFunctions();

	initBuffers(numValues);

	// Setup input buffer & copy data
	uploadInputBuffer(inputs, numValues);

	if (!m_inputs.empty())
		gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, INPUT_BUFFER_BINDING, getInputBuffer());

	gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, OUTPUT_BUFFER_BINDING, getOutputBuffer());

	deUint32 vertexArray;
	gl.genVertexArrays(1, &vertexArray);
	gl.bindVertexArray(vertexArray);

	// Render patches
	gl.patchParameteri(GL_PATCH_VERTICES, 3);
	gl.drawArrays(GL_PATCHES, 0, 3*numValues);

	gl.bindVertexArray(0);
	gl.deleteVertexArrays(1, &vertexArray);

	// Read back data
	readOutputBuffer(outputs, numValues);
}

// TessEvaluationExecutor

class TessEvaluationExecutor : public BufferIoExecutor
{
public:
	static TessEvaluationExecutor*	create					(const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec);

									~TessEvaluationExecutor	(void);

	void							execute					(int numValues, const void* const* inputs, void* const* outputs);


protected:
	static std::string				generateTessEvalShader	(const ShaderSpec& shaderSpec);

private:
									TessEvaluationExecutor	(const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec);
};

TessEvaluationExecutor* TessEvaluationExecutor::create (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec)
{
	checkTessSupport(renderCtx, shaderSpec, glu::SHADERTYPE_TESSELLATION_EVALUATION);

	return new TessEvaluationExecutor(renderCtx, shaderSpec);
}

static std::string generatePassthroughTessControlShader (glu::GLSLVersion version)
{
	std::ostringstream src;

	src << glu::getGLSLVersionDeclaration(version) << "\n";

	if (glu::glslVersionIsES(version) && version <= glu::GLSL_VERSION_310_ES)
		src << "#extension GL_EXT_tessellation_shader : require\n\n";

	src << "layout(vertices = 1) out;\n\n";

	src << "void main (void)\n{\n";

	for (int ndx = 0; ndx < 2; ndx++)
		src << "\tgl_TessLevelInner[" << ndx << "] = 1.0;\n";

	for (int ndx = 0; ndx < 4; ndx++)
		src << "\tgl_TessLevelOuter[" << ndx << "] = 1.0;\n";

	src << "}\n";

	return src.str();
}

std::string TessEvaluationExecutor::generateTessEvalShader (const ShaderSpec& shaderSpec)
{
	std::ostringstream src;

	src << glu::getGLSLVersionDeclaration(shaderSpec.version) << "\n";

	if (glu::glslVersionIsES(shaderSpec.version) && shaderSpec.version <= glu::GLSL_VERSION_310_ES)
		src << "#extension GL_EXT_tessellation_shader : require\n";

	if (!shaderSpec.globalDeclarations.empty())
		src << shaderSpec.globalDeclarations << "\n";

	src << "\n";

	src << "layout(isolines, equal_spacing) in;\n\n";

	declareBufferBlocks(src, shaderSpec);

	src << "void main (void)\n{\n"
		<< "\tgl_Position = vec4(gl_TessCoord.x, 0.0, 0.0, 1.0);\n"
		<< "\thighp uint invocationId = uint(gl_PrimitiveID)*2u + (gl_TessCoord.x > 0.5 ? 1u : 0u);\n";

	generateExecBufferIo(src, shaderSpec, "invocationId");

	src	<< "}\n";

	return src.str();
}

TessEvaluationExecutor::TessEvaluationExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec)
	: BufferIoExecutor	(renderCtx, shaderSpec, glu::ProgramSources()
							<< glu::VertexSource(generateVertexShaderForTess(shaderSpec.version))
							<< glu::TessellationControlSource(generatePassthroughTessControlShader(shaderSpec.version))
							<< glu::TessellationEvaluationSource(generateTessEvalShader(shaderSpec))
							<< glu::FragmentSource(generateEmptyFragmentSource(shaderSpec.version)))
{
}

TessEvaluationExecutor::~TessEvaluationExecutor (void)
{
}

void TessEvaluationExecutor::execute (int numValues, const void* const* inputs, void* const* outputs)
{
	const glw::Functions&	gl				= m_renderCtx.getFunctions();
	const int				alignedValues	= deAlign32(numValues, 2);

	// Initialize buffers with aligned value count to make room for padding
	initBuffers(alignedValues);

	// Setup input buffer & copy data
	uploadInputBuffer(inputs, numValues);

	// \todo [2014-06-26 pyry] Duplicate last value in the buffer to prevent infinite loops for example?

	if (!m_inputs.empty())
		gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, INPUT_BUFFER_BINDING, getInputBuffer());

	gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, OUTPUT_BUFFER_BINDING, getOutputBuffer());

	deUint32 vertexArray;
	gl.genVertexArrays(1, &vertexArray);
	gl.bindVertexArray(vertexArray);

	// Render patches
	gl.patchParameteri(GL_PATCH_VERTICES, 2);
	gl.drawArrays(GL_PATCHES, 0, alignedValues);

	gl.bindVertexArray(0);
	gl.deleteVertexArrays(1, &vertexArray);

	// Read back data
	readOutputBuffer(outputs, numValues);
}

// Utilities

ShaderExecutor* createExecutor (const glu::RenderContext& renderCtx, glu::ShaderType shaderType, const ShaderSpec& shaderSpec)
{
	switch (shaderType)
	{
		case glu::SHADERTYPE_VERTEX:					return new VertexShaderExecutor			(renderCtx, shaderSpec);
		case glu::SHADERTYPE_TESSELLATION_CONTROL:		return TessControlExecutor::create		(renderCtx, shaderSpec);
		case glu::SHADERTYPE_TESSELLATION_EVALUATION:	return TessEvaluationExecutor::create	(renderCtx, shaderSpec);
		case glu::SHADERTYPE_GEOMETRY:					return GeometryShaderExecutor::create	(renderCtx, shaderSpec);
		case glu::SHADERTYPE_FRAGMENT:					return new FragmentShaderExecutor		(renderCtx, shaderSpec);
		case glu::SHADERTYPE_COMPUTE:					return new ComputeShaderExecutor		(renderCtx, shaderSpec);
		default:
			throw tcu::InternalError("Unsupported shader type");
	}
}

bool  executorSupported(glu::ShaderType shaderType)
{
	switch (shaderType)
	{
	case glu::SHADERTYPE_VERTEX:
	case glu::SHADERTYPE_TESSELLATION_CONTROL:
	case glu::SHADERTYPE_TESSELLATION_EVALUATION:
	case glu::SHADERTYPE_GEOMETRY:
	case glu::SHADERTYPE_FRAGMENT:
	case glu::SHADERTYPE_COMPUTE:
		return true;
	default:
		return false;
	}
}

} // ShaderExecUtil
} // gls
} // deqp
