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