Home | History | Annotate | Download | only in shaderexecutor
      1 /*------------------------------------------------------------------------
      2  * Vulkan Conformance Tests
      3  * ------------------------
      4  *
      5  * Copyright (c) 2015 The Khronos Group Inc.
      6  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
      7  * Copyright (c) 2016 The Android Open Source Project
      8  *
      9  * Licensed under the Apache License, Version 2.0 (the "License");
     10  * you may not use this file except in compliance with the License.
     11  * You may obtain a copy of the License at
     12  *
     13  *      http://www.apache.org/licenses/LICENSE-2.0
     14  *
     15  * Unless required by applicable law or agreed to in writing, software
     16  * distributed under the License is distributed on an "AS IS" BASIS,
     17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     18  * See the License for the specific language governing permissions and
     19  * limitations under the License.
     20  *
     21  *//*!
     22  * \file
     23  * \brief Vulkan ShaderExecutor
     24  *//*--------------------------------------------------------------------*/
     25 
     26 #include "vktShaderExecutor.hpp"
     27 
     28 #include "vkMemUtil.hpp"
     29 #include "vkRef.hpp"
     30 #include "vkPrograms.hpp"
     31 #include "vkRefUtil.hpp"
     32 #include "vkTypeUtil.hpp"
     33 #include "vkQueryUtil.hpp"
     34 #include "vkBuilderUtil.hpp"
     35 
     36 #include "gluShaderUtil.hpp"
     37 
     38 #include "tcuVector.hpp"
     39 #include "tcuTestLog.hpp"
     40 #include "tcuTextureUtil.hpp"
     41 
     42 #include "deUniquePtr.hpp"
     43 #include "deStringUtil.hpp"
     44 #include "deSharedPtr.hpp"
     45 
     46 #include <map>
     47 #include <sstream>
     48 #include <iostream>
     49 
     50 using std::vector;
     51 using namespace vk;
     52 
     53 namespace vkt
     54 {
     55 namespace shaderexecutor
     56 {
     57 namespace
     58 {
     59 
     60 enum
     61 {
     62 	DEFAULT_RENDER_WIDTH	= 100,
     63 	DEFAULT_RENDER_HEIGHT	= 100,
     64 };
     65 
     66 // Common typedefs
     67 
     68 typedef de::SharedPtr<Unique<VkImage> >		VkImageSp;
     69 typedef de::SharedPtr<Unique<VkImageView> >	VkImageViewSp;
     70 typedef de::SharedPtr<Unique<VkBuffer> >	VkBufferSp;
     71 typedef de::SharedPtr<Allocation>			AllocationSp;
     72 
     73 // Shader utilities
     74 
     75 static VkClearValue	getDefaultClearColor (void)
     76 {
     77 	return makeClearValueColorF32(0.125f, 0.25f, 0.5f, 1.0f);
     78 }
     79 
     80 static std::string generateEmptyFragmentSource (void)
     81 {
     82 	std::ostringstream src;
     83 
     84 	src << "#version 310 es\n"
     85 		   "layout(location=0) out highp vec4 o_color;\n";
     86 
     87 	src << "void main (void)\n{\n";
     88 	src << "	o_color = vec4(0.0);\n";
     89 	src << "}\n";
     90 
     91 	return src.str();
     92 }
     93 
     94 static std::string generatePassthroughVertexShader (const std::vector<Symbol>& inputs, const char* inputPrefix, const char* outputPrefix)
     95 {
     96 
     97 	std::ostringstream	src;
     98 	int					location	= 0;
     99 
    100 	src << "#version 310 es\n"
    101 		   "layout(location = " << location << ") in highp vec4 a_position;\n";
    102 
    103 	for (vector<Symbol>::const_iterator input = inputs.begin(); input != inputs.end(); ++input)
    104 	{
    105 		location++;
    106 		src << "layout(location = "<< location << ") in " << glu::declare(input->varType, inputPrefix + input->name) << ";\n"
    107 			<< "layout(location = " << location - 1 << ") flat out " << glu::declare(input->varType, outputPrefix + input->name) << ";\n";
    108 	}
    109 
    110 	src << "\nvoid main (void)\n{\n"
    111 		<< "	gl_Position = a_position;\n"
    112 		<< "	gl_PointSize = 1.0;\n";
    113 
    114 	for (vector<Symbol>::const_iterator input = inputs.begin(); input != inputs.end(); ++input)
    115 		src << "\t" << outputPrefix << input->name << " = " << inputPrefix << input->name << ";\n";
    116 
    117 	src << "}\n";
    118 
    119 	return src.str();
    120 }
    121 
    122 static std::string generateVertexShader (const ShaderSpec& shaderSpec, const std::string& inputPrefix, const std::string& outputPrefix)
    123 {
    124 	DE_ASSERT(!inputPrefix.empty() && !outputPrefix.empty());
    125 
    126 	std::ostringstream	src;
    127 
    128 	src << glu::getGLSLVersionDeclaration(shaderSpec.glslVersion) << "\n";
    129 
    130 	if (!shaderSpec.globalDeclarations.empty())
    131 		src << shaderSpec.globalDeclarations << "\n";
    132 
    133 	src << "layout(location = 0) in highp vec4 a_position;\n";
    134 
    135 	int locationNumber = 1;
    136 	for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input, ++locationNumber)
    137 		src <<  "layout(location = " << locationNumber << ") in " << glu::declare(input->varType, inputPrefix + input->name) << ";\n";
    138 
    139 	locationNumber = 0;
    140 	for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output, ++locationNumber)
    141 	{
    142 		DE_ASSERT(output->varType.isBasicType());
    143 
    144 		if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType()))
    145 		{
    146 			const int				vecSize		= glu::getDataTypeScalarSize(output->varType.getBasicType());
    147 			const glu::DataType		intBaseType	= vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
    148 			const glu::VarType		intType		(intBaseType, glu::PRECISION_HIGHP);
    149 
    150 			src << "layout(location = " << locationNumber << ") flat out " << glu::declare(intType, outputPrefix + output->name) << ";\n";
    151 		}
    152 		else
    153 			src << "layout(location = " << locationNumber << ") flat out " << glu::declare(output->varType, outputPrefix + output->name) << ";\n";
    154 	}
    155 
    156 	src << "\n"
    157 		<< "void main (void)\n"
    158 		<< "{\n"
    159 		<< "	gl_Position = a_position;\n"
    160 		<< "	gl_PointSize = 1.0;\n";
    161 
    162 	// Declare & fetch local input variables
    163 	for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input)
    164 		src << "\t" << glu::declare(input->varType, input->name) << " = " << inputPrefix << input->name << ";\n";
    165 
    166 	// Declare local output variables
    167 	for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output)
    168 		src << "\t" << glu::declare(output->varType, output->name) << ";\n";
    169 
    170 	// Operation - indented to correct level.
    171 	{
    172 		std::istringstream	opSrc	(shaderSpec.source);
    173 		std::string			line;
    174 
    175 		while (std::getline(opSrc, line))
    176 			src << "\t" << line << "\n";
    177 	}
    178 
    179 	// Assignments to outputs.
    180 	for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output)
    181 	{
    182 		if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType()))
    183 		{
    184 			const int				vecSize		= glu::getDataTypeScalarSize(output->varType.getBasicType());
    185 			const glu::DataType		intBaseType	= vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
    186 
    187 			src << "\t" << outputPrefix << output->name << " = " << glu::getDataTypeName(intBaseType) << "(" << output->name << ");\n";
    188 		}
    189 		else
    190 			src << "\t" << outputPrefix << output->name << " = " << output->name << ";\n";
    191 	}
    192 
    193 	src << "}\n";
    194 
    195 	return src.str();
    196 }
    197 
    198 struct FragmentOutputLayout
    199 {
    200 	std::vector<const Symbol*>		locationSymbols;		//! Symbols by location
    201 	std::map<std::string, int>		locationMap;			//! Map from symbol name to start location
    202 };
    203 
    204 static void generateFragShaderOutputDecl (std::ostream& src, const ShaderSpec& shaderSpec, bool useIntOutputs, const std::map<std::string, int>& outLocationMap, const std::string& outputPrefix)
    205 {
    206 	for (int outNdx = 0; outNdx < (int)shaderSpec.outputs.size(); ++outNdx)
    207 	{
    208 		const Symbol&				output		= shaderSpec.outputs[outNdx];
    209 		const int					location	= de::lookup(outLocationMap, output.name);
    210 		const std::string			outVarName	= outputPrefix + output.name;
    211 		glu::VariableDeclaration	decl		(output.varType, outVarName, glu::STORAGE_OUT, glu::INTERPOLATION_LAST, glu::Layout(location));
    212 
    213 		TCU_CHECK_INTERNAL(output.varType.isBasicType());
    214 
    215 		if (useIntOutputs && glu::isDataTypeFloatOrVec(output.varType.getBasicType()))
    216 		{
    217 			const int			vecSize			= glu::getDataTypeScalarSize(output.varType.getBasicType());
    218 			const glu::DataType	uintBasicType	= vecSize > 1 ? glu::getDataTypeUintVec(vecSize) : glu::TYPE_UINT;
    219 			const glu::VarType	uintType		(uintBasicType, glu::PRECISION_HIGHP);
    220 
    221 			decl.varType = uintType;
    222 			src << decl << ";\n";
    223 		}
    224 		else if (glu::isDataTypeBoolOrBVec(output.varType.getBasicType()))
    225 		{
    226 			const int			vecSize			= glu::getDataTypeScalarSize(output.varType.getBasicType());
    227 			const glu::DataType	intBasicType	= vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
    228 			const glu::VarType	intType			(intBasicType, glu::PRECISION_HIGHP);
    229 
    230 			decl.varType = intType;
    231 			src << decl << ";\n";
    232 		}
    233 		else if (glu::isDataTypeMatrix(output.varType.getBasicType()))
    234 		{
    235 			const int			vecSize			= glu::getDataTypeMatrixNumRows(output.varType.getBasicType());
    236 			const int			numVecs			= glu::getDataTypeMatrixNumColumns(output.varType.getBasicType());
    237 			const glu::DataType	uintBasicType	= glu::getDataTypeUintVec(vecSize);
    238 			const glu::VarType	uintType		(uintBasicType, glu::PRECISION_HIGHP);
    239 
    240 			decl.varType = uintType;
    241 			for (int vecNdx = 0; vecNdx < numVecs; ++vecNdx)
    242 			{
    243 				decl.name				= outVarName + "_" + de::toString(vecNdx);
    244 				decl.layout.location	= location + vecNdx;
    245 				src << decl << ";\n";
    246 			}
    247 		}
    248 		else
    249 			src << decl << ";\n";
    250 	}
    251 }
    252 
    253 static void generateFragShaderOutAssign (std::ostream& src, const ShaderSpec& shaderSpec, bool useIntOutputs, const std::string& valuePrefix, const std::string& outputPrefix)
    254 {
    255 	for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output)
    256 	{
    257 		if (useIntOutputs && glu::isDataTypeFloatOrVec(output->varType.getBasicType()))
    258 			src << "	o_" << output->name << " = floatBitsToUint(" << valuePrefix << output->name << ");\n";
    259 		else if (glu::isDataTypeMatrix(output->varType.getBasicType()))
    260 		{
    261 			const int	numVecs		= glu::getDataTypeMatrixNumColumns(output->varType.getBasicType());
    262 
    263 			for (int vecNdx = 0; vecNdx < numVecs; ++vecNdx)
    264 				if (useIntOutputs)
    265 					src << "\t" << outputPrefix << output->name << "_" << vecNdx << " = floatBitsToUint(" << valuePrefix << output->name << "[" << vecNdx << "]);\n";
    266 				else
    267 					src << "\t" << outputPrefix << output->name << "_" << vecNdx << " = " << valuePrefix << output->name << "[" << vecNdx << "];\n";
    268 		}
    269 		else if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType()))
    270 		{
    271 			const int				vecSize		= glu::getDataTypeScalarSize(output->varType.getBasicType());
    272 			const glu::DataType		intBaseType	= vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
    273 
    274 			src << "\t" << outputPrefix << output->name << " = " << glu::getDataTypeName(intBaseType) << "(" << valuePrefix << output->name << ");\n";
    275 		}
    276 		else
    277 			src << "\t" << outputPrefix << output->name << " = " << valuePrefix << output->name << ";\n";
    278 	}
    279 }
    280 
    281 static std::string generatePassthroughFragmentShader (const ShaderSpec& shaderSpec, bool useIntOutputs, const std::map<std::string, int>& outLocationMap, const std::string& inputPrefix, const std::string& outputPrefix)
    282 {
    283 	std::ostringstream	src;
    284 
    285 	src <<"#version 310 es\n";
    286 
    287 	if (!shaderSpec.globalDeclarations.empty())
    288 		src << shaderSpec.globalDeclarations << "\n";
    289 
    290 	int locationNumber = 0;
    291 	for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output, ++locationNumber)
    292 	{
    293 		if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType()))
    294 		{
    295 			const int				vecSize		= glu::getDataTypeScalarSize(output->varType.getBasicType());
    296 			const glu::DataType		intBaseType	= vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
    297 			const glu::VarType		intType		(intBaseType, glu::PRECISION_HIGHP);
    298 
    299 			src << "layout(location = " << locationNumber << ") flat in " << glu::declare(intType, inputPrefix + output->name) << ";\n";
    300 		}
    301 		else
    302 			src << "layout(location = " << locationNumber << ") flat in " << glu::declare(output->varType, inputPrefix + output->name) << ";\n";
    303 	}
    304 
    305 	generateFragShaderOutputDecl(src, shaderSpec, useIntOutputs, outLocationMap, outputPrefix);
    306 
    307 	src << "\nvoid main (void)\n{\n";
    308 
    309 	generateFragShaderOutAssign(src, shaderSpec, useIntOutputs, inputPrefix, outputPrefix);
    310 
    311 	src << "}\n";
    312 
    313 	return src.str();
    314 }
    315 
    316 static std::string generateGeometryShader (const ShaderSpec& shaderSpec, const std::string& inputPrefix, const std::string& outputPrefix)
    317 {
    318 	DE_ASSERT(!inputPrefix.empty() && !outputPrefix.empty());
    319 
    320 	std::ostringstream	src;
    321 
    322 	src << glu::getGLSLVersionDeclaration(shaderSpec.glslVersion) << "\n";
    323 
    324 	if (shaderSpec.glslVersion == glu::GLSL_VERSION_310_ES)
    325 		src << "#extension GL_EXT_geometry_shader : require\n";
    326 
    327 	if (!shaderSpec.globalDeclarations.empty())
    328 		src << shaderSpec.globalDeclarations << "\n";
    329 
    330 	src << "layout(points) in;\n"
    331 		<< "layout(points, max_vertices = 1) out;\n";
    332 
    333 	int locationNumber = 0;
    334 	for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input, ++locationNumber)
    335 		src << "layout(location = " << locationNumber << ") flat in " << glu::declare(input->varType, inputPrefix + input->name) << "[];\n";
    336 
    337 	locationNumber = 0;
    338 	for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output, ++locationNumber)
    339 	{
    340 		DE_ASSERT(output->varType.isBasicType());
    341 
    342 		if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType()))
    343 		{
    344 			const int				vecSize		= glu::getDataTypeScalarSize(output->varType.getBasicType());
    345 			const glu::DataType		intBaseType	= vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
    346 			const glu::VarType		intType		(intBaseType, glu::PRECISION_HIGHP);
    347 
    348 			src << "layout(location = " << locationNumber << ") flat out " << glu::declare(intType, outputPrefix + output->name) << ";\n";
    349 		}
    350 		else
    351 			src << "layout(location = " << locationNumber << ") flat out " << glu::declare(output->varType, outputPrefix + output->name) << ";\n";
    352 	}
    353 
    354 	src << "\n"
    355 		<< "void main (void)\n"
    356 		<< "{\n"
    357 		<< "	gl_Position = gl_in[0].gl_Position;\n\n";
    358 
    359 	// Fetch input variables
    360 	for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input)
    361 		src << "\t" << glu::declare(input->varType, input->name) << " = " << inputPrefix << input->name << "[0];\n";
    362 
    363 	// Declare local output variables.
    364 	for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output)
    365 		src << "\t" << glu::declare(output->varType, output->name) << ";\n";
    366 
    367 	src << "\n";
    368 
    369 	// Operation - indented to correct level.
    370 	{
    371 		std::istringstream	opSrc	(shaderSpec.source);
    372 		std::string			line;
    373 
    374 		while (std::getline(opSrc, line))
    375 			src << "\t" << line << "\n";
    376 	}
    377 
    378 	// Assignments to outputs.
    379 	for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output)
    380 	{
    381 		if (glu::isDataTypeBoolOrBVec(output->varType.getBasicType()))
    382 		{
    383 			const int				vecSize		= glu::getDataTypeScalarSize(output->varType.getBasicType());
    384 			const glu::DataType		intBaseType	= vecSize > 1 ? glu::getDataTypeIntVec(vecSize) : glu::TYPE_INT;
    385 
    386 			src << "\t" << outputPrefix << output->name << " = " << glu::getDataTypeName(intBaseType) << "(" << output->name << ");\n";
    387 		}
    388 		else
    389 			src << "\t" << outputPrefix << output->name << " = " << output->name << ";\n";
    390 	}
    391 
    392 	src << "	EmitVertex();\n"
    393 		<< "	EndPrimitive();\n"
    394 		<< "}\n";
    395 
    396 	return src.str();
    397 }
    398 
    399 static std::string generateFragmentShader (const ShaderSpec& shaderSpec, bool useIntOutputs, const std::map<std::string, int>& outLocationMap, const std::string& inputPrefix, const std::string& outputPrefix)
    400 {
    401 	std::ostringstream src;
    402 	src << glu::getGLSLVersionDeclaration(shaderSpec.glslVersion) << "\n";
    403 	if (!shaderSpec.globalDeclarations.empty())
    404 		src << shaderSpec.globalDeclarations << "\n";
    405 
    406 	int locationNumber = 0;
    407 	for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input, ++locationNumber)
    408 		src << "layout(location = " << locationNumber << ") flat in " << glu::declare(input->varType, inputPrefix + input->name) << ";\n";
    409 
    410 	generateFragShaderOutputDecl(src, shaderSpec, useIntOutputs, outLocationMap, outputPrefix);
    411 
    412 	src << "\nvoid main (void)\n{\n";
    413 
    414 	// Declare & fetch local input variables
    415 	for (vector<Symbol>::const_iterator input = shaderSpec.inputs.begin(); input != shaderSpec.inputs.end(); ++input)
    416 		src << "\t" << glu::declare(input->varType, input->name) << " = " << inputPrefix << input->name << ";\n";
    417 
    418 	// Declare output variables
    419 	for (vector<Symbol>::const_iterator output = shaderSpec.outputs.begin(); output != shaderSpec.outputs.end(); ++output)
    420 		src << "\t" << glu::declare(output->varType, output->name) << ";\n";
    421 
    422 	// Operation - indented to correct level.
    423 	{
    424 		std::istringstream	opSrc	(shaderSpec.source);
    425 		std::string			line;
    426 
    427 		while (std::getline(opSrc, line))
    428 			src << "\t" << line << "\n";
    429 	}
    430 
    431 	generateFragShaderOutAssign(src, shaderSpec, useIntOutputs, "", outputPrefix);
    432 
    433 	src << "}\n";
    434 
    435 	return src.str();
    436 }
    437 
    438 // FragmentOutExecutor
    439 
    440 class FragmentOutExecutor : public ShaderExecutor
    441 {
    442 public:
    443 														FragmentOutExecutor		(Context& context, glu::ShaderType shaderType, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout);
    444 	virtual												~FragmentOutExecutor	(void);
    445 
    446 	virtual void										execute					(int					numValues,
    447 																				 const void* const*		inputs,
    448 																				 void* const*			outputs,
    449 																				 VkDescriptorSet		extraResources);
    450 
    451 protected:
    452 	const glu::ShaderType								m_shaderType;
    453 	const FragmentOutputLayout							m_outputLayout;
    454 
    455 private:
    456 	void												bindAttributes			(int					numValues,
    457 																				 const void* const*		inputs);
    458 
    459 	void												addAttribute			(deUint32				bindingLocation,
    460 																				 VkFormat				format,
    461 																				 deUint32				sizePerElement,
    462 																				 deUint32				count,
    463 																				 const void*			dataPtr);
    464 	// reinit render data members
    465 	virtual void										clearRenderData			(void);
    466 
    467 	const VkDescriptorSetLayout							m_extraResourcesLayout;
    468 
    469 	std::vector<VkVertexInputBindingDescription>		m_vertexBindingDescriptions;
    470 	std::vector<VkVertexInputAttributeDescription>		m_vertexAttributeDescriptions;
    471 	std::vector<VkBufferSp>								m_vertexBuffers;
    472 	std::vector<AllocationSp>							m_vertexBufferAllocs;
    473 };
    474 
    475 static FragmentOutputLayout computeFragmentOutputLayout (const std::vector<Symbol>& symbols)
    476 {
    477 	FragmentOutputLayout	ret;
    478 	int						location	= 0;
    479 
    480 	for (std::vector<Symbol>::const_iterator it = symbols.begin(); it != symbols.end(); ++it)
    481 	{
    482 		const int	numLocations	= glu::getDataTypeNumLocations(it->varType.getBasicType());
    483 
    484 		TCU_CHECK_INTERNAL(!de::contains(ret.locationMap, it->name));
    485 		de::insert(ret.locationMap, it->name, location);
    486 		location += numLocations;
    487 
    488 		for (int ndx = 0; ndx < numLocations; ++ndx)
    489 			ret.locationSymbols.push_back(&*it);
    490 	}
    491 
    492 	return ret;
    493 }
    494 
    495 FragmentOutExecutor::FragmentOutExecutor (Context& context, glu::ShaderType shaderType, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout)
    496 	: ShaderExecutor			(context, shaderSpec)
    497 	, m_shaderType				(shaderType)
    498 	, m_outputLayout			(computeFragmentOutputLayout(m_shaderSpec.outputs))
    499 	, m_extraResourcesLayout	(extraResourcesLayout)
    500 {
    501 }
    502 
    503 FragmentOutExecutor::~FragmentOutExecutor (void)
    504 {
    505 }
    506 
    507 static std::vector<tcu::Vec2> computeVertexPositions (int numValues, const tcu::IVec2& renderSize)
    508 {
    509 	std::vector<tcu::Vec2> positions(numValues);
    510 	for (int valNdx = 0; valNdx < numValues; valNdx++)
    511 	{
    512 		const int		ix		= valNdx % renderSize.x();
    513 		const int		iy		= valNdx / renderSize.x();
    514 		const float		fx		= -1.0f + 2.0f*((float(ix) + 0.5f) / float(renderSize.x()));
    515 		const float		fy		= -1.0f + 2.0f*((float(iy) + 0.5f) / float(renderSize.y()));
    516 
    517 		positions[valNdx] = tcu::Vec2(fx, fy);
    518 	}
    519 
    520 	return positions;
    521 }
    522 
    523 static tcu::TextureFormat getRenderbufferFormatForOutput (const glu::VarType& outputType, bool useIntOutputs)
    524 {
    525 	const tcu::TextureFormat::ChannelOrder channelOrderMap[] =
    526 	{
    527 		tcu::TextureFormat::R,
    528 		tcu::TextureFormat::RG,
    529 		tcu::TextureFormat::RGBA,	// No RGB variants available.
    530 		tcu::TextureFormat::RGBA
    531 	};
    532 
    533 	const glu::DataType					basicType		= outputType.getBasicType();
    534 	const int							numComps		= glu::getDataTypeNumComponents(basicType);
    535 	tcu::TextureFormat::ChannelType		channelType;
    536 
    537 	switch (glu::getDataTypeScalarType(basicType))
    538 	{
    539 		case glu::TYPE_UINT:	channelType = tcu::TextureFormat::UNSIGNED_INT32;												break;
    540 		case glu::TYPE_INT:		channelType = tcu::TextureFormat::SIGNED_INT32;													break;
    541 		case glu::TYPE_BOOL:	channelType = tcu::TextureFormat::SIGNED_INT32;													break;
    542 		case glu::TYPE_FLOAT:	channelType = useIntOutputs ? tcu::TextureFormat::UNSIGNED_INT32 : tcu::TextureFormat::FLOAT;	break;
    543 		default:
    544 			throw tcu::InternalError("Invalid output type");
    545 	}
    546 
    547 	DE_ASSERT(de::inRange<int>(numComps, 1, DE_LENGTH_OF_ARRAY(channelOrderMap)));
    548 
    549 	return tcu::TextureFormat(channelOrderMap[numComps-1], channelType);
    550 }
    551 
    552 static VkFormat getAttributeFormat (const glu::DataType dataType)
    553 {
    554 	switch (dataType)
    555 	{
    556 		case glu::TYPE_FLOAT:			return VK_FORMAT_R32_SFLOAT;
    557 		case glu::TYPE_FLOAT_VEC2:		return VK_FORMAT_R32G32_SFLOAT;
    558 		case glu::TYPE_FLOAT_VEC3:		return VK_FORMAT_R32G32B32_SFLOAT;
    559 		case glu::TYPE_FLOAT_VEC4:		return VK_FORMAT_R32G32B32A32_SFLOAT;
    560 
    561 		case glu::TYPE_INT:				return VK_FORMAT_R32_SINT;
    562 		case glu::TYPE_INT_VEC2:		return VK_FORMAT_R32G32_SINT;
    563 		case glu::TYPE_INT_VEC3:		return VK_FORMAT_R32G32B32_SINT;
    564 		case glu::TYPE_INT_VEC4:		return VK_FORMAT_R32G32B32A32_SINT;
    565 
    566 		case glu::TYPE_UINT:			return VK_FORMAT_R32_UINT;
    567 		case glu::TYPE_UINT_VEC2:		return VK_FORMAT_R32G32_UINT;
    568 		case glu::TYPE_UINT_VEC3:		return VK_FORMAT_R32G32B32_UINT;
    569 		case glu::TYPE_UINT_VEC4:		return VK_FORMAT_R32G32B32A32_UINT;
    570 
    571 		case glu::TYPE_FLOAT_MAT2:		return VK_FORMAT_R32G32_SFLOAT;
    572 		case glu::TYPE_FLOAT_MAT2X3:	return VK_FORMAT_R32G32B32_SFLOAT;
    573 		case glu::TYPE_FLOAT_MAT2X4:	return VK_FORMAT_R32G32B32A32_SFLOAT;
    574 		case glu::TYPE_FLOAT_MAT3X2:	return VK_FORMAT_R32G32_SFLOAT;
    575 		case glu::TYPE_FLOAT_MAT3:		return VK_FORMAT_R32G32B32_SFLOAT;
    576 		case glu::TYPE_FLOAT_MAT3X4:	return VK_FORMAT_R32G32B32A32_SFLOAT;
    577 		case glu::TYPE_FLOAT_MAT4X2:	return VK_FORMAT_R32G32_SFLOAT;
    578 		case glu::TYPE_FLOAT_MAT4X3:	return VK_FORMAT_R32G32B32_SFLOAT;
    579 		case glu::TYPE_FLOAT_MAT4:		return VK_FORMAT_R32G32B32A32_SFLOAT;
    580 		default:
    581 			DE_ASSERT(false);
    582 			return VK_FORMAT_UNDEFINED;
    583 	}
    584 }
    585 
    586 void FragmentOutExecutor::addAttribute (deUint32 bindingLocation, VkFormat format, deUint32 sizePerElement, deUint32 count, const void* dataPtr)
    587 {
    588 	// Add binding specification
    589 	const deUint32							binding = (deUint32)m_vertexBindingDescriptions.size();
    590 	const VkVertexInputBindingDescription	bindingDescription =
    591 	{
    592 		binding,
    593 		sizePerElement,
    594 		VK_VERTEX_INPUT_RATE_VERTEX
    595 	};
    596 
    597 	m_vertexBindingDescriptions.push_back(bindingDescription);
    598 
    599 	// Add location and format specification
    600 	const VkVertexInputAttributeDescription attributeDescription =
    601 	{
    602 		bindingLocation,			// deUint32	location;
    603 		binding,					// deUint32	binding;
    604 		format,						// VkFormat	format;
    605 		0u,							// deUint32	offsetInBytes;
    606 	};
    607 
    608 	m_vertexAttributeDescriptions.push_back(attributeDescription);
    609 
    610 	// Upload data to buffer
    611 	const VkDevice				vkDevice			= m_context.getDevice();
    612 	const DeviceInterface&		vk					= m_context.getDeviceInterface();
    613 	const deUint32				queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
    614 
    615 	const VkDeviceSize			inputSize			= sizePerElement * count;
    616 	const VkBufferCreateInfo	vertexBufferParams	=
    617 	{
    618 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
    619 		DE_NULL,									// const void*			pNext;
    620 		0u,											// VkBufferCreateFlags	flags;
    621 		inputSize,									// VkDeviceSize			size;
    622 		VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			// VkBufferUsageFlags	usage;
    623 		VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
    624 		1u,											// deUint32				queueFamilyCount;
    625 		&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
    626 	};
    627 
    628 	Move<VkBuffer>			buffer	= createBuffer(vk, vkDevice, &vertexBufferParams);
    629 	de::MovePtr<Allocation>	alloc	= m_context.getDefaultAllocator().allocate(getBufferMemoryRequirements(vk, vkDevice, *buffer), MemoryRequirement::HostVisible);
    630 
    631 	VK_CHECK(vk.bindBufferMemory(vkDevice, *buffer, alloc->getMemory(), alloc->getOffset()));
    632 
    633 	deMemcpy(alloc->getHostPtr(), dataPtr, (size_t)inputSize);
    634 	flushMappedMemoryRange(vk, vkDevice, alloc->getMemory(), alloc->getOffset(), inputSize);
    635 
    636 	m_vertexBuffers.push_back(de::SharedPtr<Unique<VkBuffer> >(new Unique<VkBuffer>(buffer)));
    637 	m_vertexBufferAllocs.push_back(AllocationSp(alloc.release()));
    638 }
    639 
    640 void FragmentOutExecutor::bindAttributes (int numValues, const void* const* inputs)
    641 {
    642 	// Input attributes
    643 	for (int inputNdx = 0; inputNdx < (int)m_shaderSpec.inputs.size(); inputNdx++)
    644 	{
    645 		const Symbol&		symbol			= m_shaderSpec.inputs[inputNdx];
    646 		const void*			ptr				= inputs[inputNdx];
    647 		const glu::DataType	basicType		= symbol.varType.getBasicType();
    648 		const int			vecSize			= glu::getDataTypeScalarSize(basicType);
    649 		const VkFormat		format			= getAttributeFormat(basicType);
    650 		int					elementSize		= 0;
    651 		int					numAttrsToAdd	= 1;
    652 
    653 		if (glu::isDataTypeFloatOrVec(basicType))
    654 			elementSize = sizeof(float);
    655 		else if (glu::isDataTypeIntOrIVec(basicType))
    656 			elementSize = sizeof(int);
    657 		else if (glu::isDataTypeUintOrUVec(basicType))
    658 			elementSize = sizeof(deUint32);
    659 		else if (glu::isDataTypeMatrix(basicType))
    660 		{
    661 			int		numRows	= glu::getDataTypeMatrixNumRows(basicType);
    662 			int		numCols	= glu::getDataTypeMatrixNumColumns(basicType);
    663 
    664 			elementSize = numRows * numCols * (int)sizeof(float);
    665 			numAttrsToAdd = numCols;
    666 		}
    667 		else
    668 			DE_ASSERT(false);
    669 
    670 		// add attributes, in case of matrix every column is binded as an attribute
    671 		for (int attrNdx = 0; attrNdx < numAttrsToAdd; attrNdx++)
    672 		{
    673 			addAttribute((deUint32)m_vertexBindingDescriptions.size(), format, elementSize * vecSize, numValues, ptr);
    674 		}
    675 	}
    676 }
    677 
    678 void FragmentOutExecutor::clearRenderData (void)
    679 {
    680 	m_vertexBindingDescriptions.clear();
    681 	m_vertexAttributeDescriptions.clear();
    682 	m_vertexBuffers.clear();
    683 	m_vertexBufferAllocs.clear();
    684 }
    685 
    686 static Move<VkDescriptorSetLayout> createEmptyDescriptorSetLayout (const DeviceInterface& vkd, VkDevice device)
    687 {
    688 	const VkDescriptorSetLayoutCreateInfo	createInfo	=
    689 	{
    690 		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
    691 		DE_NULL,
    692 		(VkDescriptorSetLayoutCreateFlags)0,
    693 		0u,
    694 		DE_NULL,
    695 	};
    696 	return createDescriptorSetLayout(vkd, device, &createInfo);
    697 }
    698 
    699 static Move<VkDescriptorPool> createDummyDescriptorPool (const DeviceInterface& vkd, VkDevice device)
    700 {
    701 	const VkDescriptorPoolSize			dummySize	=
    702 	{
    703 		VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
    704 		1u,
    705 	};
    706 	const VkDescriptorPoolCreateInfo	createInfo	=
    707 	{
    708 		VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
    709 		DE_NULL,
    710 		(VkDescriptorPoolCreateFlags)VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
    711 		1u,
    712 		1u,
    713 		&dummySize
    714 	};
    715 	return createDescriptorPool(vkd, device, &createInfo);
    716 }
    717 
    718 static Move<VkDescriptorSet> allocateSingleDescriptorSet (const DeviceInterface& vkd, VkDevice device, VkDescriptorPool pool, VkDescriptorSetLayout layout)
    719 {
    720 	const VkDescriptorSetAllocateInfo	allocInfo	=
    721 	{
    722 		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
    723 		DE_NULL,
    724 		pool,
    725 		1u,
    726 		&layout,
    727 	};
    728 	return allocateDescriptorSet(vkd, device, &allocInfo);
    729 }
    730 
    731 void FragmentOutExecutor::execute (int numValues, const void* const* inputs, void* const* outputs, VkDescriptorSet extraResources)
    732 {
    733 	const VkDevice										vkDevice				= m_context.getDevice();
    734 	const DeviceInterface&								vk						= m_context.getDeviceInterface();
    735 	const VkQueue										queue					= m_context.getUniversalQueue();
    736 	const deUint32										queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
    737 	Allocator&											memAlloc				= m_context.getDefaultAllocator();
    738 
    739 	const deUint32										renderSizeX				= de::min(static_cast<deUint32>(DEFAULT_RENDER_WIDTH), (deUint32)numValues);
    740 	const deUint32										renderSizeY				= ((deUint32)numValues / renderSizeX) + (((deUint32)numValues % renderSizeX != 0) ? 1u : 0u);
    741 	const tcu::UVec2									renderSize				(renderSizeX, renderSizeY);
    742 	std::vector<tcu::Vec2>								positions;
    743 
    744 	const bool											useGeometryShader		= m_shaderType == glu::SHADERTYPE_GEOMETRY;
    745 
    746 	std::vector<VkImageSp>								colorImages;
    747 	std::vector<VkImageMemoryBarrier>					colorImagePreRenderBarriers;
    748 	std::vector<VkImageMemoryBarrier>					colorImagePostRenderBarriers;
    749 	std::vector<AllocationSp>							colorImageAllocs;
    750 	std::vector<VkAttachmentDescription>				attachments;
    751 	std::vector<VkClearValue>							attachmentClearValues;
    752 	std::vector<VkImageViewSp>							colorImageViews;
    753 
    754 	std::vector<VkPipelineColorBlendAttachmentState>	colorBlendAttachmentStates;
    755 	std::vector<VkAttachmentReference>					colorAttachmentReferences;
    756 
    757 	Move<VkRenderPass>									renderPass;
    758 	Move<VkFramebuffer>									framebuffer;
    759 	Move<VkPipelineLayout>								pipelineLayout;
    760 	Move<VkPipeline>									graphicsPipeline;
    761 
    762 	Move<VkShaderModule>								vertexShaderModule;
    763 	Move<VkShaderModule>								geometryShaderModule;
    764 	Move<VkShaderModule>								fragmentShaderModule;
    765 
    766 	Move<VkCommandPool>									cmdPool;
    767 	Move<VkCommandBuffer>								cmdBuffer;
    768 
    769 	Move<VkFence>										fence;
    770 
    771 	Unique<VkDescriptorSetLayout>						emptyDescriptorSetLayout	(createEmptyDescriptorSetLayout(vk, vkDevice));
    772 	Unique<VkDescriptorPool>							dummyDescriptorPool			(createDummyDescriptorPool(vk, vkDevice));
    773 	Unique<VkDescriptorSet>								emptyDescriptorSet			(allocateSingleDescriptorSet(vk, vkDevice, *dummyDescriptorPool, *emptyDescriptorSetLayout));
    774 
    775 	clearRenderData();
    776 
    777 	// Compute positions - 1px points are used to drive fragment shading.
    778 	positions = computeVertexPositions(numValues, renderSize.cast<int>());
    779 
    780 	// Bind attributes
    781 	addAttribute(0u, VK_FORMAT_R32G32_SFLOAT, sizeof(tcu::Vec2), (deUint32)positions.size(), &positions[0]);
    782 	bindAttributes(numValues, inputs);
    783 
    784 	// Create color images
    785 	{
    786 		const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
    787 		{
    788 			VK_FALSE,																	// VkBool32						blendEnable;
    789 			VK_BLEND_FACTOR_ONE,														// VkBlendFactor				srcColorBlendFactor;
    790 			VK_BLEND_FACTOR_ZERO,														// VkBlendFactor				dstColorBlendFactor;
    791 			VK_BLEND_OP_ADD,															// VkBlendOp					blendOpColor;
    792 			VK_BLEND_FACTOR_ONE,														// VkBlendFactor				srcAlphaBlendFactor;
    793 			VK_BLEND_FACTOR_ZERO,														// VkBlendFactor				destAlphaBlendFactor;
    794 			VK_BLEND_OP_ADD,															// VkBlendOp					blendOpAlpha;
    795 			(VK_COLOR_COMPONENT_R_BIT |
    796 			 VK_COLOR_COMPONENT_G_BIT |
    797 			 VK_COLOR_COMPONENT_B_BIT |
    798 			 VK_COLOR_COMPONENT_A_BIT)													// VkColorComponentFlags		colorWriteMask;
    799 		};
    800 
    801 		for (int outNdx = 0; outNdx < (int)m_outputLayout.locationSymbols.size(); ++outNdx)
    802 		{
    803 			const bool		isFloat		= isDataTypeFloatOrVec(m_shaderSpec.outputs[outNdx].varType.getBasicType());
    804 			const bool		isSigned	= isDataTypeIntOrIVec (m_shaderSpec.outputs[outNdx].varType.getBasicType());
    805 			const bool		isBool		= isDataTypeBoolOrBVec(m_shaderSpec.outputs[outNdx].varType.getBasicType());
    806 			const VkFormat	colorFormat = isFloat ? VK_FORMAT_R32G32B32A32_SFLOAT : (isSigned || isBool ? VK_FORMAT_R32G32B32A32_SINT : VK_FORMAT_R32G32B32A32_UINT);
    807 
    808 			const VkImageCreateInfo	 colorImageParams =
    809 			{
    810 				VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType				sType;
    811 				DE_NULL,																	// const void*					pNext;
    812 				0u,																			// VkImageCreateFlags			flags;
    813 				VK_IMAGE_TYPE_2D,															// VkImageType					imageType;
    814 				colorFormat,																// VkFormat						format;
    815 				{ renderSize.x(), renderSize.y(), 1u },										// VkExtent3D					extent;
    816 				1u,																			// deUint32						mipLevels;
    817 				1u,																			// deUint32						arraySize;
    818 				VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits		samples;
    819 				VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling				tiling;
    820 				VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags			usage;
    821 				VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode				sharingMode;
    822 				1u,																			// deUint32						queueFamilyCount;
    823 				&queueFamilyIndex,															// const deUint32*				pQueueFamilyIndices;
    824 				VK_IMAGE_LAYOUT_UNDEFINED,													// VkImageLayout				initialLayout;
    825 			};
    826 
    827 			const VkAttachmentDescription colorAttachmentDescription =
    828 			{
    829 				0u,																			// VkAttachmentDescriptorFlags	flags;
    830 				colorFormat,																// VkFormat						format;
    831 				VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits		samples;
    832 				VK_ATTACHMENT_LOAD_OP_CLEAR,												// VkAttachmentLoadOp			loadOp;
    833 				VK_ATTACHMENT_STORE_OP_STORE,												// VkAttachmentStoreOp			storeOp;
    834 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,											// VkAttachmentLoadOp			stencilLoadOp;
    835 				VK_ATTACHMENT_STORE_OP_DONT_CARE,											// VkAttachmentStoreOp			stencilStoreOp;
    836 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,									// VkImageLayout				initialLayout;
    837 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,									// VkImageLayout				finalLayout;
    838 			};
    839 
    840 			Move<VkImage> colorImage = createImage(vk, vkDevice, &colorImageParams);
    841 			colorImages.push_back(de::SharedPtr<Unique<VkImage> >(new Unique<VkImage>(colorImage)));
    842 			attachmentClearValues.push_back(getDefaultClearColor());
    843 
    844 			// Allocate and bind color image memory
    845 			{
    846 				de::MovePtr<Allocation> colorImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *((const VkImage*) colorImages.back().get())), MemoryRequirement::Any);
    847 				VK_CHECK(vk.bindImageMemory(vkDevice, colorImages.back().get()->get(), colorImageAlloc->getMemory(), colorImageAlloc->getOffset()));
    848 				colorImageAllocs.push_back(de::SharedPtr<Allocation>(colorImageAlloc.release()));
    849 
    850 				attachments.push_back(colorAttachmentDescription);
    851 				colorBlendAttachmentStates.push_back(colorBlendAttachmentState);
    852 
    853 				const VkAttachmentReference colorAttachmentReference =
    854 				{
    855 					(deUint32) (colorImages.size() - 1),			//	deUint32		attachment;
    856 					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL		//	VkImageLayout	layout;
    857 				};
    858 
    859 				colorAttachmentReferences.push_back(colorAttachmentReference);
    860 			}
    861 
    862 			// Create color attachment view
    863 			{
    864 				const VkImageViewCreateInfo colorImageViewParams =
    865 				{
    866 					VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
    867 					DE_NULL,											// const void*				pNext;
    868 					0u,													// VkImageViewCreateFlags	flags;
    869 					colorImages.back().get()->get(),					// VkImage					image;
    870 					VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
    871 					colorFormat,										// VkFormat					format;
    872 					{
    873 						VK_COMPONENT_SWIZZLE_R,							// VkComponentSwizzle		r;
    874 						VK_COMPONENT_SWIZZLE_G,							// VkComponentSwizzle		g;
    875 						VK_COMPONENT_SWIZZLE_B,							// VkComponentSwizzle		b;
    876 						VK_COMPONENT_SWIZZLE_A							// VkComponentSwizzle		a;
    877 					},													// VkComponentMapping		components;
    878 					{
    879 						VK_IMAGE_ASPECT_COLOR_BIT,						// VkImageAspectFlags		aspectMask;
    880 						0u,												// deUint32					baseMipLevel;
    881 						1u,												// deUint32					mipLevels;
    882 						0u,												// deUint32					baseArraySlice;
    883 						1u												// deUint32					arraySize;
    884 					}													// VkImageSubresourceRange	subresourceRange;
    885 				};
    886 
    887 				Move<VkImageView> colorImageView = createImageView(vk, vkDevice, &colorImageViewParams);
    888 				colorImageViews.push_back(de::SharedPtr<Unique<VkImageView> >(new Unique<VkImageView>(colorImageView)));
    889 
    890 				const VkImageMemoryBarrier	colorImagePreRenderBarrier =
    891 				{
    892 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,					// sType
    893 					DE_NULL,												// pNext
    894 					0u,														// srcAccessMask
    895 					(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
    896 					VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),					// dstAccessMask
    897 					VK_IMAGE_LAYOUT_UNDEFINED,								// oldLayout
    898 					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,				// newLayout
    899 					VK_QUEUE_FAMILY_IGNORED,								// srcQueueFamilyIndex
    900 					VK_QUEUE_FAMILY_IGNORED,								// dstQueueFamilyIndex
    901 					colorImages.back().get()->get(),						// image
    902 					{
    903 						VK_IMAGE_ASPECT_COLOR_BIT,								// aspectMask
    904 						0u,														// baseMipLevel
    905 						1u,														// levelCount
    906 						0u,														// baseArrayLayer
    907 						1u,														// layerCount
    908 					}														// subresourceRange
    909 				};
    910 				colorImagePreRenderBarriers.push_back(colorImagePreRenderBarrier);
    911 
    912 				const VkImageMemoryBarrier	colorImagePostRenderBarrier =
    913 				{
    914 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,					// sType
    915 					DE_NULL,												// pNext
    916 					(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
    917 					VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),					// srcAccessMask
    918 					VK_ACCESS_TRANSFER_READ_BIT,							// dstAccessMask
    919 					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,				// oldLayout
    920 					VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,					// newLayout
    921 					VK_QUEUE_FAMILY_IGNORED,								// srcQueueFamilyIndex
    922 					VK_QUEUE_FAMILY_IGNORED,								// dstQueueFamilyIndex
    923 					colorImages.back().get()->get(),						// image
    924 					{
    925 						VK_IMAGE_ASPECT_COLOR_BIT,								// aspectMask
    926 						0u,														// baseMipLevel
    927 						1u,														// levelCount
    928 						0u,														// baseArrayLayer
    929 						1u,														// layerCount
    930 					}														// subresourceRange
    931 				};
    932 				colorImagePostRenderBarriers.push_back(colorImagePostRenderBarrier);
    933 			}
    934 		}
    935 	}
    936 
    937 	// Create render pass
    938 	{
    939 		const VkSubpassDescription subpassDescription =
    940 		{
    941 			0u,													// VkSubpassDescriptionFlags	flags;
    942 			VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint			pipelineBindPoint;
    943 			0u,													// deUint32						inputCount;
    944 			DE_NULL,											// const VkAttachmentReference*	pInputAttachments;
    945 			(deUint32)colorImages.size(),						// deUint32						colorCount;
    946 			&colorAttachmentReferences[0],						// const VkAttachmentReference*	colorAttachments;
    947 			DE_NULL,											// const VkAttachmentReference*	resolveAttachments;
    948 			DE_NULL,											// VkAttachmentReference		depthStencilAttachment;
    949 			0u,													// deUint32						preserveCount;
    950 			DE_NULL												// const VkAttachmentReference*	pPreserveAttachments;
    951 		};
    952 
    953 		const VkRenderPassCreateInfo renderPassParams =
    954 		{
    955 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
    956 			DE_NULL,											// const void*						pNext;
    957 			(VkRenderPassCreateFlags)0,							// VkRenderPassCreateFlags			flags;
    958 			(deUint32)attachments.size(),						// deUint32							attachmentCount;
    959 			&attachments[0],									// const VkAttachmentDescription*	pAttachments;
    960 			1u,													// deUint32							subpassCount;
    961 			&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
    962 			0u,													// deUint32							dependencyCount;
    963 			DE_NULL												// const VkSubpassDependency*		pDependencies;
    964 		};
    965 
    966 		renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
    967 	}
    968 
    969 	// Create framebuffer
    970 	{
    971 		std::vector<VkImageView> views(colorImageViews.size());
    972 		for (size_t i = 0; i < colorImageViews.size(); i++)
    973 		{
    974 			views[i] = colorImageViews[i].get()->get();
    975 		}
    976 
    977 		const VkFramebufferCreateInfo framebufferParams =
    978 		{
    979 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType				sType;
    980 			DE_NULL,											// const void*					pNext;
    981 			0u,													// VkFramebufferCreateFlags		flags;
    982 			*renderPass,										// VkRenderPass					renderPass;
    983 			(deUint32)views.size(),								// deUint32						attachmentCount;
    984 			&views[0],											// const VkImageView*			pAttachments;
    985 			(deUint32)renderSize.x(),							// deUint32						width;
    986 			(deUint32)renderSize.y(),							// deUint32						height;
    987 			1u													// deUint32						layers;
    988 		};
    989 
    990 		framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
    991 	}
    992 
    993 	// Create pipeline layout
    994 	{
    995 		const VkDescriptorSetLayout			setLayouts[]			=
    996 		{
    997 			*emptyDescriptorSetLayout,
    998 			m_extraResourcesLayout
    999 		};
   1000 		const VkPipelineLayoutCreateInfo	pipelineLayoutParams	=
   1001 		{
   1002 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
   1003 			DE_NULL,											// const void*					pNext;
   1004 			(VkPipelineLayoutCreateFlags)0,						// VkPipelineLayoutCreateFlags	flags;
   1005 			(m_extraResourcesLayout != 0 ? 2u : 0u),			// deUint32						descriptorSetCount;
   1006 			setLayouts,											// const VkDescriptorSetLayout*	pSetLayouts;
   1007 			0u,													// deUint32						pushConstantRangeCount;
   1008 			DE_NULL												// const VkPushConstantRange*	pPushConstantRanges;
   1009 		};
   1010 
   1011 		pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
   1012 	}
   1013 
   1014 	// Create shaders
   1015 	{
   1016 		vertexShaderModule		= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("vert"), 0);
   1017 		fragmentShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("frag"), 0);
   1018 
   1019 		if (useGeometryShader)
   1020 		{
   1021 			geometryShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("geom"), 0);
   1022 		}
   1023 	}
   1024 
   1025 	// Create pipeline
   1026 	{
   1027 		std::vector<VkPipelineShaderStageCreateInfo> shaderStageParams;
   1028 
   1029 		const VkPipelineShaderStageCreateInfo vertexShaderStageParams =
   1030 		{
   1031 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
   1032 			DE_NULL,													// const void*							pNext;
   1033 			(VkPipelineShaderStageCreateFlags)0,						// VkPipelineShaderStageCreateFlags		flags;
   1034 			VK_SHADER_STAGE_VERTEX_BIT,									// VkShaderStageFlagBits				stage;
   1035 			*vertexShaderModule,										// VkShaderModule						module;
   1036 			"main",														// const char*							pName;
   1037 			DE_NULL														// const VkSpecializationInfo*			pSpecializationInfo;
   1038 		};
   1039 
   1040 		const VkPipelineShaderStageCreateInfo fragmentShaderStageParams =
   1041 		{
   1042 			VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
   1043 			DE_NULL,													// const void*							pNext;
   1044 			(VkPipelineShaderStageCreateFlags)0,						// VkPipelineShaderStageCreateFlags		flags;
   1045 			VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStageFlagBits				stage;
   1046 			*fragmentShaderModule,										// VkShaderModule						module;
   1047 			"main",														// const char*							pName;
   1048 			DE_NULL														// const VkSpecializationInfo*			pSpecializationInfo;
   1049 		};
   1050 
   1051 		shaderStageParams.push_back(vertexShaderStageParams);
   1052 		shaderStageParams.push_back(fragmentShaderStageParams);
   1053 
   1054 		if (useGeometryShader)
   1055 		{
   1056 			const VkPipelineShaderStageCreateInfo geometryShaderStageParams =
   1057 			{
   1058 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
   1059 				DE_NULL,													// const void*							pNext;
   1060 				(VkPipelineShaderStageCreateFlags)0,						// VkPipelineShaderStageCreateFlags		flags;
   1061 				VK_SHADER_STAGE_GEOMETRY_BIT,								// VkShaderStageFlagBits				stage;
   1062 				*geometryShaderModule,										// VkShaderModule						module;
   1063 				"main",														// VkShader								shader;
   1064 				DE_NULL														// const VkSpecializationInfo*			pSpecializationInfo;
   1065 			};
   1066 
   1067 			shaderStageParams.push_back(geometryShaderStageParams);
   1068 		}
   1069 
   1070 		const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
   1071 		{
   1072 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType								sType;
   1073 			DE_NULL,													// const void*									pNext;
   1074 			(VkPipelineVertexInputStateCreateFlags)0,					// VkPipelineVertexInputStateCreateFlags		flags;
   1075 			(deUint32)m_vertexBindingDescriptions.size(),				// deUint32										bindingCount;
   1076 			&m_vertexBindingDescriptions[0],							// const VkVertexInputBindingDescription*		pVertexBindingDescriptions;
   1077 			(deUint32)m_vertexAttributeDescriptions.size(),				// deUint32										attributeCount;
   1078 			&m_vertexAttributeDescriptions[0],							// const VkVertexInputAttributeDescription*		pvertexAttributeDescriptions;
   1079 		};
   1080 
   1081 		const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
   1082 		{
   1083 			VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType							sType;
   1084 			DE_NULL,														// const void*								pNext;
   1085 			(VkPipelineInputAssemblyStateCreateFlags)0,						// VkPipelineInputAssemblyStateCreateFlags	flags;
   1086 			VK_PRIMITIVE_TOPOLOGY_POINT_LIST,								// VkPrimitiveTopology						topology;
   1087 			DE_FALSE														// VkBool32									primitiveRestartEnable;
   1088 		};
   1089 
   1090 		const VkViewport viewport =
   1091 		{
   1092 			0.0f,						// float	originX;
   1093 			0.0f,						// float	originY;
   1094 			(float)renderSize.x(),		// float	width;
   1095 			(float)renderSize.y(),		// float	height;
   1096 			0.0f,						// float	minDepth;
   1097 			1.0f						// float	maxDepth;
   1098 		};
   1099 
   1100 		const VkRect2D scissor =
   1101 		{
   1102 			{
   1103 				0u,						// deUint32	x;
   1104 				0u,						// deUint32	y;
   1105 			},							// VkOffset2D	offset;
   1106 			{
   1107 				renderSize.x(),			// deUint32	width;
   1108 				renderSize.y(),			// deUint32	height;
   1109 			},							// VkExtent2D	extent;
   1110 		};
   1111 
   1112 		const VkPipelineViewportStateCreateInfo viewportStateParams =
   1113 		{
   1114 			VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,	// VkStructureType										sType;
   1115 			DE_NULL,												// const void*											pNext;
   1116 			0u,														// VkPipelineViewportStateCreateFlags					flags;
   1117 			1u,														// deUint32												viewportCount;
   1118 			&viewport,												// const VkViewport*									pViewports;
   1119 			1u,														// deUint32												scissorsCount;
   1120 			&scissor												// const VkRect2D*										pScissors;
   1121 		};
   1122 
   1123 		const VkPipelineRasterizationStateCreateInfo rasterStateParams =
   1124 		{
   1125 			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType								sType;
   1126 			DE_NULL,														// const void*									pNext;
   1127 			(VkPipelineRasterizationStateCreateFlags)0u,					//VkPipelineRasterizationStateCreateFlags		flags;
   1128 			VK_FALSE,														// VkBool32										depthClipEnable;
   1129 			VK_FALSE,														// VkBool32										rasterizerDiscardEnable;
   1130 			VK_POLYGON_MODE_FILL,											// VkPolygonMode								polygonMode;
   1131 			VK_CULL_MODE_NONE,												// VkCullModeFlags								cullMode;
   1132 			VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace									frontFace;
   1133 			VK_FALSE,														// VkBool32										depthBiasEnable;
   1134 			0.0f,															// float										depthBias;
   1135 			0.0f,															// float										depthBiasClamp;
   1136 			0.0f,															// float										slopeScaledDepthBias;
   1137 			1.0f															// float										lineWidth;
   1138 		};
   1139 
   1140 		const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
   1141 		{
   1142 			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,		// VkStructureType							sType;
   1143 			DE_NULL,														// const void*								pNext;
   1144 			0u,																// VkPipelineMultisampleStateCreateFlags	flags;
   1145 			VK_SAMPLE_COUNT_1_BIT,											// VkSampleCountFlagBits					rasterizationSamples;
   1146 			VK_FALSE,														// VkBool32									sampleShadingEnable;
   1147 			0.0f,															// float									minSampleShading;
   1148 			DE_NULL,														// const VkSampleMask*						pSampleMask;
   1149 			VK_FALSE,														// VkBool32									alphaToCoverageEnable;
   1150 			VK_FALSE														// VkBool32									alphaToOneEnable;
   1151 		};
   1152 
   1153 		const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
   1154 		{
   1155 			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,		// VkStructureType								sType;
   1156 			DE_NULL,														// const void*									pNext;
   1157 			(VkPipelineColorBlendStateCreateFlags)0,						// VkPipelineColorBlendStateCreateFlags			flags;
   1158 			VK_FALSE,														// VkBool32										logicOpEnable;
   1159 			VK_LOGIC_OP_COPY,												// VkLogicOp									logicOp;
   1160 			(deUint32)colorBlendAttachmentStates.size(),					// deUint32										attachmentCount;
   1161 			&colorBlendAttachmentStates[0],									// const VkPipelineColorBlendAttachmentState*	pAttachments;
   1162 			{ 0.0f, 0.0f, 0.0f, 0.0f }										// float										blendConst[4];
   1163 		};
   1164 
   1165 		const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
   1166 		{
   1167 			VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
   1168 			DE_NULL,											// const void*										pNext;
   1169 			(VkPipelineCreateFlags)0,							// VkPipelineCreateFlags							flags;
   1170 			(deUint32)shaderStageParams.size(),					// deUint32											stageCount;
   1171 			&shaderStageParams[0],								// const VkPipelineShaderStageCreateInfo*			pStages;
   1172 			&vertexInputStateParams,							// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
   1173 			&inputAssemblyStateParams,							// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
   1174 			DE_NULL,											// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
   1175 			&viewportStateParams,								// const VkPipelineViewportStateCreateInfo*			pViewportState;
   1176 			&rasterStateParams,									// const VkPipelineRasterStateCreateInfo*			pRasterState;
   1177 			&multisampleStateParams,							// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
   1178 			DE_NULL,											// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
   1179 			&colorBlendStateParams,								// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
   1180 			(const VkPipelineDynamicStateCreateInfo*)DE_NULL,	// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
   1181 			*pipelineLayout,									// VkPipelineLayout									layout;
   1182 			*renderPass,										// VkRenderPass										renderPass;
   1183 			0u,													// deUint32											subpass;
   1184 			0u,													// VkPipeline										basePipelineHandle;
   1185 			0u													// deInt32											basePipelineIndex;
   1186 		};
   1187 
   1188 		graphicsPipeline = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
   1189 	}
   1190 
   1191 	// Create command pool
   1192 	cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
   1193 
   1194 	// Create command buffer
   1195 	{
   1196 		const VkCommandBufferBeginInfo cmdBufferBeginInfo =
   1197 		{
   1198 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType				sType;
   1199 			DE_NULL,										// const void*					pNext;
   1200 			0u,												// VkCmdBufferOptimizeFlags		flags;
   1201 			(const VkCommandBufferInheritanceInfo*)DE_NULL,
   1202 		};
   1203 
   1204 		const VkRenderPassBeginInfo renderPassBeginInfo =
   1205 		{
   1206 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,				// VkStructureType		sType;
   1207 			DE_NULL,												// const void*			pNext;
   1208 			*renderPass,											// VkRenderPass			renderPass;
   1209 			*framebuffer,											// VkFramebuffer		framebuffer;
   1210 			{ { 0, 0 }, { renderSize.x(), renderSize.y() } },		// VkRect2D				renderArea;
   1211 			(deUint32)attachmentClearValues.size(),					// deUint32				attachmentCount;
   1212 			&attachmentClearValues[0]								// const VkClearValue*	pAttachmentClearValues;
   1213 		};
   1214 
   1215 		cmdBuffer = allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
   1216 
   1217 		VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
   1218 
   1219 		vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (VkDependencyFlags)0,
   1220 							  0, (const VkMemoryBarrier*)DE_NULL,
   1221 							  0, (const VkBufferMemoryBarrier*)DE_NULL,
   1222 							  (deUint32)colorImagePreRenderBarriers.size(), colorImagePreRenderBarriers.empty() ? DE_NULL : &colorImagePreRenderBarriers[0]);
   1223 		vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
   1224 
   1225 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
   1226 
   1227 		if (m_extraResourcesLayout != 0)
   1228 		{
   1229 			DE_ASSERT(extraResources != 0);
   1230 			const VkDescriptorSet	descriptorSets[]	= { *emptyDescriptorSet, extraResources };
   1231 			vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, DE_LENGTH_OF_ARRAY(descriptorSets), descriptorSets, 0u, DE_NULL);
   1232 		}
   1233 		else
   1234 			DE_ASSERT(extraResources == 0);
   1235 
   1236 		const deUint32 numberOfVertexAttributes = (deUint32)m_vertexBuffers.size();
   1237 
   1238 		std::vector<VkDeviceSize> offsets(numberOfVertexAttributes, 0);
   1239 
   1240 		std::vector<VkBuffer> buffers(numberOfVertexAttributes);
   1241 		for (size_t i = 0; i < numberOfVertexAttributes; i++)
   1242 		{
   1243 			buffers[i] = m_vertexBuffers[i].get()->get();
   1244 		}
   1245 
   1246 		vk.cmdBindVertexBuffers(*cmdBuffer, 0, numberOfVertexAttributes, &buffers[0], &offsets[0]);
   1247 		vk.cmdDraw(*cmdBuffer, (deUint32)positions.size(), 1u, 0u, 0u);
   1248 
   1249 		vk.cmdEndRenderPass(*cmdBuffer);
   1250 		vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (VkDependencyFlags)0,
   1251 							  0, (const VkMemoryBarrier*)DE_NULL,
   1252 							  0, (const VkBufferMemoryBarrier*)DE_NULL,
   1253 							  (deUint32)colorImagePostRenderBarriers.size(), colorImagePostRenderBarriers.empty() ? DE_NULL : &colorImagePostRenderBarriers[0]);
   1254 
   1255 		VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
   1256 	}
   1257 
   1258 	// Create fence
   1259 	fence = createFence(vk, vkDevice);
   1260 
   1261 	// Execute Draw
   1262 	{
   1263 
   1264 		const VkSubmitInfo submitInfo =
   1265 		{
   1266 			VK_STRUCTURE_TYPE_SUBMIT_INFO,			// sType
   1267 			DE_NULL,								// pNext
   1268 			0u,										// waitSemaphoreCount
   1269 			DE_NULL,								// pWaitSemaphores
   1270 			(const VkPipelineStageFlags*)DE_NULL,
   1271 			1u,										// commandBufferCount
   1272 			&cmdBuffer.get(),						// pCommandBuffers
   1273 			0u,										// signalSemaphoreCount
   1274 			DE_NULL									// pSignalSemaphores
   1275 		};
   1276 
   1277 		VK_CHECK(vk.resetFences(vkDevice, 1, &fence.get()));
   1278 		VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
   1279 		VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), DE_TRUE, ~(0ull) /* infinity*/));
   1280 	}
   1281 
   1282 	// Read back result and output
   1283 	{
   1284 		const VkDeviceSize imageSizeBytes = (VkDeviceSize)(4 * sizeof(deUint32) * renderSize.x() * renderSize.y());
   1285 		const VkBufferCreateInfo readImageBufferParams =
   1286 		{
   1287 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
   1288 			DE_NULL,									// const void*			pNext;
   1289 			0u,											// VkBufferCreateFlags	flags;
   1290 			imageSizeBytes,								// VkDeviceSize			size;
   1291 			VK_BUFFER_USAGE_TRANSFER_DST_BIT,			// VkBufferUsageFlags	usage;
   1292 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
   1293 			1u,											// deUint32				queueFamilyCount;
   1294 			&queueFamilyIndex,							// const deUint32*		pQueueFamilyIndices;
   1295 		};
   1296 
   1297 		// constants for image copy
   1298 		Move<VkCommandPool>	copyCmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
   1299 
   1300 		const VkCommandBufferBeginInfo cmdBufferBeginInfo =
   1301 		{
   1302 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType					sType;
   1303 			DE_NULL,										// const void*						pNext;
   1304 			0u,												// VkCmdBufferOptimizeFlags			flags;
   1305 			(const VkCommandBufferInheritanceInfo*)DE_NULL,
   1306 		};
   1307 
   1308 		const VkBufferImageCopy copyParams =
   1309 		{
   1310 			0u,											// VkDeviceSize			bufferOffset;
   1311 			(deUint32)renderSize.x(),					// deUint32				bufferRowLength;
   1312 			(deUint32)renderSize.y(),					// deUint32				bufferImageHeight;
   1313 			{
   1314 				VK_IMAGE_ASPECT_COLOR_BIT,				// VkImageAspect		aspect;
   1315 				0u,										// deUint32				mipLevel;
   1316 				0u,										// deUint32				arraySlice;
   1317 				1u,										// deUint32				arraySize;
   1318 			},											// VkImageSubresource	imageSubresource;
   1319 			{ 0u, 0u, 0u },								// VkOffset3D			imageOffset;
   1320 			{ renderSize.x(), renderSize.y(), 1u }		// VkExtent3D			imageExtent;
   1321 		};
   1322 
   1323 		// Read back pixels.
   1324 		for (int outNdx = 0; outNdx < (int)m_shaderSpec.outputs.size(); ++outNdx)
   1325 		{
   1326 			const Symbol&				output			= m_shaderSpec.outputs[outNdx];
   1327 			const int					outSize			= output.varType.getScalarSize();
   1328 			const int					outVecSize		= glu::getDataTypeNumComponents(output.varType.getBasicType());
   1329 			const int					outNumLocs		= glu::getDataTypeNumLocations(output.varType.getBasicType());
   1330 			deUint32*					dstPtrBase		= static_cast<deUint32*>(outputs[outNdx]);
   1331 			const int					outLocation		= de::lookup(m_outputLayout.locationMap, output.name);
   1332 
   1333 			for (int locNdx = 0; locNdx < outNumLocs; ++locNdx)
   1334 			{
   1335 				tcu::TextureLevel			tmpBuf;
   1336 				const tcu::TextureFormat	format = getRenderbufferFormatForOutput(output.varType, false);
   1337 				const tcu::TextureFormat	readFormat (tcu::TextureFormat::RGBA, format.type);
   1338 				const Unique<VkBuffer>		readImageBuffer(createBuffer(vk, vkDevice, &readImageBufferParams));
   1339 				const de::UniquePtr<Allocation> readImageBufferMemory(memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *readImageBuffer), MemoryRequirement::HostVisible));
   1340 
   1341 				VK_CHECK(vk.bindBufferMemory(vkDevice, *readImageBuffer, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset()));
   1342 
   1343 				// Copy image to buffer
   1344 				{
   1345 
   1346 					Move<VkCommandBuffer> copyCmdBuffer = allocateCommandBuffer(vk, vkDevice, *copyCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
   1347 
   1348 					const VkSubmitInfo submitInfo =
   1349 					{
   1350 						VK_STRUCTURE_TYPE_SUBMIT_INFO,
   1351 						DE_NULL,
   1352 						0u,
   1353 						(const VkSemaphore*)DE_NULL,
   1354 						(const VkPipelineStageFlags*)DE_NULL,
   1355 						1u,
   1356 						&copyCmdBuffer.get(),
   1357 						0u,
   1358 						(const VkSemaphore*)DE_NULL,
   1359 					};
   1360 
   1361 					VK_CHECK(vk.beginCommandBuffer(*copyCmdBuffer, &cmdBufferBeginInfo));
   1362 					vk.cmdCopyImageToBuffer(*copyCmdBuffer, colorImages[outLocation + locNdx].get()->get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *readImageBuffer, 1u, &copyParams);
   1363 					VK_CHECK(vk.endCommandBuffer(*copyCmdBuffer));
   1364 
   1365 					VK_CHECK(vk.resetFences(vkDevice, 1, &fence.get()));
   1366 					VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
   1367 					VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), true, ~(0ull) /* infinity */));
   1368 				}
   1369 
   1370 				const VkMappedMemoryRange range =
   1371 				{
   1372 					VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,	// VkStructureType	sType;
   1373 					DE_NULL,								// const void*		pNext;
   1374 					readImageBufferMemory->getMemory(),		// VkDeviceMemory	mem;
   1375 					0,										// VkDeviceSize		offset;
   1376 					imageSizeBytes,							// VkDeviceSize		size;
   1377 				};
   1378 
   1379 				VK_CHECK(vk.invalidateMappedMemoryRanges(vkDevice, 1u, &range));
   1380 
   1381 				tmpBuf.setStorage(readFormat, renderSize.x(), renderSize.y());
   1382 
   1383 				const tcu::TextureFormat resultFormat(tcu::TextureFormat::RGBA, format.type);
   1384 				const tcu::ConstPixelBufferAccess resultAccess(resultFormat, renderSize.x(), renderSize.y(), 1, readImageBufferMemory->getHostPtr());
   1385 
   1386 				tcu::copy(tmpBuf.getAccess(), resultAccess);
   1387 
   1388 				if (outSize == 4 && outNumLocs == 1)
   1389 					deMemcpy(dstPtrBase, tmpBuf.getAccess().getDataPtr(), numValues * outVecSize * sizeof(deUint32));
   1390 				else
   1391 				{
   1392 					for (int valNdx = 0; valNdx < numValues; valNdx++)
   1393 					{
   1394 						const deUint32* srcPtr = (const deUint32*)tmpBuf.getAccess().getDataPtr() + valNdx * 4;
   1395 						deUint32*		dstPtr = &dstPtrBase[outSize * valNdx + outVecSize * locNdx];
   1396 						deMemcpy(dstPtr, srcPtr, outVecSize * sizeof(deUint32));
   1397 					}
   1398 				}
   1399 			}
   1400 		}
   1401 	}
   1402 }
   1403 
   1404 // VertexShaderExecutor
   1405 
   1406 class VertexShaderExecutor : public FragmentOutExecutor
   1407 {
   1408 public:
   1409 								VertexShaderExecutor	(Context& context, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout);
   1410 	virtual						~VertexShaderExecutor	(void);
   1411 
   1412 	static void					generateSources			(const ShaderSpec& shaderSpec, SourceCollections& dst);
   1413 };
   1414 
   1415 VertexShaderExecutor::VertexShaderExecutor (Context& context, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout)
   1416 	: FragmentOutExecutor(context, glu::SHADERTYPE_VERTEX, shaderSpec, extraResourcesLayout)
   1417 {
   1418 }
   1419 
   1420 VertexShaderExecutor::~VertexShaderExecutor (void)
   1421 {
   1422 }
   1423 
   1424 void VertexShaderExecutor::generateSources (const ShaderSpec& shaderSpec, SourceCollections& programCollection)
   1425 {
   1426 	const FragmentOutputLayout	outputLayout	(computeFragmentOutputLayout(shaderSpec.outputs));
   1427 
   1428 	programCollection.glslSources.add("vert") << glu::VertexSource(generateVertexShader(shaderSpec, "a_", "vtx_out_")) << shaderSpec.buildOptions;
   1429 	/* \todo [2015-09-11 hegedusd] set useIntOutputs parameter if needed. */
   1430 	programCollection.glslSources.add("frag") << glu::FragmentSource(generatePassthroughFragmentShader(shaderSpec, false, outputLayout.locationMap, "vtx_out_", "o_")) << shaderSpec.buildOptions;
   1431 }
   1432 
   1433 // GeometryShaderExecutor
   1434 
   1435 class GeometryShaderExecutor : public FragmentOutExecutor
   1436 {
   1437 public:
   1438 								GeometryShaderExecutor	(Context& context, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout);
   1439 	virtual						~GeometryShaderExecutor	(void);
   1440 
   1441 	static void					generateSources			(const ShaderSpec& shaderSpec, SourceCollections& programCollection);
   1442 
   1443 };
   1444 
   1445 GeometryShaderExecutor::GeometryShaderExecutor (Context& context, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout)
   1446 	: FragmentOutExecutor(context, glu::SHADERTYPE_GEOMETRY, shaderSpec, extraResourcesLayout)
   1447 {
   1448 	const VkPhysicalDeviceFeatures& features = context.getDeviceFeatures();
   1449 
   1450 	if (!features.geometryShader)
   1451 		TCU_THROW(NotSupportedError, "Geometry shader type not supported by device");
   1452 }
   1453 
   1454 GeometryShaderExecutor::~GeometryShaderExecutor (void)
   1455 {
   1456 }
   1457 
   1458 void GeometryShaderExecutor::generateSources (const ShaderSpec& shaderSpec, SourceCollections& programCollection)
   1459 {
   1460 	const FragmentOutputLayout	outputLayout	(computeFragmentOutputLayout(shaderSpec.outputs));
   1461 
   1462 	programCollection.glslSources.add("vert") << glu::VertexSource(generatePassthroughVertexShader(shaderSpec.inputs, "a_", "vtx_out_")) << shaderSpec.buildOptions;
   1463 
   1464 	programCollection.glslSources.add("geom") << glu::GeometrySource(generateGeometryShader(shaderSpec, "vtx_out_", "geom_out_")) << shaderSpec.buildOptions;
   1465 
   1466 	/* \todo [2015-09-18 rsipka] set useIntOutputs parameter if needed. */
   1467 	programCollection.glslSources.add("frag") << glu::FragmentSource(generatePassthroughFragmentShader(shaderSpec, false, outputLayout.locationMap, "geom_out_", "o_")) << shaderSpec.buildOptions;
   1468 
   1469 }
   1470 
   1471 // FragmentShaderExecutor
   1472 
   1473 class FragmentShaderExecutor : public FragmentOutExecutor
   1474 {
   1475 public:
   1476 								FragmentShaderExecutor	(Context& context, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout);
   1477 	virtual						~FragmentShaderExecutor (void);
   1478 
   1479 	static void					generateSources			(const ShaderSpec& shaderSpec, SourceCollections& programCollection);
   1480 
   1481 };
   1482 
   1483 FragmentShaderExecutor::FragmentShaderExecutor (Context& context, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout)
   1484 	: FragmentOutExecutor(context, glu::SHADERTYPE_FRAGMENT, shaderSpec, extraResourcesLayout)
   1485 {
   1486 }
   1487 
   1488 FragmentShaderExecutor::~FragmentShaderExecutor (void)
   1489 {
   1490 }
   1491 
   1492 void FragmentShaderExecutor::generateSources (const ShaderSpec& shaderSpec, SourceCollections& programCollection)
   1493 {
   1494 	const FragmentOutputLayout	outputLayout	(computeFragmentOutputLayout(shaderSpec.outputs));
   1495 
   1496 	programCollection.glslSources.add("vert") << glu::VertexSource(generatePassthroughVertexShader(shaderSpec.inputs, "a_", "vtx_out_")) << shaderSpec.buildOptions;
   1497 	/* \todo [2015-09-11 hegedusd] set useIntOutputs parameter if needed. */
   1498 	programCollection.glslSources.add("frag") << glu::FragmentSource(generateFragmentShader(shaderSpec, false, outputLayout.locationMap, "vtx_out_", "o_")) << shaderSpec.buildOptions;
   1499 }
   1500 
   1501 // Shared utilities for compute and tess executors
   1502 
   1503 static deUint32 getVecStd430ByteAlignment (glu::DataType type)
   1504 {
   1505 	switch (glu::getDataTypeScalarSize(type))
   1506 	{
   1507 		case 1:		return 4u;
   1508 		case 2:		return 8u;
   1509 		case 3:		return 16u;
   1510 		case 4:		return 16u;
   1511 		default:
   1512 			DE_ASSERT(false);
   1513 			return 0u;
   1514 	}
   1515 }
   1516 
   1517 class BufferIoExecutor : public ShaderExecutor
   1518 {
   1519 public:
   1520 							BufferIoExecutor	(Context& context, const ShaderSpec& shaderSpec);
   1521 	virtual					~BufferIoExecutor	(void);
   1522 
   1523 protected:
   1524 	enum
   1525 	{
   1526 		INPUT_BUFFER_BINDING	= 0,
   1527 		OUTPUT_BUFFER_BINDING	= 1,
   1528 	};
   1529 
   1530 	void					initBuffers			(int numValues);
   1531 	VkBuffer				getInputBuffer		(void) const		{ return *m_inputBuffer;					}
   1532 	VkBuffer				getOutputBuffer		(void) const		{ return *m_outputBuffer;					}
   1533 	deUint32				getInputStride		(void) const		{ return getLayoutStride(m_inputLayout);	}
   1534 	deUint32				getOutputStride		(void) const		{ return getLayoutStride(m_outputLayout);	}
   1535 
   1536 	void					uploadInputBuffer	(const void* const* inputPtrs, int numValues);
   1537 	void					readOutputBuffer	(void* const* outputPtrs, int numValues);
   1538 
   1539 	static void				declareBufferBlocks	(std::ostream& src, const ShaderSpec& spec);
   1540 	static void				generateExecBufferIo(std::ostream& src, const ShaderSpec& spec, const char* invocationNdxName);
   1541 
   1542 protected:
   1543 	Move<VkBuffer>			m_inputBuffer;
   1544 	Move<VkBuffer>			m_outputBuffer;
   1545 
   1546 private:
   1547 	struct VarLayout
   1548 	{
   1549 		deUint32		offset;
   1550 		deUint32		stride;
   1551 		deUint32		matrixStride;
   1552 
   1553 		VarLayout (void) : offset(0), stride(0), matrixStride(0) {}
   1554 	};
   1555 
   1556 	static void				computeVarLayout	(const std::vector<Symbol>& symbols, std::vector<VarLayout>* layout);
   1557 	static deUint32			getLayoutStride		(const vector<VarLayout>& layout);
   1558 
   1559 	static void				copyToBuffer		(const glu::VarType& varType, const VarLayout& layout, int numValues, const void* srcBasePtr, void* dstBasePtr);
   1560 	static void				copyFromBuffer		(const glu::VarType& varType, const VarLayout& layout, int numValues, const void* srcBasePtr, void* dstBasePtr);
   1561 
   1562 	de::MovePtr<Allocation>	m_inputAlloc;
   1563 	de::MovePtr<Allocation>	m_outputAlloc;
   1564 
   1565 	vector<VarLayout>		m_inputLayout;
   1566 	vector<VarLayout>		m_outputLayout;
   1567 };
   1568 
   1569 BufferIoExecutor::BufferIoExecutor (Context& context, const ShaderSpec& shaderSpec)
   1570 	: ShaderExecutor(context, shaderSpec)
   1571 {
   1572 	computeVarLayout(m_shaderSpec.inputs, &m_inputLayout);
   1573 	computeVarLayout(m_shaderSpec.outputs, &m_outputLayout);
   1574 }
   1575 
   1576 BufferIoExecutor::~BufferIoExecutor (void)
   1577 {
   1578 }
   1579 
   1580 inline deUint32 BufferIoExecutor::getLayoutStride (const vector<VarLayout>& layout)
   1581 {
   1582 	return layout.empty() ? 0 : layout[0].stride;
   1583 }
   1584 
   1585 void BufferIoExecutor::computeVarLayout (const std::vector<Symbol>& symbols, std::vector<VarLayout>* layout)
   1586 {
   1587 	deUint32	maxAlignment	= 0;
   1588 	deUint32	curOffset		= 0;
   1589 
   1590 	DE_ASSERT(layout != DE_NULL);
   1591 	DE_ASSERT(layout->empty());
   1592 	layout->resize(symbols.size());
   1593 
   1594 	for (size_t varNdx = 0; varNdx < symbols.size(); varNdx++)
   1595 	{
   1596 		const Symbol&		symbol		= symbols[varNdx];
   1597 		const glu::DataType	basicType	= symbol.varType.getBasicType();
   1598 		VarLayout&			layoutEntry	= (*layout)[varNdx];
   1599 
   1600 		if (glu::isDataTypeScalarOrVector(basicType))
   1601 		{
   1602 			const deUint32	alignment	= getVecStd430ByteAlignment(basicType);
   1603 			const deUint32	size		= (deUint32)glu::getDataTypeScalarSize(basicType) * (int)sizeof(deUint32);
   1604 
   1605 			curOffset		= (deUint32)deAlign32((int)curOffset, (int)alignment);
   1606 			maxAlignment	= de::max(maxAlignment, alignment);
   1607 
   1608 			layoutEntry.offset			= curOffset;
   1609 			layoutEntry.matrixStride	= 0;
   1610 
   1611 			curOffset += size;
   1612 		}
   1613 		else if (glu::isDataTypeMatrix(basicType))
   1614 		{
   1615 			const int				numVecs			= glu::getDataTypeMatrixNumColumns(basicType);
   1616 			const glu::DataType		vecType			= glu::getDataTypeFloatVec(glu::getDataTypeMatrixNumRows(basicType));
   1617 			const deUint32			vecAlignment	= getVecStd430ByteAlignment(vecType);
   1618 
   1619 			curOffset		= (deUint32)deAlign32((int)curOffset, (int)vecAlignment);
   1620 			maxAlignment	= de::max(maxAlignment, vecAlignment);
   1621 
   1622 			layoutEntry.offset			= curOffset;
   1623 			layoutEntry.matrixStride	= vecAlignment;
   1624 
   1625 			curOffset += vecAlignment*numVecs;
   1626 		}
   1627 		else
   1628 			DE_ASSERT(false);
   1629 	}
   1630 
   1631 	{
   1632 		const deUint32	totalSize	= (deUint32)deAlign32(curOffset, maxAlignment);
   1633 
   1634 		for (vector<VarLayout>::iterator varIter = layout->begin(); varIter != layout->end(); ++varIter)
   1635 			varIter->stride = totalSize;
   1636 	}
   1637 }
   1638 
   1639 void BufferIoExecutor::declareBufferBlocks (std::ostream& src, const ShaderSpec& spec)
   1640 {
   1641 	// Input struct
   1642 	if (!spec.inputs.empty())
   1643 	{
   1644 		glu::StructType inputStruct("Inputs");
   1645 		for (vector<Symbol>::const_iterator symIter = spec.inputs.begin(); symIter != spec.inputs.end(); ++symIter)
   1646 			inputStruct.addMember(symIter->name.c_str(), symIter->varType);
   1647 		src << glu::declare(&inputStruct) << ";\n";
   1648 	}
   1649 
   1650 	// Output struct
   1651 	{
   1652 		glu::StructType outputStruct("Outputs");
   1653 		for (vector<Symbol>::const_iterator symIter = spec.outputs.begin(); symIter != spec.outputs.end(); ++symIter)
   1654 			outputStruct.addMember(symIter->name.c_str(), symIter->varType);
   1655 		src << glu::declare(&outputStruct) << ";\n";
   1656 	}
   1657 
   1658 	src << "\n";
   1659 
   1660 	if (!spec.inputs.empty())
   1661 	{
   1662 		src	<< "layout(set = 0, binding = " << int(INPUT_BUFFER_BINDING) << ", std430) buffer InBuffer\n"
   1663 			<< "{\n"
   1664 			<< "	Inputs inputs[];\n"
   1665 			<< "};\n";
   1666 	}
   1667 
   1668 	src	<< "layout(set = 0, binding = " << int(OUTPUT_BUFFER_BINDING) << ", std430) buffer OutBuffer\n"
   1669 		<< "{\n"
   1670 		<< "	Outputs outputs[];\n"
   1671 		<< "};\n"
   1672 		<< "\n";
   1673 }
   1674 
   1675 void BufferIoExecutor::generateExecBufferIo (std::ostream& src, const ShaderSpec& spec, const char* invocationNdxName)
   1676 {
   1677 	for (vector<Symbol>::const_iterator symIter = spec.inputs.begin(); symIter != spec.inputs.end(); ++symIter)
   1678 		src << "\t" << glu::declare(symIter->varType, symIter->name) << " = inputs[" << invocationNdxName << "]." << symIter->name << ";\n";
   1679 
   1680 	for (vector<Symbol>::const_iterator symIter = spec.outputs.begin(); symIter != spec.outputs.end(); ++symIter)
   1681 		src << "\t" << glu::declare(symIter->varType, symIter->name) << ";\n";
   1682 
   1683 	src << "\n";
   1684 
   1685 	{
   1686 		std::istringstream	opSrc	(spec.source);
   1687 		std::string			line;
   1688 
   1689 		while (std::getline(opSrc, line))
   1690 			src << "\t" << line << "\n";
   1691 	}
   1692 
   1693 	src << "\n";
   1694 	for (vector<Symbol>::const_iterator symIter = spec.outputs.begin(); symIter != spec.outputs.end(); ++symIter)
   1695 		src << "\toutputs[" << invocationNdxName << "]." << symIter->name << " = " << symIter->name << ";\n";
   1696 }
   1697 
   1698 void BufferIoExecutor::copyToBuffer (const glu::VarType& varType, const VarLayout& layout, int numValues, const void* srcBasePtr, void* dstBasePtr)
   1699 {
   1700 	if (varType.isBasicType())
   1701 	{
   1702 		const glu::DataType		basicType		= varType.getBasicType();
   1703 		const bool				isMatrix		= glu::isDataTypeMatrix(basicType);
   1704 		const int				scalarSize		= glu::getDataTypeScalarSize(basicType);
   1705 		const int				numVecs			= isMatrix ? glu::getDataTypeMatrixNumColumns(basicType) : 1;
   1706 		const int				numComps		= scalarSize / numVecs;
   1707 
   1708 		for (int elemNdx = 0; elemNdx < numValues; elemNdx++)
   1709 		{
   1710 			for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
   1711 			{
   1712 				const int		srcOffset		= (int)sizeof(deUint32) * (elemNdx * scalarSize + vecNdx * numComps);
   1713 				const int		dstOffset		= layout.offset + layout.stride * elemNdx + (isMatrix ? layout.matrixStride * vecNdx : 0);
   1714 				const deUint8*	srcPtr			= (const deUint8*)srcBasePtr + srcOffset;
   1715 				deUint8*		dstPtr			= (deUint8*)dstBasePtr + dstOffset;
   1716 
   1717 				deMemcpy(dstPtr, srcPtr, sizeof(deUint32) * numComps);
   1718 			}
   1719 		}
   1720 	}
   1721 	else
   1722 		throw tcu::InternalError("Unsupported type");
   1723 }
   1724 
   1725 void BufferIoExecutor::copyFromBuffer (const glu::VarType& varType, const VarLayout& layout, int numValues, const void* srcBasePtr, void* dstBasePtr)
   1726 {
   1727 	if (varType.isBasicType())
   1728 	{
   1729 		const glu::DataType		basicType		= varType.getBasicType();
   1730 		const bool				isMatrix		= glu::isDataTypeMatrix(basicType);
   1731 		const int				scalarSize		= glu::getDataTypeScalarSize(basicType);
   1732 		const int				numVecs			= isMatrix ? glu::getDataTypeMatrixNumColumns(basicType) : 1;
   1733 		const int				numComps		= scalarSize / numVecs;
   1734 
   1735 		for (int elemNdx = 0; elemNdx < numValues; elemNdx++)
   1736 		{
   1737 			for (int vecNdx = 0; vecNdx < numVecs; vecNdx++)
   1738 			{
   1739 				const int		srcOffset		= layout.offset + layout.stride * elemNdx + (isMatrix ? layout.matrixStride * vecNdx : 0);
   1740 				const int		dstOffset		= (int)sizeof(deUint32) * (elemNdx * scalarSize + vecNdx * numComps);
   1741 				const deUint8*	srcPtr			= (const deUint8*)srcBasePtr + srcOffset;
   1742 				deUint8*		dstPtr			= (deUint8*)dstBasePtr + dstOffset;
   1743 
   1744 				deMemcpy(dstPtr, srcPtr, sizeof(deUint32) * numComps);
   1745 			}
   1746 		}
   1747 	}
   1748 	else
   1749 		throw tcu::InternalError("Unsupported type");
   1750 }
   1751 
   1752 void BufferIoExecutor::uploadInputBuffer (const void* const* inputPtrs, int numValues)
   1753 {
   1754 	const VkDevice			vkDevice			= m_context.getDevice();
   1755 	const DeviceInterface&	vk					= m_context.getDeviceInterface();
   1756 
   1757 	const deUint32			inputStride			= getLayoutStride(m_inputLayout);
   1758 	const int				inputBufferSize		= inputStride * numValues;
   1759 
   1760 	if (inputBufferSize == 0)
   1761 		return; // No inputs
   1762 
   1763 	DE_ASSERT(m_shaderSpec.inputs.size() == m_inputLayout.size());
   1764 	for (size_t inputNdx = 0; inputNdx < m_shaderSpec.inputs.size(); ++inputNdx)
   1765 	{
   1766 		const glu::VarType&		varType		= m_shaderSpec.inputs[inputNdx].varType;
   1767 		const VarLayout&		layout		= m_inputLayout[inputNdx];
   1768 
   1769 		copyToBuffer(varType, layout, numValues, inputPtrs[inputNdx], m_inputAlloc->getHostPtr());
   1770 	}
   1771 
   1772 	flushMappedMemoryRange(vk, vkDevice, m_inputAlloc->getMemory(), m_inputAlloc->getOffset(), inputBufferSize);
   1773 }
   1774 
   1775 void BufferIoExecutor::readOutputBuffer (void* const* outputPtrs, int numValues)
   1776 {
   1777 	const VkDevice			vkDevice			= m_context.getDevice();
   1778 	const DeviceInterface&	vk					= m_context.getDeviceInterface();
   1779 
   1780 	const deUint32			outputStride		= getLayoutStride(m_outputLayout);
   1781 	const int				outputBufferSize	= numValues * outputStride;
   1782 
   1783 	DE_ASSERT(outputBufferSize > 0); // At least some outputs are required.
   1784 
   1785 	invalidateMappedMemoryRange(vk, vkDevice, m_outputAlloc->getMemory(), m_outputAlloc->getOffset(), outputBufferSize);
   1786 
   1787 	DE_ASSERT(m_shaderSpec.outputs.size() == m_outputLayout.size());
   1788 	for (size_t outputNdx = 0; outputNdx < m_shaderSpec.outputs.size(); ++outputNdx)
   1789 	{
   1790 		const glu::VarType&		varType		= m_shaderSpec.outputs[outputNdx].varType;
   1791 		const VarLayout&		layout		= m_outputLayout[outputNdx];
   1792 
   1793 		copyFromBuffer(varType, layout, numValues, m_outputAlloc->getHostPtr(), outputPtrs[outputNdx]);
   1794 	}
   1795 }
   1796 
   1797 void BufferIoExecutor::initBuffers (int numValues)
   1798 {
   1799 	const deUint32				inputStride			= getLayoutStride(m_inputLayout);
   1800 	const deUint32				outputStride		= getLayoutStride(m_outputLayout);
   1801 	// Avoid creating zero-sized buffer/memory
   1802 	const size_t				inputBufferSize		= de::max(numValues * inputStride, 1u);
   1803 	const size_t				outputBufferSize	= numValues * outputStride;
   1804 
   1805 	// Upload data to buffer
   1806 	const VkDevice				vkDevice			= m_context.getDevice();
   1807 	const DeviceInterface&		vk					= m_context.getDeviceInterface();
   1808 	const deUint32				queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
   1809 	Allocator&					memAlloc			= m_context.getDefaultAllocator();
   1810 
   1811 	const VkBufferCreateInfo inputBufferParams =
   1812 	{
   1813 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
   1814 		DE_NULL,									// const void*			pNext;
   1815 		0u,											// VkBufferCreateFlags	flags;
   1816 		inputBufferSize,							// VkDeviceSize			size;
   1817 		VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,			// VkBufferUsageFlags	usage;
   1818 		VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
   1819 		1u,											// deUint32				queueFamilyCount;
   1820 		&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
   1821 	};
   1822 
   1823 	m_inputBuffer = createBuffer(vk, vkDevice, &inputBufferParams);
   1824 	m_inputAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_inputBuffer), MemoryRequirement::HostVisible);
   1825 
   1826 	VK_CHECK(vk.bindBufferMemory(vkDevice, *m_inputBuffer, m_inputAlloc->getMemory(), m_inputAlloc->getOffset()));
   1827 
   1828 	const VkBufferCreateInfo outputBufferParams =
   1829 	{
   1830 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
   1831 		DE_NULL,									// const void*			pNext;
   1832 		0u,											// VkBufferCreateFlags	flags;
   1833 		outputBufferSize,							// VkDeviceSize			size;
   1834 		VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,			// VkBufferUsageFlags	usage;
   1835 		VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
   1836 		1u,											// deUint32				queueFamilyCount;
   1837 		&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
   1838 	};
   1839 
   1840 	m_outputBuffer = createBuffer(vk, vkDevice, &outputBufferParams);
   1841 	m_outputAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_outputBuffer), MemoryRequirement::HostVisible);
   1842 
   1843 	VK_CHECK(vk.bindBufferMemory(vkDevice, *m_outputBuffer, m_outputAlloc->getMemory(), m_outputAlloc->getOffset()));
   1844 }
   1845 
   1846 // ComputeShaderExecutor
   1847 
   1848 class ComputeShaderExecutor : public BufferIoExecutor
   1849 {
   1850 public:
   1851 						ComputeShaderExecutor	(Context& context, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout);
   1852 	virtual				~ComputeShaderExecutor	(void);
   1853 
   1854 	static void			generateSources			(const ShaderSpec& shaderSpec, SourceCollections& programCollection);
   1855 
   1856 	virtual void		execute					(int numValues, const void* const* inputs, void* const* outputs, VkDescriptorSet extraResources);
   1857 
   1858 protected:
   1859 	static std::string	generateComputeShader	(const ShaderSpec& spec);
   1860 
   1861 private:
   1862 	const VkDescriptorSetLayout					m_extraResourcesLayout;
   1863 };
   1864 
   1865 ComputeShaderExecutor::ComputeShaderExecutor(Context& context, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout)
   1866 	: BufferIoExecutor			(context, shaderSpec)
   1867 	, m_extraResourcesLayout	(extraResourcesLayout)
   1868 {
   1869 }
   1870 
   1871 ComputeShaderExecutor::~ComputeShaderExecutor	(void)
   1872 {
   1873 }
   1874 
   1875 std::string ComputeShaderExecutor::generateComputeShader (const ShaderSpec& spec)
   1876 {
   1877 	std::ostringstream src;
   1878 	src << glu::getGLSLVersionDeclaration(spec.glslVersion) << "\n";
   1879 
   1880 	if (!spec.globalDeclarations.empty())
   1881 		src << spec.globalDeclarations << "\n";
   1882 
   1883 	src << "layout(local_size_x = 1) in;\n"
   1884 		<< "\n";
   1885 
   1886 	declareBufferBlocks(src, spec);
   1887 
   1888 	src << "void main (void)\n"
   1889 		<< "{\n"
   1890 		<< "	uint invocationNdx = gl_NumWorkGroups.x*gl_NumWorkGroups.y*gl_WorkGroupID.z\n"
   1891 		<< "	                   + gl_NumWorkGroups.x*gl_WorkGroupID.y + gl_WorkGroupID.x;\n";
   1892 
   1893 	generateExecBufferIo(src, spec, "invocationNdx");
   1894 
   1895 	src << "}\n";
   1896 
   1897 	return src.str();
   1898 }
   1899 
   1900 void ComputeShaderExecutor::generateSources (const ShaderSpec& shaderSpec, SourceCollections& programCollection)
   1901 {
   1902 	programCollection.glslSources.add("compute") << glu::ComputeSource(generateComputeShader(shaderSpec)) << shaderSpec.buildOptions;
   1903 }
   1904 
   1905 void ComputeShaderExecutor::execute (int numValues, const void* const* inputs, void* const* outputs, VkDescriptorSet extraResources)
   1906 {
   1907 	const VkDevice					vkDevice				= m_context.getDevice();
   1908 	const DeviceInterface&			vk						= m_context.getDeviceInterface();
   1909 	const VkQueue					queue					= m_context.getUniversalQueue();
   1910 	const deUint32					queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
   1911 
   1912 	DescriptorPoolBuilder			descriptorPoolBuilder;
   1913 	DescriptorSetLayoutBuilder		descriptorSetLayoutBuilder;
   1914 
   1915 	Move<VkShaderModule>			computeShaderModule;
   1916 	Move<VkPipeline>				computePipeline;
   1917 	Move<VkPipelineLayout>			pipelineLayout;
   1918 	Move<VkCommandPool>				cmdPool;
   1919 	Move<VkDescriptorPool>			descriptorPool;
   1920 	Move<VkDescriptorSetLayout>		descriptorSetLayout;
   1921 	Move<VkDescriptorSet>			descriptorSet;
   1922 	const deUint32					numDescriptorSets		= (m_extraResourcesLayout != 0) ? 2u : 1u;
   1923 	Move<VkFence>					fence;
   1924 
   1925 	DE_ASSERT((m_extraResourcesLayout != 0) == (extraResources != 0));
   1926 
   1927 	initBuffers(numValues);
   1928 
   1929 	// Setup input buffer & copy data
   1930 	uploadInputBuffer(inputs, numValues);
   1931 
   1932 	// Create command pool
   1933 	cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
   1934 
   1935 	// Create command buffer
   1936 	const VkCommandBufferBeginInfo cmdBufferBeginInfo =
   1937 	{
   1938 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType					sType;
   1939 		DE_NULL,										// const void*						pNext;
   1940 		0u,												// VkCmdBufferOptimizeFlags			flags;
   1941 		(const VkCommandBufferInheritanceInfo*)DE_NULL,
   1942 	};
   1943 
   1944 	descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT);
   1945 	descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
   1946 	descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT);
   1947 	descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
   1948 
   1949 	descriptorSetLayout = descriptorSetLayoutBuilder.build(vk, vkDevice);
   1950 	descriptorPool = descriptorPoolBuilder.build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
   1951 
   1952 	const VkDescriptorSetAllocateInfo allocInfo =
   1953 	{
   1954 		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
   1955 		DE_NULL,
   1956 		*descriptorPool,
   1957 		1u,
   1958 		&*descriptorSetLayout
   1959 	};
   1960 
   1961 	descriptorSet = allocateDescriptorSet(vk, vkDevice, &allocInfo);
   1962 
   1963 	// Create pipeline layout
   1964 	{
   1965 		const VkDescriptorSetLayout			descriptorSetLayouts[]	=
   1966 		{
   1967 			*descriptorSetLayout,
   1968 			m_extraResourcesLayout
   1969 		};
   1970 		const VkPipelineLayoutCreateInfo	pipelineLayoutParams	=
   1971 		{
   1972 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
   1973 			DE_NULL,											// const void*					pNext;
   1974 			(VkPipelineLayoutCreateFlags)0,						// VkPipelineLayoutCreateFlags	flags;
   1975 			numDescriptorSets,									// deUint32						CdescriptorSetCount;
   1976 			descriptorSetLayouts,								// const VkDescriptorSetLayout*	pSetLayouts;
   1977 			0u,													// deUint32						pushConstantRangeCount;
   1978 			DE_NULL												// const VkPushConstantRange*	pPushConstantRanges;
   1979 		};
   1980 
   1981 		pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
   1982 	}
   1983 
   1984 	// Create shaders
   1985 	{
   1986 		computeShaderModule		= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("compute"), 0);
   1987 	}
   1988 
   1989 	// create pipeline
   1990 	{
   1991 		const VkPipelineShaderStageCreateInfo shaderStageParams[1] =
   1992 		{
   1993 			{
   1994 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
   1995 				DE_NULL,													// const void*							pNext;
   1996 				(VkPipelineShaderStageCreateFlags)0u,						// VkPipelineShaderStageCreateFlags		flags;
   1997 				VK_SHADER_STAGE_COMPUTE_BIT,								// VkShaderStageFlagsBit				stage;
   1998 				*computeShaderModule,										// VkShaderModule						shader;
   1999 				"main",														// const char*							pName;
   2000 				DE_NULL														// const VkSpecializationInfo*			pSpecializationInfo;
   2001 			}
   2002 		};
   2003 
   2004 		const VkComputePipelineCreateInfo computePipelineParams =
   2005 		{
   2006 			VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,		// VkStructureType									sType;
   2007 			DE_NULL,											// const void*										pNext;
   2008 			(VkPipelineCreateFlags)0,							// VkPipelineCreateFlags							flags;
   2009 			*shaderStageParams,									// VkPipelineShaderStageCreateInfo					cs;
   2010 			*pipelineLayout,									// VkPipelineLayout									layout;
   2011 			0u,													// VkPipeline										basePipelineHandle;
   2012 			0u,													// int32_t											basePipelineIndex;
   2013 		};
   2014 
   2015 		computePipeline = createComputePipeline(vk, vkDevice, DE_NULL, &computePipelineParams);
   2016 	}
   2017 
   2018 	// Create fence
   2019 	fence = createFence(vk, vkDevice);
   2020 
   2021 	const int			maxValuesPerInvocation	= m_context.getDeviceProperties().limits.maxComputeWorkGroupSize[0];
   2022 	int					curOffset				= 0;
   2023 	const deUint32		inputStride				= getInputStride();
   2024 	const deUint32		outputStride			= getOutputStride();
   2025 
   2026 	while (curOffset < numValues)
   2027 	{
   2028 		Move<VkCommandBuffer>	cmdBuffer;
   2029 		const int				numToExec	= de::min(maxValuesPerInvocation, numValues-curOffset);
   2030 
   2031 		// Update descriptors
   2032 		{
   2033 			DescriptorSetUpdateBuilder descriptorSetUpdateBuilder;
   2034 
   2035 			const VkDescriptorBufferInfo outputDescriptorBufferInfo =
   2036 			{
   2037 				*m_outputBuffer,				// VkBuffer			buffer;
   2038 				curOffset * outputStride,		// VkDeviceSize		offset;
   2039 				numToExec * outputStride		// VkDeviceSize		range;
   2040 			};
   2041 
   2042 			descriptorSetUpdateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding((deUint32)OUTPUT_BUFFER_BINDING), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outputDescriptorBufferInfo);
   2043 
   2044 			if (inputStride)
   2045 			{
   2046 				const VkDescriptorBufferInfo inputDescriptorBufferInfo =
   2047 				{
   2048 					*m_inputBuffer,					// VkBuffer			buffer;
   2049 					curOffset * inputStride,		// VkDeviceSize		offset;
   2050 					numToExec * inputStride			// VkDeviceSize		range;
   2051 				};
   2052 
   2053 				descriptorSetUpdateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding((deUint32)INPUT_BUFFER_BINDING), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &inputDescriptorBufferInfo);
   2054 			}
   2055 
   2056 			descriptorSetUpdateBuilder.update(vk, vkDevice);
   2057 		}
   2058 
   2059 		cmdBuffer = allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
   2060 		VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
   2061 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *computePipeline);
   2062 
   2063 		{
   2064 			const VkDescriptorSet	descriptorSets[]	= { *descriptorSet, extraResources };
   2065 			vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, numDescriptorSets, descriptorSets, 0u, DE_NULL);
   2066 		}
   2067 
   2068 		vk.cmdDispatch(*cmdBuffer, numToExec, 1, 1);
   2069 
   2070 		VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
   2071 
   2072 		curOffset += numToExec;
   2073 
   2074 		// Execute
   2075 		{
   2076 			VK_CHECK(vk.resetFences(vkDevice, 1, &fence.get()));
   2077 
   2078 			const VkSubmitInfo submitInfo =
   2079 			{
   2080 				VK_STRUCTURE_TYPE_SUBMIT_INFO,
   2081 				DE_NULL,
   2082 				0u,
   2083 				(const VkSemaphore*)DE_NULL,
   2084 				(const VkPipelineStageFlags*)DE_NULL,
   2085 				1u,
   2086 				&cmdBuffer.get(),
   2087 				0u,
   2088 				(const VkSemaphore*)DE_NULL,
   2089 			};
   2090 
   2091 			VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
   2092 			VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), true, ~(0ull) /* infinity*/));
   2093 		}
   2094 	}
   2095 
   2096 	// Read back data
   2097 	readOutputBuffer(outputs, numValues);
   2098 }
   2099 
   2100 // Tessellation utils
   2101 
   2102 static std::string generateVertexShaderForTess (void)
   2103 {
   2104 	std::ostringstream	src;
   2105 	src << "#version 310 es\n"
   2106 		<< "void main (void)\n{\n"
   2107 		<< "	gl_Position = vec4(gl_VertexIndex/2, gl_VertexIndex%2, 0.0, 1.0);\n"
   2108 		<< "}\n";
   2109 
   2110 	return src.str();
   2111 }
   2112 
   2113 class TessellationExecutor : public BufferIoExecutor
   2114 {
   2115 public:
   2116 					TessellationExecutor		(Context& context, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout);
   2117 	virtual			~TessellationExecutor		(void);
   2118 
   2119 	void			renderTess					(deUint32 numValues, deUint32 vertexCount, deUint32 patchControlPoints, VkDescriptorSet extraResources);
   2120 
   2121 private:
   2122 	const VkDescriptorSetLayout					m_extraResourcesLayout;
   2123 };
   2124 
   2125 TessellationExecutor::TessellationExecutor (Context& context, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout)
   2126 	: BufferIoExecutor			(context, shaderSpec)
   2127 	, m_extraResourcesLayout	(extraResourcesLayout)
   2128 {
   2129 	const VkPhysicalDeviceFeatures& features = context.getDeviceFeatures();
   2130 
   2131 	if (!features.tessellationShader)
   2132 		TCU_THROW(NotSupportedError, "Tessellation shader is not supported by device");
   2133 }
   2134 
   2135 TessellationExecutor::~TessellationExecutor (void)
   2136 {
   2137 }
   2138 
   2139 void TessellationExecutor::renderTess (deUint32 numValues, deUint32 vertexCount, deUint32 patchControlPoints, VkDescriptorSet extraResources)
   2140 {
   2141 	const size_t						inputBufferSize				= numValues * getInputStride();
   2142 	const VkDevice						vkDevice					= m_context.getDevice();
   2143 	const DeviceInterface&				vk							= m_context.getDeviceInterface();
   2144 	const VkQueue						queue						= m_context.getUniversalQueue();
   2145 	const deUint32						queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
   2146 	Allocator&							memAlloc					= m_context.getDefaultAllocator();
   2147 
   2148 	const tcu::UVec2					renderSize					(DEFAULT_RENDER_WIDTH, DEFAULT_RENDER_HEIGHT);
   2149 
   2150 	Move<VkImage>						colorImage;
   2151 	de::MovePtr<Allocation>				colorImageAlloc;
   2152 	VkFormat							colorFormat					= VK_FORMAT_R8G8B8A8_UNORM;
   2153 	Move<VkImageView>					colorImageView;
   2154 
   2155 	Move<VkRenderPass>					renderPass;
   2156 	Move<VkFramebuffer>					framebuffer;
   2157 	Move<VkPipelineLayout>				pipelineLayout;
   2158 	Move<VkPipeline>					graphicsPipeline;
   2159 
   2160 	Move<VkShaderModule>				vertexShaderModule;
   2161 	Move<VkShaderModule>				tessControlShaderModule;
   2162 	Move<VkShaderModule>				tessEvalShaderModule;
   2163 	Move<VkShaderModule>				fragmentShaderModule;
   2164 
   2165 	Move<VkCommandPool>					cmdPool;
   2166 	Move<VkCommandBuffer>				cmdBuffer;
   2167 
   2168 	Move<VkFence>						fence;
   2169 
   2170 	Move<VkDescriptorPool>				descriptorPool;
   2171 	Move<VkDescriptorSetLayout>			descriptorSetLayout;
   2172 	Move<VkDescriptorSet>				descriptorSet;
   2173 	const deUint32						numDescriptorSets			= (m_extraResourcesLayout != 0) ? 2u : 1u;
   2174 
   2175 	DE_ASSERT((m_extraResourcesLayout != 0) == (extraResources != 0));
   2176 
   2177 	// Create color image
   2178 	{
   2179 		const VkImageCreateInfo colorImageParams =
   2180 		{
   2181 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
   2182 			DE_NULL,																	// const void*				pNext;
   2183 			0u,																			// VkImageCreateFlags		flags;
   2184 			VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
   2185 			colorFormat,																// VkFormat					format;
   2186 			{ renderSize.x(), renderSize.y(), 1u },										// VkExtent3D				extent;
   2187 			1u,																			// deUint32					mipLevels;
   2188 			1u,																			// deUint32					arraySize;
   2189 			VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits	samples;
   2190 			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
   2191 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags		usage;
   2192 			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
   2193 			1u,																			// deUint32					queueFamilyCount;
   2194 			&queueFamilyIndex,															// const deUint32*			pQueueFamilyIndices;
   2195 			VK_IMAGE_LAYOUT_UNDEFINED													// VkImageLayout			initialLayout;
   2196 		};
   2197 
   2198 		colorImage = createImage(vk, vkDevice, &colorImageParams);
   2199 
   2200 		// Allocate and bind color image memory
   2201 		colorImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *colorImage), MemoryRequirement::Any);
   2202 		VK_CHECK(vk.bindImageMemory(vkDevice, *colorImage, colorImageAlloc->getMemory(), colorImageAlloc->getOffset()));
   2203 	}
   2204 
   2205 	// Create color attachment view
   2206 	{
   2207 		const VkImageViewCreateInfo colorImageViewParams =
   2208 		{
   2209 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
   2210 			DE_NULL,											// const void*				pNext;
   2211 			0u,													// VkImageViewCreateFlags	flags;
   2212 			*colorImage,										// VkImage					image;
   2213 			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
   2214 			colorFormat,										// VkFormat					format;
   2215 			{
   2216 				VK_COMPONENT_SWIZZLE_R,							// VkComponentSwizzle		r;
   2217 				VK_COMPONENT_SWIZZLE_G,							// VkComponentSwizzle		g;
   2218 				VK_COMPONENT_SWIZZLE_B,							// VkComponentSwizzle		b;
   2219 				VK_COMPONENT_SWIZZLE_A							// VkComponentSwizzle		a;
   2220 			},													// VkComponentsMapping		components;
   2221 			{
   2222 				VK_IMAGE_ASPECT_COLOR_BIT,						// VkImageAspectFlags		aspectMask;
   2223 				0u,												// deUint32					baseMipLevel;
   2224 				1u,												// deUint32					mipLevels;
   2225 				0u,												// deUint32					baseArraylayer;
   2226 				1u												// deUint32					layerCount;
   2227 			}													// VkImageSubresourceRange	subresourceRange;
   2228 		};
   2229 
   2230 		colorImageView = createImageView(vk, vkDevice, &colorImageViewParams);
   2231 	}
   2232 
   2233 	// Create render pass
   2234 	{
   2235 		const VkAttachmentDescription colorAttachmentDescription =
   2236 		{
   2237 			0u,													// VkAttachmentDescriptorFlags	flags;
   2238 			colorFormat,										// VkFormat						format;
   2239 			VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits		samples;
   2240 			VK_ATTACHMENT_LOAD_OP_CLEAR,						// VkAttachmentLoadOp			loadOp;
   2241 			VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp			storeOp;
   2242 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// VkAttachmentLoadOp			stencilLoadOp;
   2243 			VK_ATTACHMENT_STORE_OP_DONT_CARE,					// VkAttachmentStoreOp			stencilStoreOp;
   2244 			VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout				initialLayout;
   2245 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout				finalLayout
   2246 		};
   2247 
   2248 		const VkAttachmentDescription attachments[1] =
   2249 		{
   2250 			colorAttachmentDescription
   2251 		};
   2252 
   2253 		const VkAttachmentReference colorAttachmentReference =
   2254 		{
   2255 			0u,													// deUint32			attachment;
   2256 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL			// VkImageLayout	layout;
   2257 		};
   2258 
   2259 		const VkSubpassDescription subpassDescription =
   2260 		{
   2261 			0u,													// VkSubpassDescriptionFlags	flags;
   2262 			VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint			pipelineBindPoint;
   2263 			0u,													// deUint32						inputCount;
   2264 			DE_NULL,											// const VkAttachmentReference*	pInputAttachments;
   2265 			1u,													// deUint32						colorCount;
   2266 			&colorAttachmentReference,							// const VkAttachmentReference*	pColorAttachments;
   2267 			DE_NULL,											// const VkAttachmentReference*	pResolveAttachments;
   2268 			DE_NULL,											// VkAttachmentReference		depthStencilAttachment;
   2269 			0u,													// deUint32						preserveCount;
   2270 			DE_NULL												// const VkAttachmentReference* pPreserveAttachments;
   2271 		};
   2272 
   2273 		const VkRenderPassCreateInfo renderPassParams =
   2274 		{
   2275 			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
   2276 			DE_NULL,											// const void*						pNext;
   2277 			0u,													// VkRenderPassCreateFlags			flags;
   2278 			1u,													// deUint32							attachmentCount;
   2279 			attachments,										// const VkAttachmentDescription*	pAttachments;
   2280 			1u,													// deUint32							subpassCount;
   2281 			&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
   2282 			0u,													// deUint32							dependencyCount;
   2283 			DE_NULL												// const VkSubpassDependency*		pDependencies;
   2284 		};
   2285 
   2286 		renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
   2287 	}
   2288 
   2289 	// Create framebuffer
   2290 	{
   2291 		const VkFramebufferCreateInfo framebufferParams =
   2292 		{
   2293 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType				sType;
   2294 			DE_NULL,											// const void*					pNext;
   2295 			0u,													// VkFramebufferCreateFlags		flags;
   2296 			*renderPass,										// VkRenderPass					renderPass;
   2297 			1u,													// deUint32						attachmentCount;
   2298 			&*colorImageView,									// const VkAttachmentBindInfo*	pAttachments;
   2299 			(deUint32)renderSize.x(),							// deUint32						width;
   2300 			(deUint32)renderSize.y(),							// deUint32						height;
   2301 			1u													// deUint32						layers;
   2302 		};
   2303 
   2304 		framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
   2305 	}
   2306 
   2307 	// Create descriptors
   2308 	{
   2309 		DescriptorPoolBuilder		descriptorPoolBuilder;
   2310 		DescriptorSetLayoutBuilder	descriptorSetLayoutBuilder;
   2311 
   2312 		descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_ALL);
   2313 		descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
   2314 		descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_ALL);
   2315 		descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
   2316 
   2317 		descriptorSetLayout	= descriptorSetLayoutBuilder.build(vk, vkDevice);
   2318 		descriptorPool		= descriptorPoolBuilder.build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
   2319 
   2320 		const VkDescriptorSetAllocateInfo allocInfo =
   2321 		{
   2322 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
   2323 			DE_NULL,
   2324 			*descriptorPool,
   2325 			1u,
   2326 			&*descriptorSetLayout
   2327 		};
   2328 
   2329 		descriptorSet = allocateDescriptorSet(vk, vkDevice, &allocInfo);
   2330 		// Update descriptors
   2331 		{
   2332 			DescriptorSetUpdateBuilder descriptorSetUpdateBuilder;
   2333 			const VkDescriptorBufferInfo outputDescriptorBufferInfo =
   2334 			{
   2335 				*m_outputBuffer,				// VkBuffer			buffer;
   2336 				0u,								// VkDeviceSize		offset;
   2337 				VK_WHOLE_SIZE					// VkDeviceSize		range;
   2338 			};
   2339 
   2340 			descriptorSetUpdateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding((deUint32)OUTPUT_BUFFER_BINDING), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outputDescriptorBufferInfo);
   2341 
   2342 			VkDescriptorBufferInfo inputDescriptorBufferInfo =
   2343 			{
   2344 				0,							// VkBuffer			buffer;
   2345 				0u,							// VkDeviceSize		offset;
   2346 				VK_WHOLE_SIZE				// VkDeviceSize		range;
   2347 			};
   2348 
   2349 			if (inputBufferSize > 0)
   2350 			{
   2351 				inputDescriptorBufferInfo.buffer = *m_inputBuffer;
   2352 
   2353 				descriptorSetUpdateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding((deUint32)INPUT_BUFFER_BINDING), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &inputDescriptorBufferInfo);
   2354 			}
   2355 
   2356 			descriptorSetUpdateBuilder.update(vk, vkDevice);
   2357 		}
   2358 	}
   2359 
   2360 	// Create pipeline layout
   2361 	{
   2362 		const VkDescriptorSetLayout			descriptorSetLayouts[]		=
   2363 		{
   2364 			*descriptorSetLayout,
   2365 			m_extraResourcesLayout
   2366 		};
   2367 		const VkPipelineLayoutCreateInfo pipelineLayoutParams =
   2368 		{
   2369 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType				sType;
   2370 			DE_NULL,											// const void*					pNext;
   2371 			(VkPipelineLayoutCreateFlags)0,						// VkPipelineLayoutCreateFlags	flags;
   2372 			numDescriptorSets,									// deUint32						descriptorSetCount;
   2373 			descriptorSetLayouts,								// const VkDescriptorSetLayout*	pSetLayouts;
   2374 			0u,													// deUint32						pushConstantRangeCount;
   2375 			DE_NULL												// const VkPushConstantRange*	pPushConstantRanges;
   2376 		};
   2377 
   2378 		pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
   2379 	}
   2380 
   2381 	// Create shader modules
   2382 	{
   2383 		vertexShaderModule		= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("vert"), 0);
   2384 		tessControlShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("tess_control"), 0);
   2385 		tessEvalShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("tess_eval"), 0);
   2386 		fragmentShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("frag"), 0);
   2387 	}
   2388 
   2389 	// Create pipeline
   2390 	{
   2391 		const VkPipelineShaderStageCreateInfo shaderStageParams[4] =
   2392 		{
   2393 			{
   2394 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
   2395 				DE_NULL,													// const void*							pNext;
   2396 				(VkPipelineShaderStageCreateFlags)0,						// VkPipelineShaderStageCreateFlags		flags;
   2397 				VK_SHADER_STAGE_VERTEX_BIT,									// VkShaderStageFlagBit					stage;
   2398 				*vertexShaderModule,										// VkShaderModule						shader;
   2399 				"main",														// const char*							pName;
   2400 				DE_NULL														// const VkSpecializationInfo*			pSpecializationInfo;
   2401 			},
   2402 			{
   2403 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
   2404 				DE_NULL,													// const void*							pNext;
   2405 				(VkPipelineShaderStageCreateFlags)0,						// VkPipelineShaderStageCreateFlags		flags;
   2406 				VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,					// VkShaderStageFlagBit					stage;
   2407 				*tessControlShaderModule,									// VkShaderModule						shader;
   2408 				"main",														// const char*							pName;
   2409 				DE_NULL														// const VkSpecializationInfo*			pSpecializationInfo;
   2410 			},
   2411 			{
   2412 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
   2413 				DE_NULL,													// const void*							pNext;
   2414 				(VkPipelineShaderStageCreateFlags)0,						// VkPipelineShaderStageCreateFlags		flags;
   2415 				VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,				// VkShaderStageFlagBit					stage;
   2416 				*tessEvalShaderModule,										// VkShaderModule						shader;
   2417 				"main",														// const char*							pName;
   2418 				DE_NULL														// const VkSpecializationInfo*			pSpecializationInfo;
   2419 			},
   2420 			{
   2421 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,		// VkStructureType						sType;
   2422 				DE_NULL,													// const void*							pNext;
   2423 				(VkPipelineShaderStageCreateFlags)0,						// VkPipelineShaderStageCreateFlags		flags;
   2424 				VK_SHADER_STAGE_FRAGMENT_BIT,								// VkShaderStageFlagBit					stage;
   2425 				*fragmentShaderModule,										// VkShaderModule						shader;
   2426 				"main",														// const char*							pName;
   2427 				DE_NULL														// const VkSpecializationInfo*			pSpecializationInfo;
   2428 			}
   2429 		};
   2430 
   2431 		const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
   2432 		{
   2433 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
   2434 			DE_NULL,														// const void*								pNext;
   2435 			(VkPipelineVertexInputStateCreateFlags)0,						// VkPipelineVertexInputStateCreateFlags	flags;
   2436 			0u,																// deUint32									bindingCount;
   2437 			DE_NULL,														// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
   2438 			0u,																// deUint32									attributeCount;
   2439 			DE_NULL,														// const VkVertexInputAttributeDescription*	pvertexAttributeDescriptions;
   2440 		};
   2441 
   2442 		const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
   2443 		{
   2444 			VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType						sType;
   2445 			DE_NULL,														// const void*							pNext;
   2446 			(VkPipelineShaderStageCreateFlags)0,							// VkPipelineShaderStageCreateFlags	flags;
   2447 			VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,								// VkPrimitiveTopology					topology;
   2448 			DE_FALSE														// VkBool32								primitiveRestartEnable;
   2449 		};
   2450 
   2451 		struct VkPipelineTessellationStateCreateInfo tessellationStateParams =
   2452 		{
   2453 			VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,		// VkStructureType							sType;
   2454 			DE_NULL,														// const void*								pNext;
   2455 			(VkPipelineTessellationStateCreateFlags)0,						// VkPipelineTessellationStateCreateFlags	flags;
   2456 			patchControlPoints												// uint32_t									patchControlPoints;
   2457 		};
   2458 
   2459 		const VkViewport viewport =
   2460 		{
   2461 			0.0f,						// float	originX;
   2462 			0.0f,						// float	originY;
   2463 			(float)renderSize.x(),		// float	width;
   2464 			(float)renderSize.y(),		// float	height;
   2465 			0.0f,						// float	minDepth;
   2466 			1.0f						// float	maxDepth;
   2467 		};
   2468 
   2469 		const VkRect2D scissor =
   2470 		{
   2471 			{
   2472 				0u,						// deUint32	x;
   2473 				0u,						// deUint32	y;
   2474 			},							// VkOffset2D	offset;
   2475 			{
   2476 				renderSize.x(),			// deUint32	width;
   2477 				renderSize.y(),			// deUint32	height;
   2478 			},							// VkExtent2D	extent;
   2479 		};
   2480 
   2481 		const VkPipelineViewportStateCreateInfo viewportStateParams =
   2482 		{
   2483 			VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,	// VkStructureType						sType;
   2484 			DE_NULL,												// const void*							pNext;
   2485 			(VkPipelineViewportStateCreateFlags)0,					// VkPipelineViewPortStateCreateFlags	flags;
   2486 			1u,														// deUint32								viewportCount;
   2487 			&viewport,												// const VkViewport*					pViewports;
   2488 			1u,														// deUint32								scissorsCount;
   2489 			&scissor												// const VkRect2D*						pScissors;
   2490 		};
   2491 
   2492 		const VkPipelineRasterizationStateCreateInfo rasterStateParams =
   2493 		{
   2494 			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType							sType;
   2495 			DE_NULL,														// const void*								pNext;
   2496 			(VkPipelineRasterizationStateCreateFlags)0,						// VkPipelineRasterizationStageCreateFlags	flags;
   2497 			VK_FALSE,														// VkBool32									depthClipEnable;
   2498 			VK_FALSE,														// VkBool32									rasterizerDiscardEnable;
   2499 			VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
   2500 			VK_CULL_MODE_NONE,												// VkCullMode								cullMode;
   2501 			VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
   2502 			VK_FALSE,														// VkBool32									depthBiasEnable;
   2503 			0.0f,															// float									depthBias;
   2504 			0.0f,															// float									depthBiasClamp;
   2505 			0.0f,															// float									slopeScaledDepthBias;
   2506 			1.0f															// float									lineWidth;
   2507 		};
   2508 
   2509 		const VkPipelineMultisampleStateCreateInfo multisampleStateParams =
   2510 		{
   2511 			VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,		// VkStructureType							sType;
   2512 			DE_NULL,														// const void*								pNext;
   2513 			0u,																// VkPipelineMultisampleStateCreateFlags	flags;
   2514 			VK_SAMPLE_COUNT_1_BIT,											// VkSampleCountFlagBits					rasterizationSamples;
   2515 			VK_FALSE,														// VkBool32									sampleShadingEnable;
   2516 			0.0f,															// float									minSampleShading;
   2517 			DE_NULL,														// const VkSampleMask*						pSampleMask;
   2518 			VK_FALSE,														// VkBool32									alphaToCoverageEnable;
   2519 			VK_FALSE														// VkBool32									alphaToOneEnable;
   2520 		};
   2521 
   2522 		const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
   2523 		{
   2524 			VK_FALSE,						// VkBool32					blendEnable;
   2525 			VK_BLEND_FACTOR_ONE,			// VkBlendFactor			srcBlendColor;
   2526 			VK_BLEND_FACTOR_ZERO,			// VkBlendFactor			destBlendColor;
   2527 			VK_BLEND_OP_ADD,				// VkBlendOp				blendOpColor;
   2528 			VK_BLEND_FACTOR_ONE,			// VkBlendFactor			srcBlendAlpha;
   2529 			VK_BLEND_FACTOR_ZERO,			// VkBlendFactor			destBlendAlpha;
   2530 			VK_BLEND_OP_ADD,				// VkBlendOp				blendOpAlpha;
   2531 			(VK_COLOR_COMPONENT_R_BIT |
   2532 			 VK_COLOR_COMPONENT_G_BIT |
   2533 			 VK_COLOR_COMPONENT_B_BIT |
   2534 			 VK_COLOR_COMPONENT_A_BIT)		// VkColorComponentFlags	colorWriteMask;
   2535 		};
   2536 
   2537 		const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
   2538 		{
   2539 			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
   2540 			DE_NULL,													// const void*									pNext;
   2541 			(VkPipelineColorBlendStateCreateFlags)0,					// VkPipelineColorBlendStateCreateFlags			flags
   2542 			VK_FALSE,													// VkBool32										logicOpEnable;
   2543 			VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
   2544 			1u,															// deUint32										attachmentCount;
   2545 			&colorBlendAttachmentState,									// const VkPipelineColorBlendAttachmentState*	pAttachments;
   2546 			{ 0.0f, 0.0f, 0.0f, 0.0f }									// float										blendConst[4];
   2547 		};
   2548 
   2549 		const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
   2550 		{
   2551 			VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
   2552 			DE_NULL,											// const void*										pNext;
   2553 			0u,													// VkPipelineCreateFlags							flags;
   2554 			4u,													// deUint32											stageCount;
   2555 			shaderStageParams,									// const VkPipelineShaderStageCreateInfo*			pStages;
   2556 			&vertexInputStateParams,							// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
   2557 			&inputAssemblyStateParams,							// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
   2558 			&tessellationStateParams,							// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
   2559 			&viewportStateParams,								// const VkPipelineViewportStateCreateInfo*			pViewportState;
   2560 			&rasterStateParams,									// const VkPipelineRasterStateCreateInfo*			pRasterState;
   2561 			&multisampleStateParams,							// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
   2562 			DE_NULL,											// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
   2563 			&colorBlendStateParams,								// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
   2564 			(const VkPipelineDynamicStateCreateInfo*)DE_NULL,	// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
   2565 			*pipelineLayout,									// VkPipelineLayout									layout;
   2566 			*renderPass,										// VkRenderPass										renderPass;
   2567 			0u,													// deUint32											subpass;
   2568 			0u,													// VkPipeline										basePipelineHandle;
   2569 			0u													// deInt32											basePipelineIndex;
   2570 		};
   2571 
   2572 		graphicsPipeline = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
   2573 	}
   2574 
   2575 	// Create command pool
   2576 	cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
   2577 
   2578 	// Create command buffer
   2579 	{
   2580 		const VkCommandBufferBeginInfo cmdBufferBeginInfo =
   2581 		{
   2582 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType					sType;
   2583 			DE_NULL,										// const void*						pNext;
   2584 			0u,												// VkCmdBufferOptimizeFlags			flags;
   2585 			(const VkCommandBufferInheritanceInfo*)DE_NULL,
   2586 		};
   2587 
   2588 		const VkClearValue clearValues[1] =
   2589 		{
   2590 			getDefaultClearColor()
   2591 		};
   2592 
   2593 		const VkRenderPassBeginInfo renderPassBeginInfo =
   2594 		{
   2595 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,				// VkStructureType		sType;
   2596 			DE_NULL,												// const void*			pNext;
   2597 			*renderPass,											// VkRenderPass			renderPass;
   2598 			*framebuffer,											// VkFramebuffer		framebuffer;
   2599 			{ { 0, 0 }, { renderSize.x(), renderSize.y() } },		// VkRect2D				renderArea;
   2600 			1,														// deUint32				attachmentCount;
   2601 			clearValues												// const VkClearValue*	pClearValues;
   2602 		};
   2603 
   2604 		cmdBuffer = allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
   2605 
   2606 		VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
   2607 
   2608 		vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
   2609 
   2610 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
   2611 
   2612 		{
   2613 			const VkDescriptorSet	descriptorSets[]	= { *descriptorSet, extraResources };
   2614 			vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, numDescriptorSets, descriptorSets, 0u, DE_NULL);
   2615 		}
   2616 
   2617 		vk.cmdDraw(*cmdBuffer, vertexCount, 1, 0, 0);
   2618 
   2619 		vk.cmdEndRenderPass(*cmdBuffer);
   2620 		VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
   2621 	}
   2622 
   2623 	// Create fence
   2624 	fence = createFence(vk, vkDevice);
   2625 
   2626 	// Execute Draw
   2627 	{
   2628 		VK_CHECK(vk.resetFences(vkDevice, 1, &fence.get()));
   2629 		const VkSubmitInfo submitInfo =
   2630 		{
   2631 			VK_STRUCTURE_TYPE_SUBMIT_INFO,
   2632 			DE_NULL,
   2633 			0u,
   2634 			(const VkSemaphore*)0,
   2635 			(const VkPipelineStageFlags*)DE_NULL,
   2636 			1u,
   2637 			&cmdBuffer.get(),
   2638 			0u,
   2639 			(const VkSemaphore*)0,
   2640 		};
   2641 		VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *fence));
   2642 		VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), true, ~(0ull) /* infinity*/));
   2643 	}
   2644 }
   2645 
   2646 // TessControlExecutor
   2647 
   2648 class TessControlExecutor : public TessellationExecutor
   2649 {
   2650 public:
   2651 						TessControlExecutor			(Context& context, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout);
   2652 	virtual				~TessControlExecutor		(void);
   2653 
   2654 	static void			generateSources				(const ShaderSpec& shaderSpec, SourceCollections& programCollection);
   2655 
   2656 	virtual void		execute						(int numValues, const void* const* inputs, void* const* outputs, VkDescriptorSet extraResources);
   2657 
   2658 protected:
   2659 	static std::string	generateTessControlShader	(const ShaderSpec& shaderSpec);
   2660 };
   2661 
   2662 TessControlExecutor::TessControlExecutor (Context& context, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout)
   2663 	: TessellationExecutor(context, shaderSpec, extraResourcesLayout)
   2664 {
   2665 }
   2666 
   2667 TessControlExecutor::~TessControlExecutor (void)
   2668 {
   2669 }
   2670 
   2671 std::string TessControlExecutor::generateTessControlShader (const ShaderSpec& shaderSpec)
   2672 {
   2673 	std::ostringstream src;
   2674 	src << glu::getGLSLVersionDeclaration(shaderSpec.glslVersion) << "\n";
   2675 
   2676 	if (shaderSpec.glslVersion == glu::GLSL_VERSION_310_ES)
   2677 		src << "#extension GL_EXT_tessellation_shader : require\n\n";
   2678 
   2679 	if (!shaderSpec.globalDeclarations.empty())
   2680 		src << shaderSpec.globalDeclarations << "\n";
   2681 
   2682 	src << "\nlayout(vertices = 1) out;\n\n";
   2683 
   2684 	declareBufferBlocks(src, shaderSpec);
   2685 
   2686 	src << "void main (void)\n{\n";
   2687 
   2688 	for (int ndx = 0; ndx < 2; ndx++)
   2689 		src << "\tgl_TessLevelInner[" << ndx << "] = 1.0;\n";
   2690 
   2691 	for (int ndx = 0; ndx < 4; ndx++)
   2692 		src << "\tgl_TessLevelOuter[" << ndx << "] = 1.0;\n";
   2693 
   2694 	src << "\n"
   2695 		<< "\thighp uint invocationId = uint(gl_PrimitiveID);\n";
   2696 
   2697 	generateExecBufferIo(src, shaderSpec, "invocationId");
   2698 
   2699 	src << "}\n";
   2700 
   2701 	return src.str();
   2702 }
   2703 
   2704 static std::string generateEmptyTessEvalShader ()
   2705 {
   2706 	std::ostringstream src;
   2707 
   2708 	src << "#version 310 es\n"
   2709 		   "#extension GL_EXT_tessellation_shader : require\n\n";
   2710 
   2711 	src << "layout(triangles, ccw) in;\n";
   2712 
   2713 	src << "\nvoid main (void)\n{\n"
   2714 		<< "\tgl_Position = vec4(gl_TessCoord.xy, 0.0, 1.0);\n"
   2715 		<< "}\n";
   2716 
   2717 	return src.str();
   2718 }
   2719 
   2720 void TessControlExecutor::generateSources (const ShaderSpec& shaderSpec, SourceCollections& programCollection)
   2721 {
   2722 	programCollection.glslSources.add("vert") << glu::VertexSource(generateVertexShaderForTess()) << shaderSpec.buildOptions;
   2723 	programCollection.glslSources.add("tess_control") << glu::TessellationControlSource(generateTessControlShader(shaderSpec)) << shaderSpec.buildOptions;
   2724 	programCollection.glslSources.add("tess_eval") << glu::TessellationEvaluationSource(generateEmptyTessEvalShader()) << shaderSpec.buildOptions;
   2725 	programCollection.glslSources.add("frag") << glu::FragmentSource(generateEmptyFragmentSource()) << shaderSpec.buildOptions;
   2726 }
   2727 
   2728 void TessControlExecutor::execute (int numValues, const void* const* inputs, void* const* outputs, VkDescriptorSet extraResources)
   2729 {
   2730 	const deUint32	patchSize	= 3;
   2731 
   2732 	initBuffers(numValues);
   2733 
   2734 	// Setup input buffer & copy data
   2735 	uploadInputBuffer(inputs, numValues);
   2736 
   2737 	renderTess(numValues, patchSize * numValues, patchSize, extraResources);
   2738 
   2739 	// Read back data
   2740 	readOutputBuffer(outputs, numValues);
   2741 }
   2742 
   2743 // TessEvaluationExecutor
   2744 
   2745 class TessEvaluationExecutor : public TessellationExecutor
   2746 {
   2747 public:
   2748 						TessEvaluationExecutor	(Context& context, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout);
   2749 	virtual				~TessEvaluationExecutor	(void);
   2750 
   2751 	static void			generateSources			(const ShaderSpec& shaderSpec, SourceCollections& programCollection);
   2752 
   2753 	virtual void		execute					(int numValues, const void* const* inputs, void* const* outputs, VkDescriptorSet extraResources);
   2754 
   2755 protected:
   2756 	static std::string	generateTessEvalShader	(const ShaderSpec& shaderSpec);
   2757 };
   2758 
   2759 TessEvaluationExecutor::TessEvaluationExecutor (Context& context, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout)
   2760 	: TessellationExecutor (context, shaderSpec, extraResourcesLayout)
   2761 {
   2762 }
   2763 
   2764 TessEvaluationExecutor::~TessEvaluationExecutor (void)
   2765 {
   2766 }
   2767 
   2768 static std::string generatePassthroughTessControlShader (void)
   2769 {
   2770 	std::ostringstream src;
   2771 
   2772 	src << "#version 310 es\n"
   2773 		   "#extension GL_EXT_tessellation_shader : require\n\n";
   2774 
   2775 	src << "layout(vertices = 1) out;\n\n";
   2776 
   2777 	src << "void main (void)\n{\n";
   2778 
   2779 	for (int ndx = 0; ndx < 2; ndx++)
   2780 		src << "\tgl_TessLevelInner[" << ndx << "] = 1.0;\n";
   2781 
   2782 	for (int ndx = 0; ndx < 4; ndx++)
   2783 		src << "\tgl_TessLevelOuter[" << ndx << "] = 1.0;\n";
   2784 
   2785 	src << "}\n";
   2786 
   2787 	return src.str();
   2788 }
   2789 
   2790 std::string TessEvaluationExecutor::generateTessEvalShader (const ShaderSpec& shaderSpec)
   2791 {
   2792 	std::ostringstream src;
   2793 
   2794 	src << glu::getGLSLVersionDeclaration(shaderSpec.glslVersion) << "\n";
   2795 
   2796 	if (shaderSpec.glslVersion == glu::GLSL_VERSION_310_ES)
   2797 		src << "#extension GL_EXT_tessellation_shader : require\n\n";
   2798 
   2799 	if (!shaderSpec.globalDeclarations.empty())
   2800 		src << shaderSpec.globalDeclarations << "\n";
   2801 
   2802 	src << "\n";
   2803 
   2804 	src << "layout(isolines, equal_spacing) in;\n\n";
   2805 
   2806 	declareBufferBlocks(src, shaderSpec);
   2807 
   2808 	src << "void main (void)\n{\n"
   2809 		<< "\tgl_Position = vec4(gl_TessCoord.x, 0.0, 0.0, 1.0);\n"
   2810 		<< "\thighp uint invocationId = uint(gl_PrimitiveID)*2u + (gl_TessCoord.x > 0.5 ? 1u : 0u);\n";
   2811 
   2812 	generateExecBufferIo(src, shaderSpec, "invocationId");
   2813 
   2814 	src	<< "}\n";
   2815 
   2816 	return src.str();
   2817 }
   2818 
   2819 void TessEvaluationExecutor::generateSources (const ShaderSpec& shaderSpec, SourceCollections& programCollection)
   2820 {
   2821 	programCollection.glslSources.add("vert") << glu::VertexSource(generateVertexShaderForTess()) << shaderSpec.buildOptions;
   2822 	programCollection.glslSources.add("tess_control") << glu::TessellationControlSource(generatePassthroughTessControlShader()) << shaderSpec.buildOptions;
   2823 	programCollection.glslSources.add("tess_eval") << glu::TessellationEvaluationSource(generateTessEvalShader(shaderSpec)) << shaderSpec.buildOptions;
   2824 	programCollection.glslSources.add("frag") << glu::FragmentSource(generateEmptyFragmentSource()) << shaderSpec.buildOptions;
   2825 }
   2826 
   2827 void TessEvaluationExecutor::execute (int numValues, const void* const* inputs, void* const* outputs, VkDescriptorSet extraResources)
   2828 {
   2829 	const int	patchSize		= 2;
   2830 	const int	alignedValues	= deAlign32(numValues, patchSize);
   2831 
   2832 	// Initialize buffers with aligned value count to make room for padding
   2833 	initBuffers(alignedValues);
   2834 
   2835 	// Setup input buffer & copy data
   2836 	uploadInputBuffer(inputs, numValues);
   2837 
   2838 	renderTess((deUint32)alignedValues, (deUint32)alignedValues, (deUint32)patchSize, extraResources);
   2839 
   2840 	// Read back data
   2841 	readOutputBuffer(outputs, numValues);
   2842 }
   2843 
   2844 } // anonymous
   2845 
   2846 // ShaderExecutor
   2847 
   2848 ShaderExecutor::~ShaderExecutor (void)
   2849 {
   2850 }
   2851 
   2852 // Utilities
   2853 
   2854 void generateSources (glu::ShaderType shaderType, const ShaderSpec& shaderSpec, vk::SourceCollections& dst)
   2855 {
   2856 	switch (shaderType)
   2857 	{
   2858 		case glu::SHADERTYPE_VERTEX:					VertexShaderExecutor::generateSources	(shaderSpec, dst);	break;
   2859 		case glu::SHADERTYPE_TESSELLATION_CONTROL:		TessControlExecutor::generateSources	(shaderSpec, dst);	break;
   2860 		case glu::SHADERTYPE_TESSELLATION_EVALUATION:	TessEvaluationExecutor::generateSources	(shaderSpec, dst);	break;
   2861 		case glu::SHADERTYPE_GEOMETRY:					GeometryShaderExecutor::generateSources	(shaderSpec, dst);	break;
   2862 		case glu::SHADERTYPE_FRAGMENT:					FragmentShaderExecutor::generateSources	(shaderSpec, dst);	break;
   2863 		case glu::SHADERTYPE_COMPUTE:					ComputeShaderExecutor::generateSources	(shaderSpec, dst);	break;
   2864 		default:
   2865 			TCU_THROW(InternalError, "Unsupported shader type");
   2866 	}
   2867 }
   2868 
   2869 ShaderExecutor* createExecutor (Context& context, glu::ShaderType shaderType, const ShaderSpec& shaderSpec, VkDescriptorSetLayout extraResourcesLayout)
   2870 {
   2871 	switch (shaderType)
   2872 	{
   2873 		case glu::SHADERTYPE_VERTEX:					return new VertexShaderExecutor		(context, shaderSpec, extraResourcesLayout);
   2874 		case glu::SHADERTYPE_TESSELLATION_CONTROL:		return new TessControlExecutor		(context, shaderSpec, extraResourcesLayout);
   2875 		case glu::SHADERTYPE_TESSELLATION_EVALUATION:	return new TessEvaluationExecutor	(context, shaderSpec, extraResourcesLayout);
   2876 		case glu::SHADERTYPE_GEOMETRY:					return new GeometryShaderExecutor	(context, shaderSpec, extraResourcesLayout);
   2877 		case glu::SHADERTYPE_FRAGMENT:					return new FragmentShaderExecutor	(context, shaderSpec, extraResourcesLayout);
   2878 		case glu::SHADERTYPE_COMPUTE:					return new ComputeShaderExecutor	(context, shaderSpec, extraResourcesLayout);
   2879 		default:
   2880 			TCU_THROW(InternalError, "Unsupported shader type");
   2881 	}
   2882 }
   2883 
   2884 } // shaderexecutor
   2885 } // vkt
   2886