Home | History | Annotate | Download | only in glshared
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL (ES) Module
      3  * -----------------------------------------------
      4  *
      5  * Copyright 2014 The Android Open Source Project
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  *
     19  *//*!
     20  * \file
     21  * \brief Shader execution utilities.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "glsShaderExecUtil.hpp"
     25 #include "gluRenderContext.hpp"
     26 #include "gluDrawUtil.hpp"
     27 #include "gluObjectWrapper.hpp"
     28 #include "gluShaderProgram.hpp"
     29 #include "gluTextureUtil.hpp"
     30 #include "gluProgramInterfaceQuery.hpp"
     31 #include "gluPixelTransfer.hpp"
     32 #include "tcuTestLog.hpp"
     33 #include "glwFunctions.hpp"
     34 #include "glwEnums.hpp"
     35 #include "deSTLUtil.hpp"
     36 #include "deStringUtil.hpp"
     37 #include "deUniquePtr.hpp"
     38 #include "deMemory.h"
     39 
     40 #include <map>
     41 
     42 namespace deqp
     43 {
     44 namespace gls
     45 {
     46 
     47 namespace ShaderExecUtil
     48 {
     49 
     50 using std::vector;
     51 
     52 static bool isExtensionSupported (const glu::RenderContext& renderCtx, const std::string& extension)
     53 {
     54 	const glw::Functions&	gl		= renderCtx.getFunctions();
     55 	int						numExts	= 0;
     56 
     57 	gl.getIntegerv(GL_NUM_EXTENSIONS, &numExts);
     58 
     59 	for (int ndx = 0; ndx < numExts; ndx++)
     60 	{
     61 		const char* curExt = (const char*)gl.getStringi(GL_EXTENSIONS, ndx);
     62 
     63 		if (extension == curExt)
     64 			return true;
     65 	}
     66 
     67 	return false;
     68 }
     69 
     70 static void checkExtension (const glu::RenderContext& renderCtx, const std::string& extension)
     71 {
     72 	if (!isExtensionSupported(renderCtx, extension))
     73 		throw tcu::NotSupportedError(extension + " is not supported");
     74 }
     75 
     76 // Shader utilities
     77 
     78 static std::string generateVertexShader (const ShaderSpec& shaderSpec)
     79 {
     80 	const bool			usesInout	= glu::glslVersionUsesInOutQualifiers(shaderSpec.version);
     81 	const char*			in			= usesInout ? "in"		: "attribute";
     82 	const char*			out			= usesInout ? "out"		: "varying";
     83 	std::ostringstream	src;
     84 
     85 	src << glu::getGLSLVersionDeclaration(shaderSpec.version) << "\n";
     86 
     87 	if (!shaderSpec.globalDeclarations.empty())
     88 		src << shaderSpec.globalDeclarations << "\n";
     89 
     90 	for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input)
     91 		src << in << " " << glu::declare(input->varType, input->name) << ";\n";
     92 
     93 	for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output)
     94 	{
     95 		DE_ASSERT(output->varType.isBasicType());
     96 
     97 		if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType()))
     98 		{
     99 			const int				vecSize		= glu::getDataTypeScalarSize(output->varType.getBasicType());
    100 			const glu::DataType		intBaseType	= vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
    101 			const glu::VarType		intType		(intBaseType, glu::PRECISION_HIGHP);
    102 
    103 			src << "flat " << out << " " << glu::declare(intType, "o_" + output->name) << ";\n";
    104 		}
    105 		else
    106 			src << "flat " << out << " " << glu::declare(output->varType, output->name) << ";\n";
    107 	}
    108 
    109 	src << "\n"
    110 		<< "void main (void)\n"
    111 		<< "{\n"
    112 		<< "	gl_Position = vec4(0.0);\n"
    113 		<< "	gl_PointSize = 1.0;\n\n";
    114 
    115 	// Declare necessary output variables (bools).
    116 	for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output)
    117 	{
    118 		if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType()))
    119 			src << "\t" << glu::declare(output->varType, output->name) << ";\n";
    120 	}
    121 
    122 	// Operation - indented to correct level.
    123 	{
    124 		std::istringstream	opSrc	(shaderSpec.source);
    125 		std::string			line;
    126 
    127 		while (std::getline(opSrc, line))
    128 			src << "\t" << line << "\n";
    129 	}
    130 
    131 	// Assignments to outputs.
    132 	for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output)
    133 	{
    134 		if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType()))
    135 		{
    136 			const int				vecSize		= glu::getDataTypeScalarSize(output->varType.getBasicType());
    137 			const glu::DataType		intBaseType	= vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
    138 
    139 			src << "\to_" << output->name << " = " << glu::getDataTypeName(intBaseType) << "(" << output->name << ");\n";
    140 		}
    141 	}
    142 
    143 	src << "}\n";
    144 
    145 	return src.str();
    146 }
    147 
    148 static std::string generateGeometryShader (const ShaderSpec& shaderSpec)
    149 {
    150 	DE_ASSERT(glu::glslVersionUsesInOutQualifiers(shaderSpec.version));
    151 
    152 	std::ostringstream	src;
    153 
    154 	src << glu::getGLSLVersionDeclaration(shaderSpec.version) << "\n";
    155 
    156 	if (glu::glslVersionIsES(shaderSpec.version) && shaderSpec.version <= glu::GLSL_VERSION_310_ES)
    157 		src << "#extension GL_EXT_geometry_shader : require\n";
    158 
    159 	if (!shaderSpec.globalDeclarations.empty())
    160 		src << shaderSpec.globalDeclarations << "\n";
    161 
    162 	src << "layout(points) in;\n"
    163 		<< "layout(points, max_vertices = 1) out;\n";
    164 
    165 	for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input)
    166 		src << "flat in " << glu::declare(input->varType, "geom_" + input->name) << "[];\n";
    167 
    168 	for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output)
    169 	{
    170 		DE_ASSERT(output->varType.isBasicType());
    171 
    172 		if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType()))
    173 		{
    174 			const int				vecSize		= glu::getDataTypeScalarSize(output->varType.getBasicType());
    175 			const glu::DataType		intBaseType	= vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
    176 			const glu::VarType		intType		(intBaseType, glu::PRECISION_HIGHP);
    177 
    178 			src << "flat out " << glu::declare(intType, "o_" + output->name) << ";\n";
    179 		}
    180 		else
    181 			src << "flat out " << glu::declare(output->varType, output->name) << ";\n";
    182 	}
    183 
    184 	src << "\n"
    185 		<< "void main (void)\n"
    186 		<< "{\n"
    187 		<< "	gl_Position = gl_in[0].gl_Position;\n\n";
    188 
    189 	// Fetch input variables
    190 	for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input)
    191 		src << "\t" << glu::declare(input->varType, input->name) << " = geom_" << input->name << "[0];\n";
    192 
    193 	// Declare necessary output variables (bools).
    194 	for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output)
    195 	{
    196 		if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType()))
    197 			src << "\t" << glu::declare(output->varType, output->name) << ";\n";
    198 	}
    199 
    200 	src << "\n";
    201 
    202 	// Operation - indented to correct level.
    203 	{
    204 		std::istringstream	opSrc	(shaderSpec.source);
    205 		std::string			line;
    206 
    207 		while (std::getline(opSrc, line))
    208 			src << "\t" << line << "\n";
    209 	}
    210 
    211 	// Assignments to outputs.
    212 	for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output)
    213 	{
    214 		if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType()))
    215 		{
    216 			const int				vecSize		= glu::getDataTypeScalarSize(output->varType.getBasicType());
    217 			const glu::DataType		intBaseType	= vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
    218 
    219 			src << "\to_" << output->name << " = " << glu::getDataTypeName(intBaseType) << "(" << output->name << ");\n";
    220 		}
    221 	}
    222 
    223 	src << "	EmitVertex();\n"
    224 		<< "	EndPrimitive();\n"
    225 		<< "}\n";
    226 
    227 	return src.str();
    228 }
    229 
    230 static std::string generateEmptyFragmentSource (glu::GLSLVersion version)
    231 {
    232 	const bool			customOut		= glu::glslVersionUsesInOutQualifiers(version);
    233 	std::ostringstream	src;
    234 
    235 	src << glu::getGLSLVersionDeclaration(version) << "\n";
    236 
    237 	// \todo [2013-08-05 pyry] Do we need one dummy output?
    238 
    239 	src << "void main (void)\n{\n";
    240 	if (!customOut)
    241 		src << "	gl_FragColor = vec4(0.0);\n";
    242 	src << "}\n";
    243 
    244 	return src.str();
    245 }
    246 
    247 static std::string generatePassthroughVertexShader (const ShaderSpec& shaderSpec, const char* inputPrefix, const char* outputPrefix)
    248 {
    249 	// flat qualifier is not present in earlier versions?
    250 	DE_ASSERT(glu::glslVersionUsesInOutQualifiers(shaderSpec.version));
    251 
    252 	std::ostringstream src;
    253 
    254 	src << glu::getGLSLVersionDeclaration(shaderSpec.version) << "\n"
    255 		<< "in highp vec4 a_position;\n";
    256 
    257 	for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input)
    258 	{
    259 		src << "in " << glu::declare(input->varType, inputPrefix + input->name) << ";\n"
    260 			<< "flat out " << glu::declare(input->varType, outputPrefix + input->name) << ";\n";
    261 	}
    262 
    263 	src << "\nvoid main (void)\n{\n"
    264 		<< "	gl_Position = a_position;\n"
    265 		<< "	gl_PointSize = 1.0;\n";
    266 
    267 	for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input)
    268 		src << "\t" << outputPrefix << input->name << " = " << inputPrefix << input->name << ";\n";
    269 
    270 	src << "}\n";
    271 
    272 	return src.str();
    273 }
    274 
    275 static std::string generateFragmentShader (const ShaderSpec& shaderSpec, bool useIntOutputs, const std::map<std::string, int>& outLocationMap)
    276 {
    277 	DE_ASSERT(glu::glslVersionUsesInOutQualifiers(shaderSpec.version));
    278 
    279 	std::ostringstream	src;
    280 	src << glu::getGLSLVersionDeclaration(shaderSpec.version) << "\n";
    281 
    282 	if (!shaderSpec.globalDeclarations.empty())
    283 		src << shaderSpec.globalDeclarations << "\n";
    284 
    285 	for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input)
    286 		src << "flat in " << glu::declare(input->varType, input->name) << ";\n";
    287 
    288 	for (int outNdx = 0; outNdx < (int)shaderSpec.outputs.size(); ++outNdx)
    289 	{
    290 		const Symbol&				output		= shaderSpec.outputs[outNdx];
    291 		const int					location	= de::lookup(outLocationMap, output.name);
    292 		const std::string			outVarName	= "o_" + output.name;
    293 		glu::VariableDeclaration	decl		(output.varType, outVarName, glu::STORAGE_OUT, glu::INTERPOLATION_LAST, glu::Layout(location));
    294 
    295 		TCU_CHECK_INTERNAL(output.varType.isBasicType());
    296 
    297 		if (useIntOutputs && glu::isDataTypeFloatOrVec(output.varType.getBasicType()))
    298 		{
    299 			const int			vecSize			= glu::getDataTypeScalarSize(output.varType.getBasicType());
    300 			const glu::DataType	uintBasicType	= vecSize > 1 ? glu::getDataTypeUintVec(vecSize) : glu::TYPE_UINT;
    301 			const glu::VarType	uintType		(uintBasicType, glu::PRECISION_HIGHP);
    302 
    303 			decl.varType = uintType;
    304 			src << decl << ";\n";
    305 		}
    306 		else if (glu::isDataTypeBoolOrBVec(output.varType.getBasicType()))
    307 		{
    308 			const int			vecSize			= glu::getDataTypeScalarSize(output.varType.getBasicType());
    309 			const glu::DataType	intBasicType	= vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
    310 			const glu::VarType	intType			(intBasicType, glu::PRECISION_HIGHP);
    311 
    312 			decl.varType = intType;
    313 			src << decl << ";\n";
    314 		}
    315 		else if (glu::isDataTypeMatrix(output.varType.getBasicType()))
    316 		{
    317 			const int			vecSize			= glu::getDataTypeMatrixNumRows(output.varType.getBasicType());
    318 			const int			numVecs			= glu::getDataTypeMatrixNumColumns(output.varType.getBasicType());
    319 			const glu::DataType	uintBasicType	= glu::getDataTypeUintVec(vecSize);
    320 			const glu::VarType	uintType		(uintBasicType, glu::PRECISION_HIGHP);
    321 
    322 			decl.varType = uintType;
    323 			for (int vecNdx = 0; vecNdx < numVecs; ++vecNdx)
    324 			{
    325 				decl.name				= outVarName + "_" + de::toString(vecNdx);
    326 				decl.layout.location	= location + vecNdx;
    327 				src << decl << ";\n";
    328 			}
    329 		}
    330 		else
    331 			src << glu::VariableDeclaration(output.varType, output.name, glu::STORAGE_OUT, glu::INTERPOLATION_LAST, location) << ";\n";
    332 	}
    333 
    334 	src << "\nvoid main (void)\n{\n";
    335 
    336 	for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output)
    337 	{
    338 		if ((useIntOutputs && glu::isDataTypeFloatOrVec(output->varType.getBasicType())) ||
    339 			glu::isDataTypeBoolOrBVec(output->varType.getBasicType()) ||
    340 			glu::isDataTypeMatrix(output->varType.getBasicType()))
    341 			src << "\t" << glu::declare(output->varType, output->name) << ";\n";
    342 	}
    343 
    344 	// Operation - indented to correct level.
    345 	{
    346 		std::istringstream	opSrc	(shaderSpec.source);
    347 		std::string			line;
    348 
    349 		while (std::getline(opSrc, line))
    350 			src << "\t" << line << "\n";
    351 	}
    352 
    353 	for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output)
    354 	{
    355 		if (useIntOutputs && glu::isDataTypeFloatOrVec(output->varType.getBasicType()))
    356 			src << "	o_" << output->name << " = floatBitsToUint(" << output->name << ");\n";
    357 		else if (glu::isDataTypeMatrix(output->varType.getBasicType()))
    358 		{
    359 			const int			numVecs			= glu::getDataTypeMatrixNumColumns(output->varType.getBasicType());
    360 
    361 			for (int vecNdx = 0; vecNdx < numVecs; ++vecNdx)
    362 				if (useIntOutputs)
    363 					src << "\to_" << output->name << "_" << vecNdx << " = floatBitsToUint(" << output->name << "[" << vecNdx << "]);\n";
    364 				else
    365 					src << "\to_" << output->name << "_" << vecNdx << " = " << output->name << "[" << vecNdx << "];\n";
    366 		}
    367 		else if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType()))
    368 		{
    369 			const int				vecSize		= glu::getDataTypeScalarSize(output->varType.getBasicType());
    370 			const glu::DataType		intBaseType	= vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
    371 
    372 			src << "\to_" << output->name << " = " << glu::getDataTypeName(intBaseType) << "(" << output->name << ");\n";
    373 		}
    374 	}
    375 
    376 	src << "}\n";
    377 
    378 	return src.str();
    379 }
    380 
    381 // ShaderExecutor
    382 
    383 ShaderExecutor::ShaderExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec)
    384 	: m_renderCtx	(renderCtx)
    385 	, m_inputs		(shaderSpec.inputs)
    386 	, m_outputs		(shaderSpec.outputs)
    387 {
    388 }
    389 
    390 ShaderExecutor::~ShaderExecutor (void)
    391 {
    392 }
    393 
    394 void ShaderExecutor::useProgram (void)
    395 {
    396 	DE_ASSERT(isOk());
    397 	m_renderCtx.getFunctions().useProgram(getProgram());
    398 }
    399 
    400 // VertexProcessorExecutor (base class for vertex and geometry executors)
    401 
    402 class VertexProcessorExecutor : public ShaderExecutor
    403 {
    404 public:
    405 								VertexProcessorExecutor	(const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec, const glu::ProgramSources& sources);
    406 								~VertexProcessorExecutor(void);
    407 
    408 	bool						isOk					(void) const				{ return m_program.isOk();			}
    409 	void						log						(tcu::TestLog& dst) const	{ dst << m_program;					}
    410 	deUint32					getProgram				(void) const				{ return m_program.getProgram();	}
    411 
    412 	void						execute					(int numValues, const void* const* inputs, void* const* outputs);
    413 
    414 protected:
    415 	glu::ShaderProgram			m_program;
    416 };
    417 
    418 template<typename Iterator>
    419 struct SymbolNameIterator
    420 {
    421 	Iterator symbolIter;
    422 
    423 	SymbolNameIterator (Iterator symbolIter_) : symbolIter(symbolIter_) {}
    424 
    425 	inline SymbolNameIterator&	operator++	(void)								{ ++symbolIter; return *this;				}
    426 
    427 	inline bool					operator==	(const SymbolNameIterator& other)	{ return symbolIter == other.symbolIter;	}
    428 	inline bool					operator!=	(const SymbolNameIterator& other)	{ return symbolIter != other.symbolIter;	}
    429 
    430 	inline std::string operator* (void) const
    431 	{
    432 		if (glu::isDataTypeBoolOrBVec(symbolIter->varType.getBasicType()))
    433 			return "o_" + symbolIter->name;
    434 		else
    435 			return symbolIter->name;
    436 	}
    437 };
    438 
    439 template<typename Iterator>
    440 inline glu::TransformFeedbackVaryings<SymbolNameIterator<Iterator> > getTFVaryings (Iterator begin, Iterator end)
    441 {
    442 	return glu::TransformFeedbackVaryings<SymbolNameIterator<Iterator> >(SymbolNameIterator<Iterator>(begin), SymbolNameIterator<Iterator>(end));
    443 }
    444 
    445 VertexProcessorExecutor::VertexProcessorExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec, const glu::ProgramSources& sources)
    446 	: ShaderExecutor	(renderCtx, shaderSpec)
    447 	, m_program			(renderCtx,
    448 						 glu::ProgramSources(sources) << getTFVaryings(shaderSpec.outputs.begin(), shaderSpec.outputs.end())
    449 													  << glu::TransformFeedbackMode(GL_INTERLEAVED_ATTRIBS))
    450 {
    451 }
    452 
    453 VertexProcessorExecutor::~VertexProcessorExecutor (void)
    454 {
    455 }
    456 
    457 template<typename Iterator>
    458 static int computeTotalScalarSize (Iterator begin, Iterator end)
    459 {
    460 	int size = 0;
    461 	for (Iterator cur = begin; cur != end; ++cur)
    462 		size += cur->varType.getScalarSize();
    463 	return size;
    464 }
    465 
    466 void VertexProcessorExecutor::execute (int numValues, const void* const* inputs, void* const* outputs)
    467 {
    468 	const glw::Functions&					gl					= m_renderCtx.getFunctions();
    469 	const bool								useTFObject			= isContextTypeES(m_renderCtx.getType()) || (isContextTypeGLCore(m_renderCtx.getType()) && m_renderCtx.getType().getMajorVersion() >= 4);
    470 	vector<glu::VertexArrayBinding>			vertexArrays;
    471 	de::UniquePtr<glu::TransformFeedback>	transformFeedback	(useTFObject ? new glu::TransformFeedback(m_renderCtx) : DE_NULL);
    472 	glu::Buffer								outputBuffer		(m_renderCtx);
    473 	const int								outputBufferStride	= computeTotalScalarSize(m_outputs.begin(), m_outputs.end())*sizeof(deUint32);
    474 
    475 	// Setup inputs.
    476 	for (int inputNdx = 0; inputNdx < (int)m_inputs.size(); inputNdx++)
    477 	{
    478 		const Symbol&		symbol		= m_inputs[inputNdx];
    479 		const void*			ptr			= inputs[inputNdx];
    480 		const glu::DataType	basicType	= symbol.varType.getBasicType();
    481 		const int			vecSize		= glu::getDataTypeScalarSize(basicType);
    482 
    483 		if (glu::isDataTypeFloatOrVec(basicType))
    484 			vertexArrays.push_back(glu::va::Float(symbol.name, vecSize, numValues, 0, (const float*)ptr));
    485 		else if (glu::isDataTypeIntOrIVec(basicType))
    486 			vertexArrays.push_back(glu::va::Int32(symbol.name, vecSize, numValues, 0, (const deInt32*)ptr));
    487 		else if (glu::isDataTypeUintOrUVec(basicType))
    488 			vertexArrays.push_back(glu::va::Uint32(symbol.name, vecSize, numValues, 0, (const deUint32*)ptr));
    489 		else if (glu::isDataTypeMatrix(basicType))
    490 		{
    491 			int		numRows	= glu::getDataTypeMatrixNumRows(basicType);
    492 			int		numCols	= glu::getDataTypeMatrixNumColumns(basicType);
    493 			int		stride	= numRows * numCols * sizeof(float);
    494 
    495 			for (int colNdx = 0; colNdx < numCols; ++colNdx)
    496 				vertexArrays.push_back(glu::va::Float(symbol.name, colNdx, numRows, numValues, stride, ((const float*)ptr) + colNdx * numRows));
    497 		}
    498 		else
    499 			DE_ASSERT(false);
    500 	}
    501 
    502 	// Setup TF outputs.
    503 	if (useTFObject)
    504 		gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, **transformFeedback);
    505 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, *outputBuffer);
    506 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, outputBufferStride*numValues, DE_NULL, GL_STREAM_READ);
    507 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, *outputBuffer);
    508 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error in TF setup");
    509 
    510 	// Draw with rasterization disabled.
    511 	gl.beginTransformFeedback(GL_POINTS);
    512 	gl.enable(GL_RASTERIZER_DISCARD);
    513 	glu::draw(m_renderCtx, m_program.getProgram(), (int)vertexArrays.size(), vertexArrays.empty() ? DE_NULL : &vertexArrays[0],
    514 			  glu::pr::Points(numValues));
    515 	gl.disable(GL_RASTERIZER_DISCARD);
    516 	gl.endTransformFeedback();
    517 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error in draw");
    518 
    519 	// Read back data.
    520 	{
    521 		const void*	srcPtr		= gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, outputBufferStride*numValues, GL_MAP_READ_BIT);
    522 		int			curOffset	= 0; // Offset in buffer in bytes.
    523 
    524 		GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER)");
    525 		TCU_CHECK(srcPtr != DE_NULL);
    526 
    527 		for (int outputNdx = 0; outputNdx < (int)m_outputs.size(); outputNdx++)
    528 		{
    529 			const Symbol&		symbol		= m_outputs[outputNdx];
    530 			void*				dstPtr		= outputs[outputNdx];
    531 			const int			scalarSize	= symbol.varType.getScalarSize();
    532 
    533 			for (int ndx = 0; ndx < numValues; ndx++)
    534 				deMemcpy((deUint32*)dstPtr + scalarSize*ndx, (const deUint8*)srcPtr + curOffset + ndx*outputBufferStride, scalarSize*sizeof(deUint32));
    535 
    536 			curOffset += scalarSize*sizeof(deUint32);
    537 		}
    538 
    539 		gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
    540 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer()");
    541 	}
    542 
    543 	if (useTFObject)
    544 		gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
    545 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
    546 	GLU_EXPECT_NO_ERROR(gl.getError(), "Restore state");
    547 }
    548 
    549 // VertexShaderExecutor
    550 
    551 class VertexShaderExecutor : public VertexProcessorExecutor
    552 {
    553 public:
    554 								VertexShaderExecutor	(const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec);
    555 };
    556 
    557 VertexShaderExecutor::VertexShaderExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec)
    558 	: VertexProcessorExecutor	(renderCtx, shaderSpec,
    559 								 glu::ProgramSources() << glu::VertexSource(generateVertexShader(shaderSpec))
    560 													   << glu::FragmentSource(generateEmptyFragmentSource(shaderSpec.version)))
    561 {
    562 }
    563 
    564 // GeometryShaderExecutor
    565 
    566 class CheckGeomSupport
    567 {
    568 public:
    569 	inline CheckGeomSupport (const glu::RenderContext& renderCtx)
    570 	{
    571 		if (renderCtx.getType().getAPI().getProfile() == glu::PROFILE_ES)
    572 			checkExtension(renderCtx, "GL_EXT_geometry_shader");
    573 	}
    574 };
    575 
    576 class GeometryShaderExecutor : private CheckGeomSupport, public VertexProcessorExecutor
    577 {
    578 public:
    579 								GeometryShaderExecutor	(const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec);
    580 };
    581 
    582 GeometryShaderExecutor::GeometryShaderExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec)
    583 	: CheckGeomSupport			(renderCtx)
    584 	, VertexProcessorExecutor	(renderCtx, shaderSpec,
    585 								 glu::ProgramSources() << glu::VertexSource(generatePassthroughVertexShader(shaderSpec, "", "geom_"))
    586 													   << glu::GeometrySource(generateGeometryShader(shaderSpec))
    587 													   << glu::FragmentSource(generateEmptyFragmentSource(shaderSpec.version)))
    588 {
    589 }
    590 
    591 // FragmentShaderExecutor
    592 
    593 class FragmentShaderExecutor : public ShaderExecutor
    594 {
    595 public:
    596 								FragmentShaderExecutor	(const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec);
    597 								~FragmentShaderExecutor	(void);
    598 
    599 	bool						isOk					(void) const				{ return m_program.isOk();			}
    600 	void						log						(tcu::TestLog& dst) const	{ dst << m_program;					}
    601 	deUint32					getProgram				(void) const				{ return m_program.getProgram();	}
    602 
    603 	void						execute					(int numValues, const void* const* inputs, void* const* outputs);
    604 
    605 protected:
    606 	std::vector<const Symbol*>	m_outLocationSymbols;
    607 	std::map<std::string, int>	m_outLocationMap;
    608 	glu::ShaderProgram			m_program;
    609 };
    610 
    611 static std::map<std::string, int> generateLocationMap (const std::vector<Symbol>& symbols, std::vector<const Symbol*>& locationSymbols)
    612 {
    613 	std::map<std::string, int>	ret;
    614 	int							location	= 0;
    615 
    616 	locationSymbols.clear();
    617 
    618 	for (std::vector<Symbol>::const_iterator it = symbols.begin(); it != symbols.end(); ++it)
    619 	{
    620 		const int	numLocations	= glu::getDataTypeNumLocations(it->varType.getBasicType());
    621 
    622 		TCU_CHECK_INTERNAL(!de::contains(ret, it->name));
    623 		de::insert(ret, it->name, location);
    624 		location += numLocations;
    625 
    626 		for (int ndx = 0; ndx < numLocations; ++ndx)
    627 			locationSymbols.push_back(&*it);
    628 	}
    629 
    630 	return ret;
    631 }
    632 
    633 inline bool hasFloatRenderTargets (const glu::RenderContext& renderCtx)
    634 {
    635 	glu::ContextType type = renderCtx.getType();
    636 	return glu::isContextTypeGLCore(type);
    637 }
    638 
    639 FragmentShaderExecutor::FragmentShaderExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec)
    640 	: ShaderExecutor		(renderCtx, shaderSpec)
    641 	, m_outLocationSymbols	()
    642 	, m_outLocationMap		(generateLocationMap(m_outputs, m_outLocationSymbols))
    643 	, m_program				(renderCtx,
    644 							 glu::ProgramSources() << glu::VertexSource(generatePassthroughVertexShader(shaderSpec, "a_", ""))
    645 												   << glu::FragmentSource(generateFragmentShader(shaderSpec, !hasFloatRenderTargets(renderCtx), m_outLocationMap)))
    646 {
    647 }
    648 
    649 FragmentShaderExecutor::~FragmentShaderExecutor (void)
    650 {
    651 }
    652 
    653 inline int queryInt (const glw::Functions& gl, deUint32 pname)
    654 {
    655 	int value = 0;
    656 	gl.getIntegerv(pname, &value);
    657 	return value;
    658 }
    659 
    660 static tcu::TextureFormat getRenderbufferFormatForOutput (const glu::VarType& outputType, bool useIntOutputs)
    661 {
    662 	const tcu::TextureFormat::ChannelOrder channelOrderMap[] =
    663 	{
    664 		tcu::TextureFormat::R,
    665 		tcu::TextureFormat::RG,
    666 		tcu::TextureFormat::RGBA,	// No RGB variants available.
    667 		tcu::TextureFormat::RGBA
    668 	};
    669 
    670 	const glu::DataType					basicType		= outputType.getBasicType();
    671 	const int							numComps		= glu::getDataTypeNumComponents(basicType);
    672 	tcu::TextureFormat::ChannelType		channelType;
    673 
    674 	switch (glu::getDataTypeScalarType(basicType))
    675 	{
    676 		case glu::TYPE_UINT:	channelType = tcu::TextureFormat::UNSIGNED_INT32;												break;
    677 		case glu::TYPE_INT:		channelType = tcu::TextureFormat::SIGNED_INT32;													break;
    678 		case glu::TYPE_BOOL:	channelType = tcu::TextureFormat::SIGNED_INT32;													break;
    679 		case glu::TYPE_FLOAT:	channelType = useIntOutputs ? tcu::TextureFormat::UNSIGNED_INT32 : tcu::TextureFormat::FLOAT;	break;
    680 		default:
    681 			throw tcu::InternalError("Invalid output type");
    682 	}
    683 
    684 	DE_ASSERT(de::inRange<int>(numComps, 1, DE_LENGTH_OF_ARRAY(channelOrderMap)));
    685 
    686 	return tcu::TextureFormat(channelOrderMap[numComps-1], channelType);
    687 }
    688 
    689 void FragmentShaderExecutor::execute (int numValues, const void* const* inputs, void* const* outputs)
    690 {
    691 	const glw::Functions&			gl					= m_renderCtx.getFunctions();
    692 	const bool						useIntOutputs		= !hasFloatRenderTargets(m_renderCtx);
    693 	const int						maxRenderbufferSize	= queryInt(gl, GL_MAX_RENDERBUFFER_SIZE);
    694 	const int						framebufferW		= de::min(maxRenderbufferSize, numValues);
    695 	const int						framebufferH		= (numValues / framebufferW) + ((numValues % framebufferW != 0) ? 1 : 0);
    696 
    697 	glu::Framebuffer				framebuffer			(m_renderCtx);
    698 	glu::RenderbufferVector			renderbuffers		(m_renderCtx, m_outLocationSymbols.size());
    699 
    700 	vector<glu::VertexArrayBinding>	vertexArrays;
    701 	vector<tcu::Vec2>				positions			(numValues);
    702 
    703 	if (framebufferH > maxRenderbufferSize)
    704 		throw tcu::NotSupportedError("Value count is too high for maximum supported renderbuffer size");
    705 
    706 	// Compute positions - 1px points are used to drive fragment shading.
    707 	for (int valNdx = 0; valNdx < numValues; valNdx++)
    708 	{
    709 		const int		ix		= valNdx % framebufferW;
    710 		const int		iy		= valNdx / framebufferW;
    711 		const float		fx		= -1.0f + 2.0f*((float(ix) + 0.5f) / float(framebufferW));
    712 		const float		fy		= -1.0f + 2.0f*((float(iy) + 0.5f) / float(framebufferH));
    713 
    714 		positions[valNdx] = tcu::Vec2(fx, fy);
    715 	}
    716 
    717 	// Vertex inputs.
    718 	vertexArrays.push_back(glu::va::Float("a_position", 2, numValues, 0, (const float*)&positions[0]));
    719 
    720 	for (int inputNdx = 0; inputNdx < (int)m_inputs.size(); inputNdx++)
    721 	{
    722 		const Symbol&		symbol		= m_inputs[inputNdx];
    723 		const std::string	attribName	= "a_" + symbol.name;
    724 		const void*			ptr			= inputs[inputNdx];
    725 		const glu::DataType	basicType	= symbol.varType.getBasicType();
    726 		const int			vecSize		= glu::getDataTypeScalarSize(basicType);
    727 
    728 		if (glu::isDataTypeFloatOrVec(basicType))
    729 			vertexArrays.push_back(glu::va::Float(attribName, vecSize, numValues, 0, (const float*)ptr));
    730 		else if (glu::isDataTypeIntOrIVec(basicType))
    731 			vertexArrays.push_back(glu::va::Int32(attribName, vecSize, numValues, 0, (const deInt32*)ptr));
    732 		else if (glu::isDataTypeUintOrUVec(basicType))
    733 			vertexArrays.push_back(glu::va::Uint32(attribName, vecSize, numValues, 0, (const deUint32*)ptr));
    734 		else if (glu::isDataTypeMatrix(basicType))
    735 		{
    736 			int		numRows	= glu::getDataTypeMatrixNumRows(basicType);
    737 			int		numCols	= glu::getDataTypeMatrixNumColumns(basicType);
    738 			int		stride	= numRows * numCols * sizeof(float);
    739 
    740 			for (int colNdx = 0; colNdx < numCols; ++colNdx)
    741 				vertexArrays.push_back(glu::va::Float(attribName, colNdx, numRows, numValues, stride, ((const float*)ptr) + colNdx * numRows));
    742 		}
    743 		else
    744 			DE_ASSERT(false);
    745 	}
    746 
    747 	// Construct framebuffer.
    748 	gl.bindFramebuffer(GL_FRAMEBUFFER, *framebuffer);
    749 
    750 	for (int outNdx = 0; outNdx < (int)m_outLocationSymbols.size(); ++outNdx)
    751 	{
    752 		const Symbol&	output			= *m_outLocationSymbols[outNdx];
    753 		const deUint32	renderbuffer	= renderbuffers[outNdx];
    754 		const deUint32	format			= glu::getInternalFormat(getRenderbufferFormatForOutput(output.varType, useIntOutputs));
    755 
    756 		gl.bindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
    757 		gl.renderbufferStorage(GL_RENDERBUFFER, format, framebufferW, framebufferH);
    758 		gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+outNdx, GL_RENDERBUFFER, renderbuffer);
    759 	}
    760 	gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
    761 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set up framebuffer object");
    762 	TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
    763 
    764 	{
    765 		vector<deUint32> drawBuffers(m_outLocationSymbols.size());
    766 		for (int ndx = 0; ndx < (int)m_outLocationSymbols.size(); ndx++)
    767 			drawBuffers[ndx] = GL_COLOR_ATTACHMENT0+ndx;
    768 		gl.drawBuffers((int)drawBuffers.size(), &drawBuffers[0]);
    769 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawBuffers()");
    770 	}
    771 
    772 	// Render
    773 	gl.viewport(0, 0, framebufferW, framebufferH);
    774 	glu::draw(m_renderCtx, m_program.getProgram(), (int)vertexArrays.size(), &vertexArrays[0],
    775 			  glu::pr::Points(numValues));
    776 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error in draw");
    777 
    778 	// Read back pixels.
    779 	{
    780 		tcu::TextureLevel	tmpBuf;
    781 
    782 		// \todo [2013-08-07 pyry] Some fast-paths could be added here.
    783 
    784 		for (int outNdx = 0; outNdx < (int)m_outputs.size(); ++outNdx)
    785 		{
    786 			const Symbol&				output			= m_outputs[outNdx];
    787 			const int					outSize			= output.varType.getScalarSize();
    788 			const int					outVecSize		= glu::getDataTypeNumComponents(output.varType.getBasicType());
    789 			const int					outNumLocs		= glu::getDataTypeNumLocations(output.varType.getBasicType());
    790 			deUint32*					dstPtrBase		= static_cast<deUint32*>(outputs[outNdx]);
    791 			const tcu::TextureFormat	format			= getRenderbufferFormatForOutput(output.varType, useIntOutputs);
    792 			const tcu::TextureFormat	readFormat		(tcu::TextureFormat::RGBA, format.type);
    793 			const int					outLocation		= de::lookup(m_outLocationMap, output.name);
    794 
    795 			tmpBuf.setStorage(readFormat, framebufferW, framebufferH);
    796 
    797 			for (int locNdx = 0; locNdx < outNumLocs; ++locNdx)
    798 			{
    799 				gl.readBuffer(GL_COLOR_ATTACHMENT0 + outLocation + locNdx);
    800 				glu::readPixels(m_renderCtx, 0, 0, tmpBuf.getAccess());
    801 				GLU_EXPECT_NO_ERROR(gl.getError(), "Reading pixels");
    802 
    803 				if (outSize == 4 && outNumLocs == 1)
    804 					deMemcpy(dstPtrBase, tmpBuf.getAccess().getDataPtr(), numValues*outVecSize*sizeof(deUint32));
    805 				else
    806 				{
    807 					for (int valNdx = 0; valNdx < numValues; valNdx++)
    808 					{
    809 						const deUint32* srcPtr = (const deUint32*)tmpBuf.getAccess().getDataPtr() + valNdx*4;
    810 						deUint32*		dstPtr = &dstPtrBase[outSize*valNdx + outVecSize*locNdx];
    811 						deMemcpy(dstPtr, srcPtr, outVecSize*sizeof(deUint32));
    812 					}
    813 				}
    814 			}
    815 		}
    816 	}
    817 
    818 	// \todo [2013-08-07 pyry] Clear draw buffers & viewport?
    819 	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
    820 }
    821 
    822 // Shared utilities for compute and tess executors
    823 
    824 static deUint32 getVecStd430ByteAlignment (glu::DataType type)
    825 {
    826 	switch (glu::getDataTypeScalarSize(type))
    827 	{
    828 		case 1:		return 4u;
    829 		case 2:		return 8u;
    830 		case 3:		return 16u;
    831 		case 4:		return 16u;
    832 		default:
    833 			DE_ASSERT(false);
    834 			return 0u;
    835 	}
    836 }
    837 
    838 class BufferIoExecutor : public ShaderExecutor
    839 {
    840 public:
    841 						BufferIoExecutor	(const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec, const glu::ProgramSources& sources);
    842 						~BufferIoExecutor	(void);
    843 
    844 	bool				isOk				(void) const				{ return m_program.isOk();			}
    845 	void				log					(tcu::TestLog& dst) const	{ dst << m_program;					}
    846 	deUint32			getProgram			(void) const				{ return m_program.getProgram();	}
    847 
    848 protected:
    849 	enum
    850 	{
    851 		INPUT_BUFFER_BINDING	= 0,
    852 		OUTPUT_BUFFER_BINDING	= 1,
    853 	};
    854 
    855 	void				initBuffers			(int numValues);
    856 	deUint32			getInputBuffer		(void) const		{ return *m_inputBuffer;					}
    857 	deUint32			getOutputBuffer		(void) const		{ return *m_outputBuffer;					}
    858 	deUint32			getInputStride		(void) const		{ return getLayoutStride(m_inputLayout);	}
    859 	deUint32			getOutputStride		(void) const		{ return getLayoutStride(m_outputLayout);	}
    860 
    861 	void				uploadInputBuffer	(const void* const* inputPtrs, int numValues);
    862 	void				readOutputBuffer	(void* const* outputPtrs, int numValues);
    863 
    864 	static void			declareBufferBlocks	(std::ostream& src, const ShaderSpec& spec);
    865 	static void			generateExecBufferIo(std::ostream& src, const ShaderSpec& spec, const char* invocationNdxName);
    866 
    867 	glu::ShaderProgram	m_program;
    868 
    869 private:
    870 	struct VarLayout
    871 	{
    872 		deUint32		offset;
    873 		deUint32		stride;
    874 		deUint32		matrixStride;
    875 
    876 		VarLayout (void) : offset(0), stride(0), matrixStride(0) {}
    877 	};
    878 
    879 	void				resizeInputBuffer	(int newSize);
    880 	void				resizeOutputBuffer	(int newSize);
    881 
    882 	static void			computeVarLayout	(const std::vector<Symbol>& symbols, std::vector<VarLayout>* layout);
    883 	static deUint32		getLayoutStride		(const vector<VarLayout>& layout);
    884 
    885 	static void			copyToBuffer		(const glu::VarType& varType, const VarLayout& layout, int numValues, const void* srcBasePtr, void* dstBasePtr);
    886 	static void			copyFromBuffer		(const glu::VarType& varType, const VarLayout& layout, int numValues, const void* srcBasePtr, void* dstBasePtr);
    887 
    888 	glu::Buffer			m_inputBuffer;
    889 	glu::Buffer			m_outputBuffer;
    890 
    891 	vector<VarLayout>	m_inputLayout;
    892 	vector<VarLayout>	m_outputLayout;
    893 };
    894 
    895 BufferIoExecutor::BufferIoExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec, const glu::ProgramSources& sources)
    896 	: ShaderExecutor	(renderCtx, shaderSpec)
    897 	, m_program			(renderCtx, sources)
    898 	, m_inputBuffer		(renderCtx)
    899 	, m_outputBuffer	(renderCtx)
    900 {
    901 	computeVarLayout(m_inputs, &m_inputLayout);
    902 	computeVarLayout(m_outputs, &m_outputLayout);
    903 }
    904 
    905 BufferIoExecutor::~BufferIoExecutor (void)
    906 {
    907 }
    908 
    909 void BufferIoExecutor::resizeInputBuffer (int newSize)
    910 {
    911 	const glw::Functions& gl = m_renderCtx.getFunctions();
    912 	gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, *m_inputBuffer);
    913 	gl.bufferData(GL_SHADER_STORAGE_BUFFER, newSize, DE_NULL, GL_STATIC_DRAW);
    914 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to allocate input buffer");
    915 }
    916 
    917 void BufferIoExecutor::resizeOutputBuffer (int newSize)
    918 {
    919 	const glw::Functions& gl = m_renderCtx.getFunctions();
    920 	gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, *m_outputBuffer);
    921 	gl.bufferData(GL_SHADER_STORAGE_BUFFER, newSize, DE_NULL, GL_STATIC_DRAW);
    922 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to allocate output buffer");
    923 }
    924 
    925 void BufferIoExecutor::initBuffers (int numValues)
    926 {
    927 	const deUint32		inputStride			= getLayoutStride(m_inputLayout);
    928 	const deUint32		outputStride		= getLayoutStride(m_outputLayout);
    929 	const int			inputBufferSize		= numValues * inputStride;
    930 	const int			outputBufferSize	= numValues * outputStride;
    931 
    932 	resizeInputBuffer(inputBufferSize);
    933 	resizeOutputBuffer(outputBufferSize);
    934 }
    935 
    936 void BufferIoExecutor::computeVarLayout (const std::vector<Symbol>& symbols, std::vector<VarLayout>* layout)
    937 {
    938 	deUint32	maxAlignment	= 0;
    939 	deUint32	curOffset		= 0;
    940 
    941 	DE_ASSERT(layout->empty());
    942 	layout->resize(symbols.size());
    943 
    944 	for (size_t varNdx = 0; varNdx < symbols.size(); varNdx++)
    945 	{
    946 		const Symbol&		symbol		= symbols[varNdx];
    947 		const glu::DataType	basicType	= symbol.varType.getBasicType();
    948 		VarLayout&			layoutEntry	= (*layout)[varNdx];
    949 
    950 		if (glu::isDataTypeScalarOrVector(basicType))
    951 		{
    952 			const deUint32	alignment	= getVecStd430ByteAlignment(basicType);
    953 			const deUint32	size		= (deUint32)glu::getDataTypeScalarSize(basicType)*sizeof(deUint32);
    954 
    955 			curOffset		= (deUint32)deAlign32((int)curOffset, (int)alignment);
    956 			maxAlignment	= de::max(maxAlignment, alignment);
    957 
    958 			layoutEntry.offset			= curOffset;
    959 			layoutEntry.matrixStride	= 0;
    960 
    961 			curOffset += size;
    962 		}
    963 		else if (glu::isDataTypeMatrix(basicType))
    964 		{
    965 			const int				numVecs			= glu::getDataTypeMatrixNumColumns(basicType);
    966 			const glu::DataType		vecType			= glu::getDataTypeFloatVec(glu::getDataTypeMatrixNumRows(basicType));
    967 			const deUint32			vecAlignment	= getVecStd430ByteAlignment(vecType);
    968 
    969 			curOffset		= (deUint32)deAlign32((int)curOffset, (int)vecAlignment);
    970 			maxAlignment	= de::max(maxAlignment, vecAlignment);
    971 
    972 			layoutEntry.offset			= curOffset;
    973 			layoutEntry.matrixStride	= vecAlignment;
    974 
    975 			curOffset += vecAlignment*numVecs;
    976 		}
    977 		else
    978 			DE_ASSERT(false);
    979 	}
    980 
    981 	{
    982 		const deUint32	totalSize	= (deUint32)deAlign32(curOffset, maxAlignment);
    983 
    984 		for (vector<VarLayout>::iterator varIter = layout->begin(); varIter != layout->end(); ++varIter)
    985 			varIter->stride = totalSize;
    986 	}
    987 }
    988 
    989 inline deUint32 BufferIoExecutor::getLayoutStride (const vector<VarLayout>& layout)
    990 {
    991 	return layout.empty() ? 0 : layout[0].stride;
    992 }
    993 
    994 void BufferIoExecutor::copyToBuffer (const glu::VarType& varType, const VarLayout& layout, int numValues, const void* srcBasePtr, void* dstBasePtr)
    995 {
    996 	if (varType.isBasicType())
    997 	{
    998 		const glu::DataType		basicType		= varType.getBasicType();
    999 		const bool				isMatrix		= glu::isDataTypeMatrix(basicType);
   1000 		const int				scalarSize		= glu::getDataTypeScalarSize(basicType);
   1001 		const int				numVecs			= isMatrix ? glu::getDataTypeMatrixNumColumns(basicType) : 1;
   1002 		const int				numComps		= scalarSize / numVecs;
   1003 
   1004 		for (int elemNdx = 0; elemNdx < numValues; elemNdx++)
   1005 		{
   1006 			for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
   1007 			{
   1008 				const int		srcOffset		= sizeof(deUint32)*(elemNdx*scalarSize + vecNdx*numComps);
   1009 				const int		dstOffset		= layout.offset + layout.stride*elemNdx + (isMatrix ? layout.matrixStride*vecNdx : 0);
   1010 				const deUint8*	srcPtr			= (const deUint8*)srcBasePtr + srcOffset;
   1011 				deUint8*		dstPtr			= (deUint8*)dstBasePtr + dstOffset;
   1012 
   1013 				deMemcpy(dstPtr, srcPtr, sizeof(deUint32)*numComps);
   1014 			}
   1015 		}
   1016 	}
   1017 	else
   1018 		throw tcu::InternalError("Unsupported type");
   1019 }
   1020 
   1021 void BufferIoExecutor::copyFromBuffer (const glu::VarType& varType, const VarLayout& layout, int numValues, const void* srcBasePtr, void* dstBasePtr)
   1022 {
   1023 	if (varType.isBasicType())
   1024 	{
   1025 		const glu::DataType		basicType		= varType.getBasicType();
   1026 		const bool				isMatrix		= glu::isDataTypeMatrix(basicType);
   1027 		const int				scalarSize		= glu::getDataTypeScalarSize(basicType);
   1028 		const int				numVecs			= isMatrix ? glu::getDataTypeMatrixNumColumns(basicType) : 1;
   1029 		const int				numComps		= scalarSize / numVecs;
   1030 
   1031 		for (int elemNdx = 0; elemNdx < numValues; elemNdx++)
   1032 		{
   1033 			for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
   1034 			{
   1035 				const int		srcOffset		= layout.offset + layout.stride*elemNdx + (isMatrix ? layout.matrixStride*vecNdx : 0);
   1036 				const int		dstOffset		= sizeof(deUint32)*(elemNdx*scalarSize + vecNdx*numComps);
   1037 				const deUint8*	srcPtr			= (const deUint8*)srcBasePtr + srcOffset;
   1038 				deUint8*		dstPtr			= (deUint8*)dstBasePtr + dstOffset;
   1039 
   1040 				deMemcpy(dstPtr, srcPtr, sizeof(deUint32)*numComps);
   1041 			}
   1042 		}
   1043 	}
   1044 	else
   1045 		throw tcu::InternalError("Unsupported type");
   1046 }
   1047 
   1048 void BufferIoExecutor::uploadInputBuffer (const void* const* inputPtrs, int numValues)
   1049 {
   1050 	const glw::Functions&	gl				= m_renderCtx.getFunctions();
   1051 	const deUint32			buffer			= *m_inputBuffer;
   1052 	const deUint32			inputStride		= getLayoutStride(m_inputLayout);
   1053 	const int				inputBufferSize	= inputStride*numValues;
   1054 
   1055 	if (inputBufferSize == 0)
   1056 		return; // No inputs
   1057 
   1058 	gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
   1059 	void* mapPtr = gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, inputBufferSize, GL_MAP_WRITE_BIT);
   1060 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange()");
   1061 	TCU_CHECK(mapPtr);
   1062 
   1063 	try
   1064 	{
   1065 		DE_ASSERT(m_inputs.size() == m_inputLayout.size());
   1066 		for (size_t inputNdx = 0; inputNdx < m_inputs.size(); ++inputNdx)
   1067 		{
   1068 			const glu::VarType&		varType		= m_inputs[inputNdx].varType;
   1069 			const VarLayout&		layout		= m_inputLayout[inputNdx];
   1070 
   1071 			copyToBuffer(varType, layout, numValues, inputPtrs[inputNdx], mapPtr);
   1072 		}
   1073 	}
   1074 	catch (...)
   1075 	{
   1076 		gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
   1077 		throw;
   1078 	}
   1079 
   1080 	gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
   1081 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer()");
   1082 }
   1083 
   1084 void BufferIoExecutor::readOutputBuffer (void* const* outputPtrs, int numValues)
   1085 {
   1086 	const glw::Functions&	gl					= m_renderCtx.getFunctions();
   1087 	const deUint32			buffer				= *m_outputBuffer;
   1088 	const deUint32			outputStride		= getLayoutStride(m_outputLayout);
   1089 	const int				outputBufferSize	= numValues*outputStride;
   1090 
   1091 	DE_ASSERT(outputBufferSize > 0); // At least some outputs are required.
   1092 
   1093 	gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
   1094 	void* mapPtr = gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, outputBufferSize, GL_MAP_READ_BIT);
   1095 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange()");
   1096 	TCU_CHECK(mapPtr);
   1097 
   1098 	try
   1099 	{
   1100 		DE_ASSERT(m_outputs.size() == m_outputLayout.size());
   1101 		for (size_t outputNdx = 0; outputNdx < m_outputs.size(); ++outputNdx)
   1102 		{
   1103 			const glu::VarType&		varType		= m_outputs[outputNdx].varType;
   1104 			const VarLayout&		layout		= m_outputLayout[outputNdx];
   1105 
   1106 			copyFromBuffer(varType, layout, numValues, mapPtr, outputPtrs[outputNdx]);
   1107 		}
   1108 	}
   1109 	catch (...)
   1110 	{
   1111 		gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
   1112 		throw;
   1113 	}
   1114 
   1115 	gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
   1116 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer()");
   1117 }
   1118 
   1119 void BufferIoExecutor::declareBufferBlocks (std::ostream& src, const ShaderSpec& spec)
   1120 {
   1121 	// Input struct
   1122 	if (!spec.inputs.empty())
   1123 	{
   1124 		glu::StructType inputStruct("Inputs");
   1125 		for (vector<Symbol>::const_iterator symIter = spec.inputs.begin(); symIter != spec.inputs.end(); ++symIter)
   1126 			inputStruct.addMember(symIter->name.c_str(), symIter->varType);
   1127 		src << glu::declare(&inputStruct) << ";\n";
   1128 	}
   1129 
   1130 	// Output struct
   1131 	{
   1132 		glu::StructType outputStruct("Outputs");
   1133 		for (vector<Symbol>::const_iterator symIter = spec.outputs.begin(); symIter != spec.outputs.end(); ++symIter)
   1134 			outputStruct.addMember(symIter->name.c_str(), symIter->varType);
   1135 		src << glu::declare(&outputStruct) << ";\n";
   1136 	}
   1137 
   1138 	src << "\n";
   1139 
   1140 	if (!spec.inputs.empty())
   1141 	{
   1142 		src	<< "layout(binding = " << int(INPUT_BUFFER_BINDING) << ", std430) buffer InBuffer\n"
   1143 			<< "{\n"
   1144 			<< "	Inputs inputs[];\n"
   1145 			<< "};\n";
   1146 	}
   1147 
   1148 	src	<< "layout(binding = " << int(OUTPUT_BUFFER_BINDING) << ", std430) buffer OutBuffer\n"
   1149 		<< "{\n"
   1150 		<< "	Outputs outputs[];\n"
   1151 		<< "};\n"
   1152 		<< "\n";
   1153 }
   1154 
   1155 void BufferIoExecutor::generateExecBufferIo (std::ostream& src, const ShaderSpec& spec, const char* invocationNdxName)
   1156 {
   1157 	for (vector<Symbol>::const_iterator symIter = spec.inputs.begin(); symIter != spec.inputs.end(); ++symIter)
   1158 		src << "\t" << glu::declare(symIter->varType, symIter->name) << " = inputs[" << invocationNdxName << "]." << symIter->name << ";\n";
   1159 
   1160 	for (vector<Symbol>::const_iterator symIter = spec.outputs.begin(); symIter != spec.outputs.end(); ++symIter)
   1161 		src << "\t" << glu::declare(symIter->varType, symIter->name) << ";\n";
   1162 
   1163 	src << "\n";
   1164 
   1165 	{
   1166 		std::istringstream	opSrc	(spec.source);
   1167 		std::string			line;
   1168 
   1169 		while (std::getline(opSrc, line))
   1170 			src << "\t" << line << "\n";
   1171 	}
   1172 
   1173 	src << "\n";
   1174 	for (vector<Symbol>::const_iterator symIter = spec.outputs.begin(); symIter != spec.outputs.end(); ++symIter)
   1175 		src << "\toutputs[" << invocationNdxName << "]." << symIter->name << " = " << symIter->name << ";\n";
   1176 }
   1177 
   1178 // ComputeShaderExecutor
   1179 
   1180 class ComputeShaderExecutor : public BufferIoExecutor
   1181 {
   1182 public:
   1183 						ComputeShaderExecutor	(const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec);
   1184 						~ComputeShaderExecutor	(void);
   1185 
   1186 	void				execute					(int numValues, const void* const* inputs, void* const* outputs);
   1187 
   1188 protected:
   1189 	static std::string	generateComputeShader	(const ShaderSpec& spec);
   1190 
   1191 	tcu::IVec3			m_maxWorkSize;
   1192 };
   1193 
   1194 std::string ComputeShaderExecutor::generateComputeShader (const ShaderSpec& spec)
   1195 {
   1196 	std::ostringstream src;
   1197 
   1198 	src << glu::getGLSLVersionDeclaration(spec.version) << "\n";
   1199 
   1200 	if (!spec.globalDeclarations.empty())
   1201 		src << spec.globalDeclarations << "\n";
   1202 
   1203 	src << "layout(local_size_x = 1) in;\n"
   1204 		<< "\n";
   1205 
   1206 	declareBufferBlocks(src, spec);
   1207 
   1208 	src << "void main (void)\n"
   1209 		<< "{\n"
   1210 		<< "	uint invocationNdx = gl_NumWorkGroups.x*gl_NumWorkGroups.y*gl_WorkGroupID.z\n"
   1211 		<< "	                   + gl_NumWorkGroups.x*gl_WorkGroupID.y + gl_WorkGroupID.x;\n";
   1212 
   1213 	generateExecBufferIo(src, spec, "invocationNdx");
   1214 
   1215 	src << "}\n";
   1216 
   1217 	return src.str();
   1218 }
   1219 
   1220 ComputeShaderExecutor::ComputeShaderExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec)
   1221 	: BufferIoExecutor	(renderCtx, shaderSpec,
   1222 						 glu::ProgramSources() << glu::ComputeSource(generateComputeShader(shaderSpec)))
   1223 {
   1224 	m_maxWorkSize	= tcu::IVec3(128,128,64); // Minimum in 3plus
   1225 }
   1226 
   1227 ComputeShaderExecutor::~ComputeShaderExecutor (void)
   1228 {
   1229 }
   1230 
   1231 void ComputeShaderExecutor::execute (int numValues, const void* const* inputs, void* const* outputs)
   1232 {
   1233 	const glw::Functions&	gl						= m_renderCtx.getFunctions();
   1234 	const int				maxValuesPerInvocation	= m_maxWorkSize[0];
   1235 	const deUint32			inputStride				= getInputStride();
   1236 	const deUint32			outputStride			= getOutputStride();
   1237 
   1238 	initBuffers(numValues);
   1239 
   1240 	// Setup input buffer & copy data
   1241 	uploadInputBuffer(inputs, numValues);
   1242 
   1243 	// Perform compute invocations
   1244 	{
   1245 		int curOffset = 0;
   1246 		while (curOffset < numValues)
   1247 		{
   1248 			const int numToExec = de::min(maxValuesPerInvocation, numValues-curOffset);
   1249 
   1250 			if (inputStride > 0)
   1251 				gl.bindBufferRange(GL_SHADER_STORAGE_BUFFER, INPUT_BUFFER_BINDING, getInputBuffer(), curOffset*inputStride, numToExec*inputStride);
   1252 
   1253 			gl.bindBufferRange(GL_SHADER_STORAGE_BUFFER, OUTPUT_BUFFER_BINDING, getOutputBuffer(), curOffset*outputStride, numToExec*outputStride);
   1254 			GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange(GL_SHADER_STORAGE_BUFFER)");
   1255 
   1256 			gl.dispatchCompute(numToExec, 1, 1);
   1257 			GLU_EXPECT_NO_ERROR(gl.getError(), "glDispatchCompute()");
   1258 
   1259 			curOffset += numToExec;
   1260 		}
   1261 	}
   1262 
   1263 	// Read back data
   1264 	readOutputBuffer(outputs, numValues);
   1265 }
   1266 
   1267 // Tessellation utils
   1268 
   1269 static std::string generateVertexShaderForTess (glu::GLSLVersion version)
   1270 {
   1271 	std::ostringstream	src;
   1272 
   1273 	src << glu::getGLSLVersionDeclaration(version) << "\n";
   1274 
   1275 	src << "void main (void)\n{\n"
   1276 		<< "	gl_Position = vec4(gl_VertexID/2, gl_VertexID%2, 0.0, 1.0);\n"
   1277 		<< "}\n";
   1278 
   1279 	return src.str();
   1280 }
   1281 
   1282 class CheckTessSupport
   1283 {
   1284 public:
   1285 	inline CheckTessSupport (const glu::RenderContext& renderCtx)
   1286 	{
   1287 		if (renderCtx.getType().getAPI().getProfile() == glu::PROFILE_ES)
   1288 			checkExtension(renderCtx, "GL_EXT_tessellation_shader");
   1289 	}
   1290 };
   1291 
   1292 // TessControlExecutor
   1293 
   1294 class TessControlExecutor : private CheckTessSupport, public BufferIoExecutor
   1295 {
   1296 public:
   1297 						TessControlExecutor			(const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec);
   1298 						~TessControlExecutor		(void);
   1299 
   1300 	void				execute						(int numValues, const void* const* inputs, void* const* outputs);
   1301 
   1302 protected:
   1303 	static std::string	generateTessControlShader	(const ShaderSpec& shaderSpec);
   1304 };
   1305 
   1306 std::string TessControlExecutor::generateTessControlShader (const ShaderSpec& shaderSpec)
   1307 {
   1308 	std::ostringstream src;
   1309 
   1310 	src << glu::getGLSLVersionDeclaration(shaderSpec.version) << "\n";
   1311 
   1312 	if (shaderSpec.version == glu::GLSL_VERSION_310_ES)
   1313 		src << "#extension GL_EXT_tessellation_shader : require\n";
   1314 
   1315 	if (!shaderSpec.globalDeclarations.empty())
   1316 		src << shaderSpec.globalDeclarations << "\n";
   1317 
   1318 	src << "\nlayout(vertices = 1) out;\n\n";
   1319 
   1320 	declareBufferBlocks(src, shaderSpec);
   1321 
   1322 	src << "void main (void)\n{\n";
   1323 
   1324 	for (int ndx = 0; ndx < 2; ndx++)
   1325 		src << "\tgl_TessLevelInner[" << ndx << "] = 1.0;\n";
   1326 
   1327 	for (int ndx = 0; ndx < 4; ndx++)
   1328 		src << "\tgl_TessLevelOuter[" << ndx << "] = 1.0;\n";
   1329 
   1330 	src << "\n"
   1331 		<< "\thighp uint invocationId = uint(gl_PrimitiveID);\n";
   1332 
   1333 	generateExecBufferIo(src, shaderSpec, "invocationId");
   1334 
   1335 	src << "}\n";
   1336 
   1337 	return src.str();
   1338 }
   1339 
   1340 static std::string generateEmptyTessEvalShader (glu::GLSLVersion version)
   1341 {
   1342 	std::ostringstream src;
   1343 
   1344 	src << glu::getGLSLVersionDeclaration(version) << "\n";
   1345 
   1346 	if (version == glu::GLSL_VERSION_310_ES)
   1347 		src << "#extension GL_EXT_tessellation_shader : require\n\n";
   1348 
   1349 	src << "layout(triangles, ccw) in;\n";
   1350 
   1351 	src << "\nvoid main (void)\n{\n"
   1352 		<< "\tgl_Position = vec4(gl_TessCoord.xy, 0.0, 1.0);\n"
   1353 		<< "}\n";
   1354 
   1355 	return src.str();
   1356 }
   1357 
   1358 TessControlExecutor::TessControlExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec)
   1359 	: CheckTessSupport	(renderCtx)
   1360 	, BufferIoExecutor	(renderCtx, shaderSpec, glu::ProgramSources()
   1361 							<< glu::VertexSource(generateVertexShaderForTess(shaderSpec.version))
   1362 							<< glu::TessellationControlSource(generateTessControlShader(shaderSpec))
   1363 							<< glu::TessellationEvaluationSource(generateEmptyTessEvalShader(shaderSpec.version))
   1364 							<< glu::FragmentSource(generateEmptyFragmentSource(shaderSpec.version)))
   1365 {
   1366 }
   1367 
   1368 TessControlExecutor::~TessControlExecutor (void)
   1369 {
   1370 }
   1371 
   1372 void TessControlExecutor::execute (int numValues, const void* const* inputs, void* const* outputs)
   1373 {
   1374 	const glw::Functions&	gl	= m_renderCtx.getFunctions();
   1375 
   1376 	initBuffers(numValues);
   1377 
   1378 	// Setup input buffer & copy data
   1379 	uploadInputBuffer(inputs, numValues);
   1380 
   1381 	if (!m_inputs.empty())
   1382 		gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, INPUT_BUFFER_BINDING, getInputBuffer());
   1383 
   1384 	gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, OUTPUT_BUFFER_BINDING, getOutputBuffer());
   1385 
   1386 	// Render patches
   1387 	gl.patchParameteri(GL_PATCH_VERTICES, 3);
   1388 	gl.drawArrays(GL_PATCHES, 0, 3*numValues);
   1389 
   1390 	// Read back data
   1391 	readOutputBuffer(outputs, numValues);
   1392 }
   1393 
   1394 // TessEvaluationExecutor
   1395 
   1396 class TessEvaluationExecutor : private CheckTessSupport, public BufferIoExecutor
   1397 {
   1398 public:
   1399 						TessEvaluationExecutor	(const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec);
   1400 						~TessEvaluationExecutor	(void);
   1401 
   1402 	void				execute					(int numValues, const void* const* inputs, void* const* outputs);
   1403 
   1404 protected:
   1405 	static std::string	generateTessEvalShader	(const ShaderSpec& shaderSpec);
   1406 };
   1407 
   1408 static std::string generatePassthroughTessControlShader (glu::GLSLVersion version)
   1409 {
   1410 	std::ostringstream src;
   1411 
   1412 	src << glu::getGLSLVersionDeclaration(version) << "\n";
   1413 
   1414 	if (version == glu::GLSL_VERSION_310_ES)
   1415 		src << "#extension GL_EXT_tessellation_shader : require\n\n";
   1416 
   1417 	src << "layout(vertices = 1) out;\n\n";
   1418 
   1419 	src << "void main (void)\n{\n";
   1420 
   1421 	for (int ndx = 0; ndx < 2; ndx++)
   1422 		src << "\tgl_TessLevelInner[" << ndx << "] = 1.0;\n";
   1423 
   1424 	for (int ndx = 0; ndx < 4; ndx++)
   1425 		src << "\tgl_TessLevelOuter[" << ndx << "] = 1.0;\n";
   1426 
   1427 	src << "}\n";
   1428 
   1429 	return src.str();
   1430 }
   1431 
   1432 std::string TessEvaluationExecutor::generateTessEvalShader (const ShaderSpec& shaderSpec)
   1433 {
   1434 	std::ostringstream src;
   1435 
   1436 	src << glu::getGLSLVersionDeclaration(shaderSpec.version) << "\n";
   1437 
   1438 	if (shaderSpec.version == glu::GLSL_VERSION_310_ES)
   1439 		src << "#extension GL_EXT_tessellation_shader : require\n";
   1440 
   1441 	if (!shaderSpec.globalDeclarations.empty())
   1442 		src << shaderSpec.globalDeclarations << "\n";
   1443 
   1444 	src << "\n";
   1445 
   1446 	src << "layout(isolines, equal_spacing) in;\n\n";
   1447 
   1448 	declareBufferBlocks(src, shaderSpec);
   1449 
   1450 	src << "void main (void)\n{\n"
   1451 		<< "\tgl_Position = vec4(gl_TessCoord.x, 0.0, 0.0, 1.0);\n"
   1452 		<< "\thighp uint invocationId = uint(gl_PrimitiveID) + (gl_TessCoord.x > 0.5 ? 1u : 0u);\n";
   1453 
   1454 	generateExecBufferIo(src, shaderSpec, "invocationId");
   1455 
   1456 	src	<< "}\n";
   1457 
   1458 	return src.str();
   1459 }
   1460 
   1461 TessEvaluationExecutor::TessEvaluationExecutor (const glu::RenderContext& renderCtx, const ShaderSpec& shaderSpec)
   1462 	: CheckTessSupport	(renderCtx)
   1463 	, BufferIoExecutor	(renderCtx, shaderSpec, glu::ProgramSources()
   1464 							<< glu::VertexSource(generateVertexShaderForTess(shaderSpec.version))
   1465 							<< glu::TessellationControlSource(generatePassthroughTessControlShader(shaderSpec.version))
   1466 							<< glu::TessellationEvaluationSource(generateTessEvalShader(shaderSpec))
   1467 							<< glu::FragmentSource(generateEmptyFragmentSource(shaderSpec.version)))
   1468 {
   1469 }
   1470 
   1471 TessEvaluationExecutor::~TessEvaluationExecutor (void)
   1472 {
   1473 }
   1474 
   1475 void TessEvaluationExecutor::execute (int numValues, const void* const* inputs, void* const* outputs)
   1476 {
   1477 	const glw::Functions&	gl				= m_renderCtx.getFunctions();
   1478 	const int				alignedValues	= deAlign32(numValues, 2);
   1479 
   1480 	// Initialize buffers with aligned value count to make room for padding
   1481 	initBuffers(alignedValues);
   1482 
   1483 	// Setup input buffer & copy data
   1484 	uploadInputBuffer(inputs, numValues);
   1485 
   1486 	// \todo [2014-06-26 pyry] Duplicate last value in the buffer to prevent infinite loops for example?
   1487 
   1488 	if (!m_inputs.empty())
   1489 		gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, INPUT_BUFFER_BINDING, getInputBuffer());
   1490 
   1491 	gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, OUTPUT_BUFFER_BINDING, getOutputBuffer());
   1492 
   1493 	// Render patches
   1494 	gl.patchParameteri(GL_PATCH_VERTICES, 2);
   1495 	gl.drawArrays(GL_PATCHES, 0, 2*alignedValues);
   1496 
   1497 	// Read back data
   1498 	readOutputBuffer(outputs, numValues);
   1499 }
   1500 
   1501 // Utilities
   1502 
   1503 ShaderExecutor* createExecutor (const glu::RenderContext& renderCtx, glu::ShaderType shaderType, const ShaderSpec& shaderSpec)
   1504 {
   1505 	switch (shaderType)
   1506 	{
   1507 		case glu::SHADERTYPE_VERTEX:					return new VertexShaderExecutor		(renderCtx, shaderSpec);
   1508 		case glu::SHADERTYPE_TESSELLATION_CONTROL:		return new TessControlExecutor		(renderCtx, shaderSpec);
   1509 		case glu::SHADERTYPE_TESSELLATION_EVALUATION:	return new TessEvaluationExecutor	(renderCtx, shaderSpec);
   1510 		case glu::SHADERTYPE_GEOMETRY:					return new GeometryShaderExecutor	(renderCtx, shaderSpec);
   1511 		case glu::SHADERTYPE_FRAGMENT:					return new FragmentShaderExecutor	(renderCtx, shaderSpec);
   1512 		case glu::SHADERTYPE_COMPUTE:					return new ComputeShaderExecutor	(renderCtx, shaderSpec);
   1513 		default:
   1514 			throw tcu::InternalError("Unsupported shader type");
   1515 	}
   1516 }
   1517 
   1518 } // ShaderExecUtil
   1519 } // gls
   1520 } // deqp
   1521