1abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski/*------------------------------------------------------------------------
2abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * Vulkan Conformance Tests
3abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * ------------------------
4abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski *
5abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * Copyright (c) 2014 The Android Open Source Project
6abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * Copyright (c) 2016 The Khronos Group Inc.
7abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski *
8abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * Licensed under the Apache License, Version 2.0 (the "License");
9abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * you may not use this file except in compliance with the License.
10abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * You may obtain a copy of the License at
11abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski *
12abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski *      http://www.apache.org/licenses/LICENSE-2.0
13abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski *
14abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * Unless required by applicable law or agreed to in writing, software
15abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * distributed under the License is distributed on an "AS IS" BASIS,
16abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * See the License for the specific language governing permissions and
18abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * limitations under the License.
19abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski *
20abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski *//*!
21abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * \file
22abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * \brief Tessellation User Defined IO Tests
23abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski *//*--------------------------------------------------------------------*/
24abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
25abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski#include "vktTessellationUserDefinedIO.hpp"
26abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski#include "vktTestCaseUtil.hpp"
27abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski#include "vktTessellationUtil.hpp"
28abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
29abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski#include "tcuTestLog.hpp"
30abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski#include "tcuImageCompare.hpp"
31abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski#include "tcuImageIO.hpp"
32abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
33abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski#include "gluVarType.hpp"
34abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski#include "gluVarTypeUtil.hpp"
35abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
36abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski#include "vkDefs.hpp"
37abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski#include "vkQueryUtil.hpp"
38abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski#include "vkImageUtil.hpp"
39abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski#include "vkBuilderUtil.hpp"
40abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski#include "vkTypeUtil.hpp"
41abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
42abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski#include "deUniquePtr.hpp"
43abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski#include "deSharedPtr.hpp"
44abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
45abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskinamespace vkt
46abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
47abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskinamespace tessellation
48abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
49abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
50abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiusing namespace vk;
51abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
52abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskinamespace
53abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
54abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
55abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskienum Constants
56abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
57abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	NUM_PER_PATCH_BLOCKS		= 2,
58abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	NUM_PER_PATCH_ARRAY_ELEMS	= 3,
59abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	NUM_OUTPUT_VERTICES			= 5,
60abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	NUM_TESS_LEVELS				= 6,
61abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	MAX_TESSELLATION_PATCH_SIZE = 32,
62abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	RENDER_SIZE					= 256,
63abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
64abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
65abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskienum IOType
66abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
67abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	IO_TYPE_PER_PATCH = 0,
68abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	IO_TYPE_PER_PATCH_ARRAY,
69abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	IO_TYPE_PER_PATCH_BLOCK,
70abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	IO_TYPE_PER_PATCH_BLOCK_ARRAY,
71abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	IO_TYPE_PER_VERTEX,
72abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	IO_TYPE_PER_VERTEX_BLOCK,
73abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
74abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	IO_TYPE_LAST
75abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
76abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
77abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskienum VertexIOArraySize
78abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
79abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	VERTEX_IO_ARRAY_SIZE_IMPLICIT = 0,
80abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	VERTEX_IO_ARRAY_SIZE_EXPLICIT_SHADER_BUILTIN,		//!< Use gl_MaxPatchVertices as size for per-vertex input array.
81abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	VERTEX_IO_ARRAY_SIZE_EXPLICIT_SPEC_MIN,				//!< Minimum maxTessellationPatchSize required by the spec.
82abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
83abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	VERTEX_IO_ARRAY_SIZE_LAST
84abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
85abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
86abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskistruct CaseDefinition
87abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
88abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	TessPrimitiveType	primitiveType;
89abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	IOType				ioType;
90abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	VertexIOArraySize	vertexIOArraySize;
91abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::string			referenceImagePath;
92abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
93abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
94abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskitypedef std::string (*BasicTypeVisitFunc)(const std::string& name, glu::DataType type, int indentationDepth); //!< See glslTraverseBasicTypes below.
95abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
96abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiclass TopLevelObject
97abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
98abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskipublic:
99abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	virtual					~TopLevelObject					(void) {}
100abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
101abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	virtual std::string		name							(void) const = 0;
102abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	virtual std::string		declare							(void) const = 0;
103abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	virtual std::string		declareArray					(const std::string& arraySizeExpr) const = 0;
104abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	virtual std::string		glslTraverseBasicTypeArray		(const int numArrayElements, //!< If negative, traverse just array[gl_InvocationID], not all indices.
105abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski															 const int indentationDepth,
106abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski															 BasicTypeVisitFunc) const = 0;
107abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	virtual std::string		glslTraverseBasicType			(const int indentationDepth,
108abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski															 BasicTypeVisitFunc) const = 0;
109abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	virtual int				numBasicSubobjectsInElementType	(void) const = 0;
110abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	virtual std::string		basicSubobjectAtIndex			(const int index, const int arraySize) const = 0;
111abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
112abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
113abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskistd::string glslTraverseBasicTypes (const std::string&			rootName,
114abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski									const glu::VarType&			rootType,
115abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski									const int					arrayNestingDepth,
116abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski									const int					indentationDepth,
117abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski									const BasicTypeVisitFunc	visit)
118abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
119abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	if (rootType.isBasicType())
120abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		return visit(rootName, rootType.getBasicType(), indentationDepth);
121abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	else if (rootType.isArrayType())
122abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
123abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const std::string indentation	= std::string(indentationDepth, '\t');
124abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const std::string loopIndexName	= "i" + de::toString(arrayNestingDepth);
125abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const std::string arrayLength	= de::toString(rootType.getArraySize());
126abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		return indentation + "for (int " + loopIndexName + " = 0; " + loopIndexName + " < " + de::toString(rootType.getArraySize()) + "; ++" + loopIndexName + ")\n" +
127abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			   indentation + "{\n" +
128abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			   glslTraverseBasicTypes(rootName + "[" + loopIndexName + "]", rootType.getElementType(), arrayNestingDepth+1, indentationDepth+1, visit) +
129abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			   indentation + "}\n";
130abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
131abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	else if (rootType.isStructType())
132abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
133abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const glu::StructType&	structType = *rootType.getStructPtr();
134abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const int				numMembers = structType.getNumMembers();
135abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		std::string				result;
136abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
137abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		for (int membNdx = 0; membNdx < numMembers; ++membNdx)
138abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
139abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			const glu::StructMember& member = structType.getMember(membNdx);
140abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			result += glslTraverseBasicTypes(rootName + "." + member.getName(), member.getType(), arrayNestingDepth, indentationDepth, visit);
141abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
142abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
143abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		return result;
144abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
145abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	else
146abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
147abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		DE_ASSERT(false);
148abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		return DE_NULL;
149abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
150abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
151abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
152abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski//! Used as the 'visit' argument for glslTraverseBasicTypes.
153abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskistd::string glslAssignBasicTypeObject (const std::string& name, const glu::DataType type, const int indentationDepth)
154abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
155abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const int			scalarSize	= glu::getDataTypeScalarSize(type);
156abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const std::string	indentation	= std::string(indentationDepth, '\t');
157abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::ostringstream	result;
158abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
159abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	result << indentation << name << " = ";
160abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
161abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	if (type != glu::TYPE_FLOAT)
162abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		result << std::string() << glu::getDataTypeName(type) << "(";
163abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	for (int i = 0; i < scalarSize; ++i)
1646e5ef4c51158771e71f72c70980b4dbd78f011f2Pyry Haulos		result << (i > 0 ? ", v+" + de::floatToString(0.8f*(float)i, 1) : "v");
165abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	if (type != glu::TYPE_FLOAT)
166abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		result << ")";
167abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	result << ";\n"
168abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		   << indentation << "v += 0.4;\n";
169abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return result.str();
170abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
171abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
172abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski//! Used as the 'visit' argument for glslTraverseBasicTypes.
173abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskistd::string glslCheckBasicTypeObject (const std::string& name, const glu::DataType type, const int indentationDepth)
174abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
175abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const int			scalarSize	= glu::getDataTypeScalarSize(type);
176abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const std::string	indentation	= std::string(indentationDepth, '\t');
177abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::ostringstream	result;
178abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
179abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	result << indentation << "allOk = allOk && compare_" << glu::getDataTypeName(type) << "(" << name << ", ";
180abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
181abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	if (type != glu::TYPE_FLOAT)
182abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		result << std::string() << glu::getDataTypeName(type) << "(";
183abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	for (int i = 0; i < scalarSize; ++i)
1846e5ef4c51158771e71f72c70980b4dbd78f011f2Pyry Haulos		result << (i > 0 ? ", v+" + de::floatToString(0.8f*(float)i, 1) : "v");
185abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	if (type != glu::TYPE_FLOAT)
186abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		result << ")";
187abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	result << ");\n"
188abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		   << indentation << "v += 0.4;\n"
189abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		   << indentation << "if (allOk) ++firstFailedInputIndex;\n";
190abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
191abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return result.str();
192abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
193abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
194abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiint numBasicSubobjectsInElementType (const std::vector<de::SharedPtr<TopLevelObject> >& objects)
195abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
196abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	int result = 0;
197abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	for (int i = 0; i < static_cast<int>(objects.size()); ++i)
198abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		result += objects[i]->numBasicSubobjectsInElementType();
199abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return result;
200abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
201abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
202abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskistd::string basicSubobjectAtIndex (const int subobjectIndex, const std::vector<de::SharedPtr<TopLevelObject> >& objects, const int topLevelArraySize)
203abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
204abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	int currentIndex = 0;
205abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	int objectIndex  = 0;
206abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
207abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	for (; currentIndex < subobjectIndex; ++objectIndex)
208abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		currentIndex += objects[objectIndex]->numBasicSubobjectsInElementType() * topLevelArraySize;
209abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
210abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	if (currentIndex > subobjectIndex)
211abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
212abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		--objectIndex;
213abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		currentIndex -= objects[objectIndex]->numBasicSubobjectsInElementType() * topLevelArraySize;
214abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
215abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
216abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return objects[objectIndex]->basicSubobjectAtIndex(subobjectIndex - currentIndex, topLevelArraySize);
217abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
218abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
219abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiint numBasicSubobjects (const glu::VarType& type)
220abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
221abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	if (type.isBasicType())
222abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		return 1;
223abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	else if (type.isArrayType())
224abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		return type.getArraySize()*numBasicSubobjects(type.getElementType());
225abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	else if (type.isStructType())
226abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
227abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const glu::StructType&	structType	= *type.getStructPtr();
228abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		int						result		= 0;
229abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		for (int i = 0; i < structType.getNumMembers(); ++i)
230abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			result += numBasicSubobjects(structType.getMember(i).getType());
231abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		return result;
232abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
233abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	else
234abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
235abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		DE_ASSERT(false);
236abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		return -1;
237abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
238abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
239abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
240abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiclass Variable : public TopLevelObject
241abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
242abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskipublic:
243abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	Variable (const std::string& name_, const glu::VarType& type, const bool isArray)
244abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		: m_name		(name_)
245abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		, m_type		(type)
246abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		, m_isArray		(isArray)
247abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
248abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		DE_ASSERT(!type.isArrayType());
249abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
250abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
251abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::string		name								(void) const { return m_name; }
252abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::string		declare								(void) const;
253abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::string		declareArray						(const std::string& arraySizeExpr) const;
254abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::string		glslTraverseBasicTypeArray			(const int numArrayElements, const int indentationDepth, BasicTypeVisitFunc) const;
255abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::string		glslTraverseBasicType				(const int indentationDepth, BasicTypeVisitFunc) const;
256abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	int				numBasicSubobjectsInElementType		(void) const;
257abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::string		basicSubobjectAtIndex				(const int index, const int arraySize) const;
258abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
259abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiprivate:
260abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::string		m_name;
261abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	glu::VarType	m_type; //!< If this Variable is an array element, m_type is the element type; otherwise just the variable type.
262abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const bool		m_isArray;
263abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
264abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
265abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskistd::string Variable::declare (void) const
266abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
267abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	DE_ASSERT(!m_isArray);
268abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return de::toString(glu::declare(m_type, m_name)) + ";\n";
269abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
270abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
271abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskistd::string Variable::declareArray (const std::string& sizeExpr) const
272abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
273abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	DE_ASSERT(m_isArray);
274abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return de::toString(glu::declare(m_type, m_name)) + "[" + sizeExpr + "];\n";
275abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
276abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
277abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskistd::string Variable::glslTraverseBasicTypeArray (const int numArrayElements, const int indentationDepth, BasicTypeVisitFunc visit) const
278abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
279abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	DE_ASSERT(m_isArray);
280abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
281abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const bool			traverseAsArray	= numArrayElements >= 0;
282abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const std::string	traversedName	= m_name + (!traverseAsArray ? "[gl_InvocationID]" : "");
283abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const glu::VarType	type			= traverseAsArray ? glu::VarType(m_type, numArrayElements) : m_type;
284abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
285abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return glslTraverseBasicTypes(traversedName, type, 0, indentationDepth, visit);
286abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
287abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
288abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskistd::string Variable::glslTraverseBasicType (const int indentationDepth, BasicTypeVisitFunc visit) const
289abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
290abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	DE_ASSERT(!m_isArray);
291abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return glslTraverseBasicTypes(m_name, m_type, 0, indentationDepth, visit);
292abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
293abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
294abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiint Variable::numBasicSubobjectsInElementType (void) const
295abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
296abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return numBasicSubobjects(m_type);
297abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
298abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
299abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskistd::string Variable::basicSubobjectAtIndex (const int subobjectIndex, const int arraySize) const
300abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
301abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const glu::VarType	type		 = m_isArray ? glu::VarType(m_type, arraySize) : m_type;
302abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	int					currentIndex = 0;
303abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
304abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	for (glu::BasicTypeIterator basicIt = glu::BasicTypeIterator::begin(&type); basicIt != glu::BasicTypeIterator::end(&type); ++basicIt)
305abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
306abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		if (currentIndex == subobjectIndex)
307abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			return m_name + de::toString(glu::TypeAccessFormat(type, basicIt.getPath()));
308abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		++currentIndex;
309abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
310abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	DE_ASSERT(false);
311abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return DE_NULL;
312abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
313abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
314abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiclass IOBlock : public TopLevelObject
315abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
316abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskipublic:
317abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	struct Member
318abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
319abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		std::string		name;
320abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		glu::VarType	type;
321abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
322abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		Member (const std::string& n, const glu::VarType& t) : name(n), type(t) {}
323abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	};
324abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
325abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	IOBlock (const std::string& blockName, const std::string& interfaceName, const std::vector<Member>& members)
326abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		: m_blockName		(blockName)
327abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		, m_interfaceName	(interfaceName)
328abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		, m_members			(members)
329abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
330abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
331abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
332abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::string			name								(void) const { return m_interfaceName; }
333abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::string			declare								(void) const;
334abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::string			declareArray						(const std::string& arraySizeExpr) const;
335abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::string			glslTraverseBasicTypeArray			(const int numArrayElements, const int indentationDepth, BasicTypeVisitFunc) const;
336abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::string			glslTraverseBasicType				(const int indentationDepth, BasicTypeVisitFunc) const;
337abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	int					numBasicSubobjectsInElementType		(void) const;
338abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::string			basicSubobjectAtIndex				(const int index, const int arraySize) const;
339abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
340abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiprivate:
341abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::string			m_blockName;
342abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::string			m_interfaceName;
343abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::vector<Member>	m_members;
344abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
345abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
346abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskistd::string IOBlock::declare (void) const
347abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
348abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::ostringstream buf;
349abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
350abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	buf << m_blockName << "\n"
351abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		<< "{\n";
352abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
353abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	for (int i = 0; i < static_cast<int>(m_members.size()); ++i)
354abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		buf << "\t" << glu::declare(m_members[i].type, m_members[i].name) << ";\n";
355abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
356abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	buf << "} " << m_interfaceName << ";\n";
357abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return buf.str();
358abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
359abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
360abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskistd::string IOBlock::declareArray (const std::string& sizeExpr) const
361abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
362abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::ostringstream buf;
363abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
364abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	buf << m_blockName << "\n"
365abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		<< "{\n";
366abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
367abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	for (int i = 0; i < static_cast<int>(m_members.size()); ++i)
368abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		buf << "\t" << glu::declare(m_members[i].type, m_members[i].name) << ";\n";
369abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
370abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	buf << "} " << m_interfaceName << "[" << sizeExpr << "];\n";
371abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return buf.str();
372abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
373abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
374abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskistd::string IOBlock::glslTraverseBasicTypeArray (const int numArrayElements, const int indentationDepth, BasicTypeVisitFunc visit) const
375abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
376abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	if (numArrayElements >= 0)
377abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
378abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const std::string	indentation = std::string(indentationDepth, '\t');
379abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		std::ostringstream	result;
380abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
381abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		result << indentation << "for (int i0 = 0; i0 < " << numArrayElements << "; ++i0)\n"
382abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			   << indentation << "{\n";
383abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		for (int i = 0; i < static_cast<int>(m_members.size()); ++i)
384abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			result << glslTraverseBasicTypes(m_interfaceName + "[i0]." + m_members[i].name, m_members[i].type, 1, indentationDepth + 1, visit);
385abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		result << indentation + "}\n";
386abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		return result.str();
387abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
388abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	else
389abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
390abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		std::ostringstream result;
391abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		for (int i = 0; i < static_cast<int>(m_members.size()); ++i)
392abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			result << glslTraverseBasicTypes(m_interfaceName + "[gl_InvocationID]." + m_members[i].name, m_members[i].type, 0, indentationDepth, visit);
393abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		return result.str();
394abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
395abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
396abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
397abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskistd::string IOBlock::glslTraverseBasicType (const int indentationDepth, BasicTypeVisitFunc visit) const
398abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
399abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::ostringstream result;
400abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	for (int i = 0; i < static_cast<int>(m_members.size()); ++i)
401abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		result << glslTraverseBasicTypes(m_interfaceName + "." + m_members[i].name, m_members[i].type, 0, indentationDepth, visit);
402abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return result.str();
403abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
404abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
405abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiint IOBlock::numBasicSubobjectsInElementType (void) const
406abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
407abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	int result = 0;
408abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	for (int i = 0; i < static_cast<int>(m_members.size()); ++i)
409abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		result += numBasicSubobjects(m_members[i].type);
410abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return result;
411abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
412abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
413abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskistd::string IOBlock::basicSubobjectAtIndex (const int subobjectIndex, const int arraySize) const
414abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
415abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	int currentIndex = 0;
416abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	for (int arrayNdx = 0; arrayNdx < arraySize; ++arrayNdx)
417abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	for (int memberNdx = 0; memberNdx < static_cast<int>(m_members.size()); ++memberNdx)
418abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
419abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const glu::VarType& membType = m_members[memberNdx].type;
420abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		for (glu::BasicTypeIterator basicIt = glu::BasicTypeIterator::begin(&membType); basicIt != glu::BasicTypeIterator::end(&membType); ++basicIt)
421abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
422abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			if (currentIndex == subobjectIndex)
423abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				return m_interfaceName + "[" + de::toString(arrayNdx) + "]." + m_members[memberNdx].name + de::toString(glu::TypeAccessFormat(membType, basicIt.getPath()));
424abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			currentIndex++;
425abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
426abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
427abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	DE_ASSERT(false);
428abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return DE_NULL;
429abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
430abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
431abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiclass UserDefinedIOTest : public TestCase
432abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
433abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskipublic:
434abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski							UserDefinedIOTest	(tcu::TestContext& testCtx, const std::string& name, const std::string& description, const CaseDefinition caseDef);
435abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	void					initPrograms		(vk::SourceCollections& programCollection) const;
436abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	TestInstance*			createInstance		(Context& context) const;
437abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
438abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiprivate:
439abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const CaseDefinition						m_caseDef;
440abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::vector<glu::StructType>				m_structTypes;
441abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::vector<de::SharedPtr<TopLevelObject> >	m_tcsOutputs;
442abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::vector<de::SharedPtr<TopLevelObject> >	m_tesInputs;
443abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::string									m_tcsDeclarations;
444abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::string									m_tcsStatements;
445abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::string									m_tesDeclarations;
446abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::string									m_tesStatements;
447abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
448abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
449abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej JesionowskiUserDefinedIOTest::UserDefinedIOTest (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const CaseDefinition caseDef)
450abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	: TestCase	(testCtx, name, description)
451abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	, m_caseDef	(caseDef)
452abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
453abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const bool			isPerPatchIO				= m_caseDef.ioType == IO_TYPE_PER_PATCH				||
454abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski													  m_caseDef.ioType == IO_TYPE_PER_PATCH_ARRAY		||
455abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski													  m_caseDef.ioType == IO_TYPE_PER_PATCH_BLOCK		||
456abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski													  m_caseDef.ioType == IO_TYPE_PER_PATCH_BLOCK_ARRAY;
457abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
458abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const bool			isExplicitVertexArraySize	= m_caseDef.vertexIOArraySize == VERTEX_IO_ARRAY_SIZE_EXPLICIT_SHADER_BUILTIN ||
459abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski													  m_caseDef.vertexIOArraySize == VERTEX_IO_ARRAY_SIZE_EXPLICIT_SPEC_MIN;
460abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
461abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const std::string	vertexAttrArrayInputSize	= m_caseDef.vertexIOArraySize == VERTEX_IO_ARRAY_SIZE_IMPLICIT					? ""
462abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski													: m_caseDef.vertexIOArraySize == VERTEX_IO_ARRAY_SIZE_EXPLICIT_SHADER_BUILTIN	? "gl_MaxPatchVertices"
463abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski													: m_caseDef.vertexIOArraySize == VERTEX_IO_ARRAY_SIZE_EXPLICIT_SPEC_MIN			? de::toString(MAX_TESSELLATION_PATCH_SIZE)
464abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski													: DE_NULL;
465abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
466abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const char* const	maybePatch					= isPerPatchIO ? "patch " : "";
467abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const std::string	outMaybePatch				= std::string() + maybePatch + "out ";
468abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const std::string	inMaybePatch				= std::string() + maybePatch + "in ";
469abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const bool			useBlock					= m_caseDef.ioType == IO_TYPE_PER_VERTEX_BLOCK		||
470abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski													  m_caseDef.ioType == IO_TYPE_PER_PATCH_BLOCK		||
471abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski													  m_caseDef.ioType == IO_TYPE_PER_PATCH_BLOCK_ARRAY;
472abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const int			wrongNumElements			= -2;
473abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
474abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::ostringstream tcsDeclarations;
475abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::ostringstream tcsStatements;
476abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::ostringstream tesDeclarations;
477abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::ostringstream tesStatements;
478abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
479abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	// Indices 0 and 1 are taken, see initPrograms()
480abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	int tcsNextOutputLocation = 2;
481abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	int tesNextInputLocation  = 2;
482abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
483abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	m_structTypes.push_back(glu::StructType("S"));
484abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
485abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const glu::VarType	highpFloat		(glu::TYPE_FLOAT, glu::PRECISION_HIGHP);
486abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	glu::StructType&	structType		= m_structTypes.back();
487abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const glu::VarType	structVarType	(&structType);
488abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	bool				usedStruct		= false;
489abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
490abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	structType.addMember("x", glu::VarType(glu::TYPE_INT,		 glu::PRECISION_HIGHP));
491abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	structType.addMember("y", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP));
492abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
493abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	// It is illegal to have a structure containing an array as an output variable
494abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	if (useBlock)
495abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		structType.addMember("z", glu::VarType(highpFloat, 2));
496abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
497abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	if (useBlock)
498abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
499abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		std::vector<IOBlock::Member> blockMembers;
500abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
501abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		// use leaner block to make sure it is not larger than allowed (per-patch storage is very limited)
502abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const bool useLightweightBlock = (m_caseDef.ioType == IO_TYPE_PER_PATCH_BLOCK_ARRAY);
503abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
504abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		if (!useLightweightBlock)
505abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			blockMembers.push_back(IOBlock::Member("blockS",	structVarType));
506abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
507abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		blockMembers.push_back(IOBlock::Member("blockFa",	glu::VarType(highpFloat, 3)));
508abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		blockMembers.push_back(IOBlock::Member("blockSa",	glu::VarType(structVarType, 2)));
509abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		blockMembers.push_back(IOBlock::Member("blockF",	highpFloat));
510abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
511abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		m_tcsOutputs.push_back	(de::SharedPtr<TopLevelObject>(new IOBlock("TheBlock", "tcBlock", blockMembers)));
512abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		m_tesInputs.push_back	(de::SharedPtr<TopLevelObject>(new IOBlock("TheBlock", "teBlock", blockMembers)));
513abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
514abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		usedStruct = true;
515abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
516abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	else
517abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
518abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const Variable var0("in_te_s", structVarType,	m_caseDef.ioType != IO_TYPE_PER_PATCH);
519abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const Variable var1("in_te_f", highpFloat,		m_caseDef.ioType != IO_TYPE_PER_PATCH);
520abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
521abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		if (m_caseDef.ioType != IO_TYPE_PER_PATCH_ARRAY)
522abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
523abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			// Arrays of structures are disallowed, add struct cases only if not arrayed variable
524abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			m_tcsOutputs.push_back	(de::SharedPtr<TopLevelObject>(new Variable(var0)));
525abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			m_tesInputs.push_back	(de::SharedPtr<TopLevelObject>(new Variable(var0)));
526abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
527abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			usedStruct = true;
528abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
529abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
530abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		m_tcsOutputs.push_back	(de::SharedPtr<TopLevelObject>(new Variable(var1)));
531abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		m_tesInputs.push_back	(de::SharedPtr<TopLevelObject>(new Variable(var1)));
532abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
533abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
534abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	if (usedStruct)
535abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		tcsDeclarations << de::toString(glu::declare(structType)) + ";\n";
536abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
537abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	tcsStatements << "\t{\n"
538abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				  << "\t\thighp float v = 1.3;\n";
539abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
540abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	for (int tcsOutputNdx = 0; tcsOutputNdx < static_cast<int>(m_tcsOutputs.size()); ++tcsOutputNdx)
541abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
542abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const TopLevelObject&	output		= *m_tcsOutputs[tcsOutputNdx];
543abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const int				numElements	= !isPerPatchIO										? -1	//!< \note -1 means indexing with gl_InstanceID
544abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski											: m_caseDef.ioType == IO_TYPE_PER_PATCH				? 1
545abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski											: m_caseDef.ioType == IO_TYPE_PER_PATCH_ARRAY		? NUM_PER_PATCH_ARRAY_ELEMS
546abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski											: m_caseDef.ioType == IO_TYPE_PER_PATCH_BLOCK		? 1
547abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski											: m_caseDef.ioType == IO_TYPE_PER_PATCH_BLOCK_ARRAY	? NUM_PER_PATCH_BLOCKS
548abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski											: wrongNumElements;
549abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const bool				isArray		= (numElements != 1);
550abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
551abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		DE_ASSERT(numElements != wrongNumElements);
552abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
553abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		// \note: TCS output arrays are always implicitly-sized
554abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		tcsDeclarations << "layout(location = " << tcsNextOutputLocation << ") ";
555abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		if (isArray)
556abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			tcsDeclarations << outMaybePatch << output.declareArray(m_caseDef.ioType == IO_TYPE_PER_PATCH_ARRAY			? de::toString(NUM_PER_PATCH_ARRAY_ELEMS)
557abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski																  : m_caseDef.ioType == IO_TYPE_PER_PATCH_BLOCK_ARRAY	? de::toString(NUM_PER_PATCH_BLOCKS)
558abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski																  : "");
559abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		else
560abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			tcsDeclarations << outMaybePatch << output.declare();
561abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
562abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		tcsNextOutputLocation += output.numBasicSubobjectsInElementType();
563abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
564abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		if (!isPerPatchIO)
5656e5ef4c51158771e71f72c70980b4dbd78f011f2Pyry Haulos			tcsStatements << "\t\tv += float(gl_InvocationID)*" << de::floatToString(0.4f * (float)output.numBasicSubobjectsInElementType(), 1) << ";\n";
566abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
567abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		tcsStatements << "\n\t\t// Assign values to output " << output.name() << "\n";
568abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		if (isArray)
569abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			tcsStatements << output.glslTraverseBasicTypeArray(numElements, 2, glslAssignBasicTypeObject);
570abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		else
571abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			tcsStatements << output.glslTraverseBasicType(2, glslAssignBasicTypeObject);
572abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
573abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		if (!isPerPatchIO)
5746e5ef4c51158771e71f72c70980b4dbd78f011f2Pyry Haulos			tcsStatements << "\t\tv += float(" << de::toString(NUM_OUTPUT_VERTICES) << "-gl_InvocationID-1)*" << de::floatToString(0.4f * (float)output.numBasicSubobjectsInElementType(), 1) << ";\n";
575abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
576abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	tcsStatements << "\t}\n";
577abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
578abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	tcsDeclarations << "\n"
579abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					<< "layout(location = 0) in " + Variable("in_tc_attr", highpFloat, true).declareArray(vertexAttrArrayInputSize);
580abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
581abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	if (usedStruct)
582abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		tesDeclarations << de::toString(glu::declare(structType)) << ";\n";
583abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
584abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	tesStatements << "\tbool allOk = true;\n"
585abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				  << "\thighp uint firstFailedInputIndex = 0u;\n"
586abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				  << "\t{\n"
587abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				  << "\t\thighp float v = 1.3;\n";
588abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
589abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	for (int tesInputNdx = 0; tesInputNdx < static_cast<int>(m_tesInputs.size()); ++tesInputNdx)
590abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
591abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const TopLevelObject&	input		= *m_tesInputs[tesInputNdx];
592abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const int				numElements	= !isPerPatchIO										? NUM_OUTPUT_VERTICES
593abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski											: m_caseDef.ioType == IO_TYPE_PER_PATCH				? 1
594abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski											: m_caseDef.ioType == IO_TYPE_PER_PATCH_BLOCK		? 1
595abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski											: m_caseDef.ioType == IO_TYPE_PER_PATCH_ARRAY		? NUM_PER_PATCH_ARRAY_ELEMS
596abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski											: m_caseDef.ioType == IO_TYPE_PER_PATCH_BLOCK_ARRAY	? NUM_PER_PATCH_BLOCKS
597abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski											: wrongNumElements;
598abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const bool				isArray		= (numElements != 1);
599abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
600abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		DE_ASSERT(numElements != wrongNumElements);
601abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
602abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		tesDeclarations << "layout(location = " << tesNextInputLocation << ") ";
603abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		if (isArray)
604abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			tesDeclarations << inMaybePatch << input.declareArray(m_caseDef.ioType == IO_TYPE_PER_PATCH_ARRAY		? de::toString(NUM_PER_PATCH_ARRAY_ELEMS)
605abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski																: m_caseDef.ioType == IO_TYPE_PER_PATCH_BLOCK_ARRAY	? de::toString(NUM_PER_PATCH_BLOCKS)
606abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski																: isExplicitVertexArraySize							? de::toString(vertexAttrArrayInputSize)
607abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski																: "");
608abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		else
609abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			tesDeclarations << inMaybePatch + input.declare();
610abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
611abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		tesNextInputLocation += input.numBasicSubobjectsInElementType();
612abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
613abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		tesStatements << "\n\t\t// Check values in input " << input.name() << "\n";
614abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		if (isArray)
615abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			tesStatements << input.glslTraverseBasicTypeArray(numElements, 2, glslCheckBasicTypeObject);
616abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		else
617abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			tesStatements << input.glslTraverseBasicType(2, glslCheckBasicTypeObject);
618abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
619abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	tesStatements << "\t}\n";
620abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
621abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	m_tcsDeclarations = tcsDeclarations.str();
622abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	m_tcsStatements   = tcsStatements.str();
623abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	m_tesDeclarations = tesDeclarations.str();
624abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	m_tesStatements   = tesStatements.str();
625abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
626abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
627abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskivoid UserDefinedIOTest::initPrograms (vk::SourceCollections& programCollection) const
628abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
629abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	// Vertex shader
630abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
631abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		std::ostringstream src;
632abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
633abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
634abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "layout(location = 0) in  highp float in_v_attr;\n"
635abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "layout(location = 0) out highp float in_tc_attr;\n"
636abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
637abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "void main (void)\n"
638abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "{\n"
639abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "	in_tc_attr = in_v_attr;\n"
640abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "}\n";
641abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
642abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
643abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
644abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
645abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	// Tessellation control shader
646abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
647abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		std::ostringstream src;
648abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
649abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "#extension GL_EXT_tessellation_shader : require\n"
650abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
651abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "layout(vertices = " << NUM_OUTPUT_VERTICES << ") out;\n"
652abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
653abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "layout(location = 0) patch out highp vec2 in_te_positionScale;\n"
654abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "layout(location = 1) patch out highp vec2 in_te_positionOffset;\n"
655abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
656abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< m_tcsDeclarations
657abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
658abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "void main (void)\n"
659abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "{\n"
660abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< m_tcsStatements
661abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
662abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "	gl_TessLevelInner[0] = in_tc_attr[0];\n"
663abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "	gl_TessLevelInner[1] = in_tc_attr[1];\n"
664abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
665abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "	gl_TessLevelOuter[0] = in_tc_attr[2];\n"
666abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "	gl_TessLevelOuter[1] = in_tc_attr[3];\n"
667abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "	gl_TessLevelOuter[2] = in_tc_attr[4];\n"
668abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "	gl_TessLevelOuter[3] = in_tc_attr[5];\n"
669abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
670abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "	in_te_positionScale  = vec2(in_tc_attr[6], in_tc_attr[7]);\n"
671abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "	in_te_positionOffset = vec2(in_tc_attr[8], in_tc_attr[9]);\n"
672abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "}\n";
673abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
674abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
675abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
676abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
677abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	// Tessellation evaluation shader
678abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
679abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		std::ostringstream src;
680abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
681abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "#extension GL_EXT_tessellation_shader : require\n"
682abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
683abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "layout(" << getTessPrimitiveTypeShaderName(m_caseDef.primitiveType) << ") in;\n"
684abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
685abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "layout(location = 0) patch in highp vec2 in_te_positionScale;\n"
686abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "layout(location = 1) patch in highp vec2 in_te_positionOffset;\n"
687abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
688abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< m_tesDeclarations
689abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
690abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "layout(location = 0) out highp vec4 in_f_color;\n"
691abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
692abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "// Will contain the index of the first incorrect input,\n"
693abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "// or the number of inputs if all are correct\n"
694abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "layout (set = 0, binding = 0, std430) coherent restrict buffer Output {\n"
695abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "    int  numInvocations;\n"
696abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "    uint firstFailedInputIndex[];\n"
697abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "} sb_out;\n"
698abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
699abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "bool compare_int   (int   a, int   b) { return a == b; }\n"
700abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "bool compare_float (float a, float b) { return abs(a - b) < 0.01f; }\n"
701abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "bool compare_vec4  (vec4  a, vec4  b) { return all(lessThan(abs(a - b), vec4(0.01f))); }\n"
702abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
703abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "void main (void)\n"
704abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "{\n"
705abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< m_tesStatements
706abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
707abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "	gl_Position = vec4(gl_TessCoord.xy*in_te_positionScale + in_te_positionOffset, 0.0, 1.0);\n"
708abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "	in_f_color  = allOk ? vec4(0.0, 1.0, 0.0, 1.0)\n"
709abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "	                    : vec4(1.0, 0.0, 0.0, 1.0);\n"
710abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
711abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "	int index = atomicAdd(sb_out.numInvocations, 1);\n"
712abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "	sb_out.firstFailedInputIndex[index] = firstFailedInputIndex;\n"
713abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "}\n";
714abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
715abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
716abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
717abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
718abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	// Fragment shader
719abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
720abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		std::ostringstream src;
721abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
722abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
723abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "layout(location = 0) in  highp   vec4 in_f_color;\n"
724abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "layout(location = 0) out mediump vec4 o_color;\n"
725abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
726abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "void main (void)\n"
727abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "{\n"
728abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "    o_color = in_f_color;\n"
729abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "}\n";
730abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
731abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
732abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
733abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
734abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
735abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiclass UserDefinedIOTestInstance : public TestInstance
736abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
737abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskipublic:
738abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski							UserDefinedIOTestInstance	(Context&											context,
739abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski														 const CaseDefinition								caseDef,
740abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski														 const std::vector<de::SharedPtr<TopLevelObject> >&	tesInputs);
741abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	tcu::TestStatus			iterate						(void);
742abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
743abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiprivate:
744abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const CaseDefinition								m_caseDef;
745abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const std::vector<de::SharedPtr<TopLevelObject> >	m_tesInputs;
746abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
747abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
748abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej JesionowskiUserDefinedIOTestInstance::UserDefinedIOTestInstance (Context& context, const CaseDefinition caseDef, const std::vector<de::SharedPtr<TopLevelObject> >& tesInputs)
749abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	: TestInstance		(context)
750abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	, m_caseDef			(caseDef)
751abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	, m_tesInputs		(tesInputs)
752abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
753abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
754abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
755abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskitcu::TestStatus UserDefinedIOTestInstance::iterate (void)
756abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
757abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	requireFeatures(m_context.getInstanceInterface(), m_context.getPhysicalDevice(), FEATURE_TESSELLATION_SHADER | FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS);
758abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
759abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const DeviceInterface&	vk					= m_context.getDeviceInterface();
760abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const VkDevice			device				= m_context.getDevice();
761abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const VkQueue			queue				= m_context.getUniversalQueue();
762abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const deUint32			queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
763abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	Allocator&				allocator			= m_context.getDefaultAllocator();
764abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
765abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const int				numAttributes				= NUM_TESS_LEVELS + 2 + 2;
766abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	static const float		attributes[numAttributes]	= { /* inner */ 3.0f, 4.0f, /* outer */ 5.0f, 6.0f, 7.0f, 8.0f, /* pos. scale */ 1.2f, 1.3f, /* pos. offset */ -0.3f, -0.4f };
767abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const int				refNumVertices				= referenceVertexCount(m_caseDef.primitiveType, SPACINGMODE_EQUAL, false, &attributes[0], &attributes[2]);
768abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const int				refNumUniqueVertices		= referenceVertexCount(m_caseDef.primitiveType, SPACINGMODE_EQUAL, true, &attributes[0], &attributes[2]);
769abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
770abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	// Vertex input attributes buffer: to pass tessellation levels
771abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
772abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const VkFormat     vertexFormat				= VK_FORMAT_R32_SFLOAT;
773abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const deUint32     vertexStride				= tcu::getPixelSize(mapVkFormat(vertexFormat));
774abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const VkDeviceSize vertexDataSizeBytes		= numAttributes * vertexStride;
775abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Buffer       vertexBuffer				(vk, device, allocator, makeBufferCreateInfo(vertexDataSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible);
776abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
777abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
778abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const Allocation& alloc = vertexBuffer.getAllocation();
779abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		deMemcpy(alloc.getHostPtr(), &attributes[0], static_cast<std::size_t>(vertexDataSizeBytes));
780abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), vertexDataSizeBytes);
781abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
782abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
783abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	// Output buffer: number of invocations and verification indices
784abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
785abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const int		   resultBufferMaxVertices	= refNumVertices;
786abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const VkDeviceSize resultBufferSizeBytes    = sizeof(deInt32) + resultBufferMaxVertices * sizeof(deUint32);
787abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Buffer       resultBuffer             (vk, device, allocator, makeBufferCreateInfo(resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible);
788abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
789abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
790abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const Allocation& alloc = resultBuffer.getAllocation();
791abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(resultBufferSizeBytes));
792abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), resultBufferSizeBytes);
793abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
794abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
795abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	// Color attachment
796abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
797abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const tcu::IVec2			  renderSize				 = tcu::IVec2(RENDER_SIZE, RENDER_SIZE);
798abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const VkFormat				  colorFormat				 = VK_FORMAT_R8G8B8A8_UNORM;
799abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const VkImageSubresourceRange colorImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
800abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Image					  colorAttachmentImage		 (vk, device, allocator,
801abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski															 makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 1u),
802abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski															 MemoryRequirement::Any);
803abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
804abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	// Color output buffer: image will be copied here for verification
805abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
806abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const VkDeviceSize	colorBufferSizeBytes	= renderSize.x()*renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat));
807abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Buffer		colorBuffer				(vk, device, allocator, makeBufferCreateInfo(colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible);
808abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
809abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	// Descriptors
810abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
811abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
812abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
813abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.build(vk, device));
814abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
815abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
816abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
817abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
818abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
819abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Unique<VkDescriptorSet> descriptorSet    (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
820abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const VkDescriptorBufferInfo  resultBufferInfo = makeDescriptorBufferInfo(resultBuffer.get(), 0ull, resultBufferSizeBytes);
821abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
822abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	DescriptorSetUpdateBuilder()
823abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferInfo)
824abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.update(vk, device);
825abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
826abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	// Pipeline
827abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
828abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Unique<VkImageView>      colorAttachmentView(makeImageView     (vk, device, *colorAttachmentImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorImageSubresourceRange));
829abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Unique<VkRenderPass>     renderPass         (makeRenderPass    (vk, device, colorFormat));
830abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Unique<VkFramebuffer>    framebuffer        (makeFramebuffer   (vk, device, *renderPass, *colorAttachmentView, renderSize.x(), renderSize.y(), 1u));
831abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Unique<VkPipelineLayout> pipelineLayout     (makePipelineLayout(vk, device, *descriptorSetLayout));
832abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Unique<VkCommandPool>    cmdPool            (makeCommandPool   (vk, device, queueFamilyIndex));
833abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Unique<VkCommandBuffer>  cmdBuffer          (makeCommandBuffer (vk, device, *cmdPool));
834abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
835abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Unique<VkPipeline> pipeline(GraphicsPipelineBuilder()
836abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.setRenderSize                (renderSize)
837abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.setPatchControlPoints        (numAttributes)
838abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.setVertexInputSingleAttribute(vertexFormat, vertexStride)
839abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.setShader                    (vk, device, VK_SHADER_STAGE_VERTEX_BIT,					m_context.getBinaryCollection().get("vert"), DE_NULL)
840abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.setShader                    (vk, device, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,	m_context.getBinaryCollection().get("tesc"), DE_NULL)
841abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.setShader                    (vk, device, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, m_context.getBinaryCollection().get("tese"), DE_NULL)
842abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.setShader                    (vk, device, VK_SHADER_STAGE_FRAGMENT_BIT,				m_context.getBinaryCollection().get("frag"), DE_NULL)
843abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.build                        (vk, device, *pipelineLayout, *renderPass));
844abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
845abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	// Begin draw
846abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
847abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	beginCommandBuffer(vk, *cmdBuffer);
848abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
849abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	// Change color attachment image layout
850abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
851abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const VkImageMemoryBarrier colorAttachmentLayoutBarrier = makeImageMemoryBarrier(
852abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			(VkAccessFlags)0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
853abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
854abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			*colorAttachmentImage, colorImageSubresourceRange);
855abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
856abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u,
857abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			0u, DE_NULL, 0u, DE_NULL, 1u, &colorAttachmentLayoutBarrier);
858abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
859abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
860abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
861abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const VkRect2D renderArea = {
862abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			makeOffset2D(0, 0),
863abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			makeExtent2D(renderSize.x(), renderSize.y()),
864abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		};
865abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
866abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
867abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor);
868abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
869abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
870abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
871abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
872abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
873abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const VkDeviceSize vertexBufferOffset = 0ull;
874abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
875abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
876abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
877abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	vk.cmdDraw(*cmdBuffer, numAttributes, 1u, 0u, 0u);
878abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	endRenderPass(vk, *cmdBuffer);
879abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
880abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	// Copy render result to a host-visible buffer
881abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
882abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const VkImageMemoryBarrier colorAttachmentPreCopyBarrier = makeImageMemoryBarrier(
883abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
884abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
885abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			*colorAttachmentImage, colorImageSubresourceRange);
886abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
887abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
888abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			0u, DE_NULL, 0u, DE_NULL, 1u, &colorAttachmentPreCopyBarrier);
889abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
890abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
8911d185cb7ef57f375fcdf78cb50a7b4b5e3e4923ePyry Haulos		const VkBufferImageCopy copyRegion = makeBufferImageCopy(makeExtent3D(renderSize.x(), renderSize.y(), 1), makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u));
892abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		vk.cmdCopyImageToBuffer(*cmdBuffer, *colorAttachmentImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &copyRegion);
893abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
894abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
895abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const VkBufferMemoryBarrier postCopyBarrier = makeBufferMemoryBarrier(
896abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *colorBuffer, 0ull, colorBufferSizeBytes);
897abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
898abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
899abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			0u, DE_NULL, 1u, &postCopyBarrier, 0u, DE_NULL);
900abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
901abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
902abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	endCommandBuffer(vk, *cmdBuffer);
903abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
904abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
905abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	// Verification
906abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
907abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	bool isImageCompareOK = false;
908abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
909abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const Allocation& colorBufferAlloc = colorBuffer.getAllocation();
910abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		invalidateMappedMemoryRange(vk, device, colorBufferAlloc.getMemory(), colorBufferAlloc.getOffset(), colorBufferSizeBytes);
911abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
912abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		// Load reference image
913abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		tcu::TextureLevel referenceImage;
914abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		tcu::ImageIO::loadPNG(referenceImage, m_context.getTestContext().getArchive(), m_caseDef.referenceImagePath.c_str());
915abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
916abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		// Verify case result
917abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const tcu::ConstPixelBufferAccess resultImageAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAlloc.getHostPtr());
918abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		isImageCompareOK = tcu::fuzzyCompare(m_context.getTestContext().getLog(), "ImageComparison", "Image Comparison",
919abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski											 referenceImage.getAccess(), resultImageAccess, 0.02f, tcu::COMPARE_LOG_RESULT);
920abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
921abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
922abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const Allocation& resultAlloc = resultBuffer.getAllocation();
923abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		invalidateMappedMemoryRange(vk, device, resultAlloc.getMemory(), resultAlloc.getOffset(), resultBufferSizeBytes);
924abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
925abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const deInt32			numVertices = *static_cast<deInt32*>(resultAlloc.getHostPtr());
926abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const deUint32* const	vertices    = reinterpret_cast<deUint32*>(static_cast<deUint8*>(resultAlloc.getHostPtr()) + sizeof(deInt32));
927abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
928abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		// If this fails then we didn't read all vertices from shader and test must be changed to allow more.
929abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		DE_ASSERT(numVertices <= refNumVertices);
930abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
931abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		if (numVertices < refNumUniqueVertices)
932abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
933abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			m_context.getTestContext().getLog()
934abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< tcu::TestLog::Message << "Failure: got " << numVertices << " vertices, but expected at least " << refNumUniqueVertices << tcu::TestLog::EndMessage;
935abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
936abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			return tcu::TestStatus::fail("Wrong number of vertices");
937abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
938abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		else
939abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
940abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			tcu::TestLog&	log					= m_context.getTestContext().getLog();
941abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			const int		topLevelArraySize	= (m_caseDef.ioType == IO_TYPE_PER_PATCH			? 1
942abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski												: m_caseDef.ioType == IO_TYPE_PER_PATCH_ARRAY		? NUM_PER_PATCH_ARRAY_ELEMS
943abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski												: m_caseDef.ioType == IO_TYPE_PER_PATCH_BLOCK		? 1
944abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski												: m_caseDef.ioType == IO_TYPE_PER_PATCH_BLOCK_ARRAY	? NUM_PER_PATCH_BLOCKS
945abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski												: NUM_OUTPUT_VERTICES);
946abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			const deUint32	numTEInputs			= numBasicSubobjectsInElementType(m_tesInputs) * topLevelArraySize;
947abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
948abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			for (int vertexNdx = 0; vertexNdx < numVertices; ++vertexNdx)
949abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				if (vertices[vertexNdx] > numTEInputs)
950abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				{
951abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					log << tcu::TestLog::Message
952abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						<< "Failure: out_te_firstFailedInputIndex has value " << vertices[vertexNdx]
953abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						<< ", but should be in range [0, " << numTEInputs << "]" << tcu::TestLog::EndMessage;
954abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
955abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					return tcu::TestStatus::fail("Invalid values returned from shader");
956abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				}
957abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				else if (vertices[vertexNdx] != numTEInputs)
958abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				{
959abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					log << tcu::TestLog::Message << "Failure: in tessellation evaluation shader, check for input "
960abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						<< basicSubobjectAtIndex(vertices[vertexNdx], m_tesInputs, topLevelArraySize) << " failed" << tcu::TestLog::EndMessage;
961abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
962abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					return tcu::TestStatus::fail("Invalid input value in tessellation evaluation shader");
963abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				}
964abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
965abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
966abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return (isImageCompareOK ? tcu::TestStatus::pass("OK") : tcu::TestStatus::fail("Image comparison failed"));
967abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
968abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
969abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej JesionowskiTestInstance* UserDefinedIOTest::createInstance (Context& context) const
970abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
971abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return new UserDefinedIOTestInstance(context, m_caseDef, m_tesInputs);
972abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
973abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
974abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski} // anonymous
975abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
976abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski//! These tests correspond roughly to dEQP-GLES31.functional.tessellation.user_defined_io.*
977abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski//! Original GLES test queried maxTessellationPatchSize, but this can't be done at the stage the shader source is prepared.
978abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski//! Instead, we use minimum supported value.
979abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski//! Negative tests weren't ported because vktShaderLibrary doesn't support tests that are expected to fail shader compilation.
980abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskitcu::TestCaseGroup* createUserDefinedIOTests (tcu::TestContext& testCtx)
981abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
982abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "user_defined_io", "Test non-built-in per-patch and per-vertex inputs and outputs"));
983abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
984abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	static const struct
985abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
986abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const char*	name;
987abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const char*	description;
988abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		IOType		ioType;
989abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	} ioCases[] =
990abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
991abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{ "per_patch",					"Per-patch TCS outputs",					IO_TYPE_PER_PATCH				},
992abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{ "per_patch_array",			"Per-patch array TCS outputs",				IO_TYPE_PER_PATCH_ARRAY			},
993abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{ "per_patch_block",			"Per-patch TCS outputs in IO block",		IO_TYPE_PER_PATCH_BLOCK			},
994abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{ "per_patch_block_array",		"Per-patch TCS outputs in IO block array",	IO_TYPE_PER_PATCH_BLOCK_ARRAY	},
995abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{ "per_vertex",					"Per-vertex TCS outputs",					IO_TYPE_PER_VERTEX				},
996abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{ "per_vertex_block",			"Per-vertex TCS outputs in IO block",		IO_TYPE_PER_VERTEX_BLOCK		},
997abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	};
998abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
999abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	static const struct
1000abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1001abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const char*			name;
1002abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		VertexIOArraySize	vertexIOArraySize;
1003abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	} vertexArraySizeCases[] =
1004abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1005abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{ "vertex_io_array_size_implicit",			VERTEX_IO_ARRAY_SIZE_IMPLICIT					},
1006abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{ "vertex_io_array_size_shader_builtin",	VERTEX_IO_ARRAY_SIZE_EXPLICIT_SHADER_BUILTIN	},
1007abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{ "vertex_io_array_size_spec_min",			VERTEX_IO_ARRAY_SIZE_EXPLICIT_SPEC_MIN			},
1008abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	};
1009abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1010abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(ioCases); ++caseNdx)
1011abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1012abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		de::MovePtr<tcu::TestCaseGroup> ioTypeGroup (new tcu::TestCaseGroup(testCtx, ioCases[caseNdx].name, ioCases[caseNdx].description));
1013abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		for (int arrayCaseNdx = 0; arrayCaseNdx < DE_LENGTH_OF_ARRAY(vertexArraySizeCases); ++arrayCaseNdx)
1014abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
1015abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			de::MovePtr<tcu::TestCaseGroup> vertexArraySizeGroup (new tcu::TestCaseGroup(testCtx, vertexArraySizeCases[arrayCaseNdx].name, ""));
1016abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			for (int primitiveTypeNdx = 0; primitiveTypeNdx < TESSPRIMITIVETYPE_LAST; ++primitiveTypeNdx)
1017abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			{
1018abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				const TessPrimitiveType primitiveType = static_cast<TessPrimitiveType>(primitiveTypeNdx);
1019abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				const std::string		primitiveName = getTessPrimitiveTypeShaderName(primitiveType);
1020abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				const CaseDefinition	caseDef		  = { primitiveType, ioCases[caseNdx].ioType, vertexArraySizeCases[arrayCaseNdx].vertexIOArraySize,
1021abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski														  std::string() + "vulkan/data/tessellation/user_defined_io_" + primitiveName + "_ref.png" };
1022abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1023abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				vertexArraySizeGroup->addChild(new UserDefinedIOTest(testCtx, primitiveName, "", caseDef));
1024abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			}
1025abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			ioTypeGroup->addChild(vertexArraySizeGroup.release());
1026abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
1027abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		group->addChild(ioTypeGroup.release());
1028abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
1029abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1030abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return group.release();
1031abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
1032abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1033abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski} // tessellation
1034abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski} // vkt
1035