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 Invariance Tests
23abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski *//*--------------------------------------------------------------------*/
24abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
25abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski#include "vktTessellationInvarianceTests.hpp"
26abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski#include "vktTestCaseUtil.hpp"
27abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski#include "vktTessellationUtil.hpp"
28abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
29abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski#include "tcuTestLog.hpp"
30abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski#include "tcuVectorUtil.hpp"
31abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
32abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski#include "vkDefs.hpp"
33abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski#include "vkQueryUtil.hpp"
34abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski#include "vkBuilderUtil.hpp"
35abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski#include "vkImageUtil.hpp"
36abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski#include "vkTypeUtil.hpp"
37abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
38abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski#include "deUniquePtr.hpp"
39abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski#include "deStringUtil.hpp"
40abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski#include "deRandom.hpp"
41abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
42abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski#include <string>
43abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski#include <vector>
44abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski#include <set>
45abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
46abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskinamespace vkt
47abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
48abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskinamespace tessellation
49abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
50abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
51abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiusing namespace vk;
52abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
53abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskinamespace
54abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
55abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
56abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskienum Constants
57abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
58abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	NUM_TESS_LEVELS = 6,  // two inner and four outer levels
59abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
60abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
61abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskienum WindingUsage
62abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
63abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	WINDING_USAGE_CCW = 0,
64abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	WINDING_USAGE_CW,
65abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	WINDING_USAGE_VARY,
66abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
67abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	WINDING_USAGE_LAST,
68abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
69abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
70abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiinline WindingUsage getWindingUsage (const Winding winding)
71abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
72abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const WindingUsage usage = winding == WINDING_CCW ? WINDING_USAGE_CCW :
73abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski							   winding == WINDING_CW  ? WINDING_USAGE_CW  : WINDING_USAGE_LAST;
74abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	DE_ASSERT(usage !=  WINDING_USAGE_LAST);
75abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return usage;
76abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
77abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
78abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskistd::vector<Winding> getWindingCases (const WindingUsage windingUsage)
79abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
80abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::vector<Winding> cases;
81abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	switch (windingUsage)
82abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
83abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		case WINDING_USAGE_CCW:
84abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			cases.push_back(WINDING_CCW);
85abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			break;
86abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		case WINDING_USAGE_CW:
87abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			cases.push_back(WINDING_CW);
88abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			break;
89abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		case WINDING_USAGE_VARY:
90abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			cases.push_back(WINDING_CCW);
91abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			cases.push_back(WINDING_CW);
92abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			break;
93abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		default:
94abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			DE_ASSERT(false);
95abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			break;
96abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
97abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return cases;
98abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
99abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
100abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskienum PointModeUsage
101abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
102abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	POINT_MODE_USAGE_DONT_USE = 0,
103abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	POINT_MODE_USAGE_USE,
104abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	POINT_MODE_USAGE_VARY,
105abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
106abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	POINT_MODE_USAGE_LAST,
107abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
108abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
109abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiinline PointModeUsage getPointModeUsage (const bool usePointMode)
110abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
111abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return usePointMode ? POINT_MODE_USAGE_USE : POINT_MODE_USAGE_DONT_USE;
112abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
113abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
114abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskistd::vector<bool> getUsePointModeCases (const PointModeUsage pointModeUsage)
115abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
116abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::vector<bool> cases;
117abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	switch (pointModeUsage)
118abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
119abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		case POINT_MODE_USAGE_DONT_USE:
120abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			cases.push_back(false);
121abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			break;
122abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		case POINT_MODE_USAGE_USE:
123abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			cases.push_back(true);
124abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			break;
125abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		case POINT_MODE_USAGE_VARY:
126abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			cases.push_back(false);
127abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			cases.push_back(true);
128abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			break;
129abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		default:
130abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			DE_ASSERT(false);
131abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			break;
132abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
133abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return cases;
134abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
135abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
136abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski//! Data captured in the shader per output primitive (in geometry stage).
137abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskistruct PerPrimitive
138abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
139abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	deInt32		patchPrimitiveID;	//!< gl_PrimitiveID in tessellation evaluation shader
140abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	deInt32		primitiveID;		//!< ID of an output primitive in geometry shader (user-defined)
141abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
142abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	deInt32		unused_padding[2];
143abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
144abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	tcu::Vec4	tessCoord[3];		//!< 3 coords for triangles/quads, 2 for isolines, 1 for point mode. Vec4 due to alignment.
145abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
146abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
147abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskitypedef std::vector<PerPrimitive> PerPrimitiveVec;
148abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
149abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiinline bool byPatchPrimitiveID (const PerPrimitive& a, const PerPrimitive& b)
150abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
151abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return a.patchPrimitiveID < b.patchPrimitiveID;
152abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
153abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
154abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiinline std::string getProgramName (const std::string& baseName, const Winding winding, const bool usePointMode)
155abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
156abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::ostringstream str;
157abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	str << baseName << "_" << getWindingShaderName(winding) << (usePointMode ? "_point_mode" : "");
158abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return str.str();
159abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
160abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
161abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiinline std::string getProgramName (const std::string& baseName, const bool usePointMode)
162abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
163abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::ostringstream str;
164abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	str << baseName << (usePointMode ? "_point_mode" : "");
165abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return str.str();
166abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
167abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
168abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiinline std::string getProgramDescription (const Winding winding, const bool usePointMode)
169abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
170abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::ostringstream str;
171abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	str << "winding mode " << getWindingShaderName(winding) << ", " << (usePointMode ? "" : "don't ") << "use point mode";
172abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return str.str();
173abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
174abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
175abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskitemplate <typename T, int N>
176abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskistd::vector<T> arrayToVector (const T (&arr)[N])
177abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
178abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return std::vector<T>(DE_ARRAY_BEGIN(arr), DE_ARRAY_END(arr));
179abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
180abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
181abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskitemplate <typename T, int N>
182abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej JesionowskiT arrayMax (const T (&arr)[N])
183abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
184abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return *std::max_element(DE_ARRAY_BEGIN(arr), DE_ARRAY_END(arr));
185abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
186abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
187abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskitemplate <int Size>
188abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiinline tcu::Vector<bool, Size> singleTrueMask (int index)
189abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
190abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	DE_ASSERT(de::inBounds(index, 0, Size));
191abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	tcu::Vector<bool, Size> result;
192abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	result[index] = true;
193abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return result;
194abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
195abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
196abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskitemplate <typename ContainerT, typename T>
197abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiinline bool contains (const ContainerT& c, const T& key)
198abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
199abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return c.find(key) != c.end();
200abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
201abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
202abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskitemplate <typename SeqT, int Size, typename Pred>
203abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiclass LexCompare
204abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
205abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskipublic:
206abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	LexCompare (void) : m_pred(Pred()) {}
207abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
208abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	bool operator() (const SeqT& a, const SeqT& b) const
209abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
210abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		for (int i = 0; i < Size; ++i)
211abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
212abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			if (m_pred(a[i], b[i]))
213abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				return true;
214abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			if (m_pred(b[i], a[i]))
215abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				return false;
216abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
217abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		return false;
218abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
219abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
220abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiprivate:
221abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	Pred m_pred;
222abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
223abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
224abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskitemplate <int Size>
225abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiclass VecLexLessThan : public LexCompare<tcu::Vector<float, Size>, Size, std::less<float> >
226abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
227abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
228abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
229abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski//! Add default programs for invariance tests.
230abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski//! Creates multiple shader programs for combinations of winding and point mode.
231abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski//! mirrorCoords - special mode where some tessellation coordinates are mirrored in tessellation evaluation shader.
232abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski//!                This is used by symmetric outer edge test.
233abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskivoid addDefaultPrograms (vk::SourceCollections&  programCollection,
234abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						 const TessPrimitiveType primitiveType,
235abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						 const SpacingMode       spacingMode,
236abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						 const WindingUsage      windingUsage,
237abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						 const PointModeUsage    pointModeUsage,
238abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						 const bool				 mirrorCoords = false)
239abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
240abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	// Vertex shader
241abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
242abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		std::ostringstream src;
243abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
244abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
245abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "layout(location = 0) in  highp float in_v_attr;\n"
246abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "layout(location = 0) out highp float in_tc_attr;\n"
247abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
248abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "void main (void)\n"
249abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "{\n"
250abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "    in_tc_attr = in_v_attr;\n"
251abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "}\n";
252abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
253abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
254abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
255abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
256abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	// Tessellation control shader
257abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
258abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		std::ostringstream src;
259abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
260abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "#extension GL_EXT_tessellation_shader : require\n"
261abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
262abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "layout(vertices = 1) out;\n"
263abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
264abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "layout(location = 0) in highp float in_tc_attr[];\n"
265abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
266abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "void main (void)\n"
267abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "{\n"
268abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "    gl_TessLevelInner[0] = in_tc_attr[0];\n"
269abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "    gl_TessLevelInner[1] = in_tc_attr[1];\n"
270abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
271abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "    gl_TessLevelOuter[0] = in_tc_attr[2];\n"
272abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "    gl_TessLevelOuter[1] = in_tc_attr[3];\n"
273abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "    gl_TessLevelOuter[2] = in_tc_attr[4];\n"
274abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "    gl_TessLevelOuter[3] = in_tc_attr[5];\n"
275abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "}\n";
276abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
277abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
278abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
279abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
280abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const std::string perVertexInterfaceBlock = \
281abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		"VertexData {\n"					// no in/out qualifier
282abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		"    vec4 in_gs_tessCoord;\n"		// w component is used by mirroring test
283abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		"    int  in_gs_primitiveID;\n"
284abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		"}";								// no newline nor semicolon
285abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
286abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	// Alternative tess coordinates handling code
287abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::ostringstream tessEvalCoordSrc;
288abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	if (mirrorCoords)
289abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		switch (primitiveType)
290abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
291abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			case TESSPRIMITIVETYPE_TRIANGLES:
292abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				tessEvalCoordSrc << "    float x = gl_TessCoord.x;\n"
293abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski								 << "    float y = gl_TessCoord.y;\n"
294abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski								 << "    float z = gl_TessCoord.z;\n"
295abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski								 << "\n"
296abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski								 << "    // Mirror one half of each outer edge onto the other half, except the endpoints (because they belong to two edges)\n"
297abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski								 << "    ib_out.in_gs_tessCoord   = z == 0.0 && x > 0.5 && x != 1.0 ? vec4(1.0-x,  1.0-y,    0.0, 1.0)\n"
298abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski								 << "                             : y == 0.0 && z > 0.5 && z != 1.0 ? vec4(1.0-x,    0.0,  1.0-z, 1.0)\n"
299abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski								 << "                             : x == 0.0 && y > 0.5 && y != 1.0 ? vec4(  0.0,  1.0-y,  1.0-z, 1.0)\n"
300abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski								 << "                             : vec4(x, y, z, 0.0);\n";
301abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				break;
302abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			case TESSPRIMITIVETYPE_QUADS:
303abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				tessEvalCoordSrc << "    float x = gl_TessCoord.x;\n"
304abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski								 << "    float y = gl_TessCoord.y;\n"
305abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski								 << "\n"
306abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski								 << "    // Mirror one half of each outer edge onto the other half, except the endpoints (because they belong to two edges)\n"
307abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski								 << "    ib_out.in_gs_tessCoord   = (x == 0.0 || x == 1.0) && y > 0.5 && y != 1.0 ? vec4(    x, 1.0-y, 0.0, 1.0)\n"
308abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski								 << "                             : (y == 0.0 || y == 1.0) && x > 0.5 && x != 1.0 ? vec4(1.0-x,     y, 0.0, 1.0)\n"
309abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski								 << "                             : vec4(x, y, 0.0, 0.0);\n";
310abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				break;
311abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			case TESSPRIMITIVETYPE_ISOLINES:
312abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				tessEvalCoordSrc << "    float x = gl_TessCoord.x;\n"
313abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski								 << "    float y = gl_TessCoord.y;\n"
314abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski								 << "\n"
315abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski								 << "    // Mirror one half of each outer edge onto the other half\n"
316abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski								 << "    ib_out.in_gs_tessCoord   = (x == 0.0 || x == 1.0) && y > 0.5 ? vec4(x, 1.0-y, 0.0, 1.0)\n"
317abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski								 << "                             : vec4(x, y, 0.0, 0.0);\n";
318abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				break;
319abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			default:
320abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				DE_ASSERT(false);
321abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				return;
322abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
323abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	else
324abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		tessEvalCoordSrc << "    ib_out.in_gs_tessCoord   = vec4(gl_TessCoord, 0.0);\n";
325abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
326abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const std::vector<Winding> windingCases      = getWindingCases(windingUsage);
327abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const std::vector<bool>    usePointModeCases = getUsePointModeCases(pointModeUsage);
328abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
329abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	for (std::vector<Winding>::const_iterator windingIter = windingCases.begin(); windingIter != windingCases.end(); ++windingIter)
330abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	for (std::vector<bool>::const_iterator usePointModeIter = usePointModeCases.begin(); usePointModeIter != usePointModeCases.end(); ++usePointModeIter)
331abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
332abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		// Tessellation evaluation shader
333abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
334abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			std::ostringstream src;
335abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
336abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< "#extension GL_EXT_tessellation_shader : require\n"
337abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< "\n"
338abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< "layout(" << getTessPrimitiveTypeShaderName(primitiveType) << ", "
339abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski							 << getSpacingModeShaderName(spacingMode) << ", "
340abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski							 << getWindingShaderName(*windingIter)
341abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski							 << (*usePointModeIter ? ", point_mode" : "") << ") in;\n"
342abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< "\n"
343abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< "layout(location = 0) out " << perVertexInterfaceBlock << " ib_out;\n"
344abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< "\n"
345abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< "void main (void)\n"
346abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< "{\n"
347abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< tessEvalCoordSrc.str()
348abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< "    ib_out.in_gs_primitiveID = gl_PrimitiveID;\n"
349abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< "}\n";
350abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
351abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			programCollection.glslSources.add(getProgramName("tese", *windingIter, *usePointModeIter)) << glu::TessellationEvaluationSource(src.str());
352abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
353abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}  // for windingNdx, usePointModeNdx
354abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
355abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	// Geometry shader: data is captured here.
356abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
357abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		for (std::vector<bool>::const_iterator usePointModeIter = usePointModeCases.begin(); usePointModeIter != usePointModeCases.end(); ++usePointModeIter)
358abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
359abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			const int numVertices = numVerticesPerPrimitive(primitiveType, *usePointModeIter);  // Primitives that the tessellated patch comprises of.
360abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
361abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			std::ostringstream src;
362abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
363abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< "#extension GL_EXT_geometry_shader : require\n"
364abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< "\n"
365abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< "layout(" << getGeometryShaderInputPrimitiveTypeShaderName(primitiveType, *usePointModeIter) << ") in;\n"
366abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< "layout(" << getGeometryShaderOutputPrimitiveTypeShaderName(primitiveType, *usePointModeIter) << ", max_vertices = " << numVertices << ") out;\n"
367abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< "\n"
368abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< "layout(location = 0) in " << perVertexInterfaceBlock << " ib_in[];\n"
369abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< "\n"
370abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< "struct PerPrimitive {\n"
371abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< "    int  patchPrimitiveID;\n"
372abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< "    int  primitiveID;\n"
373abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< "    vec4 tessCoord[3];\n"
374abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< "};\n"
375abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< "\n"
376abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< "layout(set = 0, binding = 0, std430) coherent restrict buffer Output {\n"
377abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< "    int          numPrimitives;\n"
378abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< "    PerPrimitive primitive[];\n"
379abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< "} sb_out;\n"
380abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< "\n"
381abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< "void main (void)\n"
382abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< "{\n"
383abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< "    int index = atomicAdd(sb_out.numPrimitives, 1);\n"
384abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< "    sb_out.primitive[index].patchPrimitiveID = ib_in[0].in_gs_primitiveID;\n"
385abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< "    sb_out.primitive[index].primitiveID      = index;\n";
386abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			for (int i = 0; i < numVertices; ++i)
387abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				src << "    sb_out.primitive[index].tessCoord[" << i << "]     = ib_in[" << i << "].in_gs_tessCoord;\n";
388abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			for (int i = 0; i < numVertices; ++i)
389abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				src << "\n"
390abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					<< "    gl_Position = vec4(0.0);\n"
391abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					<< "    EmitVertex();\n";
392abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			src << "}\n";
393abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
394abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			programCollection.glslSources.add(getProgramName("geom", *usePointModeIter)) << glu::GeometrySource(src.str());
395abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
396abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
397abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
398abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
399abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski//! A description of an outer edge of a triangle, quad or isolines.
400abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski//! An outer edge can be described by the index of a u/v/w coordinate
401abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski//! and the coordinate's value along that edge.
402abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskistruct OuterEdgeDescription
403abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
404abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	int		constantCoordinateIndex;
405abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	float	constantCoordinateValueChoices[2];
406abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	int		numConstantCoordinateValueChoices;
407abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
408abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	OuterEdgeDescription (const int i, const float c0)					: constantCoordinateIndex(i), numConstantCoordinateValueChoices(1) { constantCoordinateValueChoices[0] = c0; }
409abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	OuterEdgeDescription (const int i, const float c0, const float c1)	: constantCoordinateIndex(i), numConstantCoordinateValueChoices(2) { constantCoordinateValueChoices[0] = c0; constantCoordinateValueChoices[1] = c1; }
410abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
411abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::string description (void) const
412abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
413abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		static const char* const	coordinateNames[] = { "u", "v", "w" };
414abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		std::string					result;
415abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		for (int i = 0; i < numConstantCoordinateValueChoices; ++i)
416abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			result += std::string() + (i > 0 ? " or " : "") + coordinateNames[constantCoordinateIndex] + "=" + de::toString(constantCoordinateValueChoices[i]);
417abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		return result;
418abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
419abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
420abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	bool contains (const tcu::Vec3& v) const
421abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
422abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		for (int i = 0; i < numConstantCoordinateValueChoices; ++i)
423abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			if (v[constantCoordinateIndex] == constantCoordinateValueChoices[i])
424abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				return true;
425abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		return false;
426abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
427abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
428abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
429abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskistd::vector<OuterEdgeDescription> outerEdgeDescriptions (const TessPrimitiveType primType)
430abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
431abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	static const OuterEdgeDescription triangleOuterEdgeDescriptions[3] =
432abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
433abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		OuterEdgeDescription(0, 0.0f),
434abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		OuterEdgeDescription(1, 0.0f),
435abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		OuterEdgeDescription(2, 0.0f)
436abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	};
437abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
438abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	static const OuterEdgeDescription quadOuterEdgeDescriptions[4] =
439abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
440abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		OuterEdgeDescription(0, 0.0f),
441abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		OuterEdgeDescription(1, 0.0f),
442abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		OuterEdgeDescription(0, 1.0f),
443abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		OuterEdgeDescription(1, 1.0f)
444abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	};
445abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
446abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	static const OuterEdgeDescription isolinesOuterEdgeDescriptions[1] =
447abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
448abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		OuterEdgeDescription(0, 0.0f, 1.0f),
449abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	};
450abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
451abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	switch (primType)
452abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
453abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		case TESSPRIMITIVETYPE_TRIANGLES:	return arrayToVector(triangleOuterEdgeDescriptions);
454abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		case TESSPRIMITIVETYPE_QUADS:		return arrayToVector(quadOuterEdgeDescriptions);
455abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		case TESSPRIMITIVETYPE_ISOLINES:	return arrayToVector(isolinesOuterEdgeDescriptions);
456abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
457abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		default:
458abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			DE_ASSERT(false);
459abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			return std::vector<OuterEdgeDescription>();
460abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
461abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
462abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
463abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskinamespace InvariantOuterEdge
464abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
465abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
466abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskistruct CaseDefinition
467abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
468abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	TessPrimitiveType	primitiveType;
469abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	SpacingMode			spacingMode;
470abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	Winding				winding;
471abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	bool				usePointMode;
472abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
473abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
474abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskitypedef std::set<tcu::Vec3, VecLexLessThan<3> > Vec3Set;
475abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
476abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskistd::vector<float> generateRandomPatchTessLevels (const int numPatches, const int constantOuterLevelIndex, const float constantOuterLevel, de::Random& rnd)
477abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
478abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::vector<float> tessLevels(numPatches*NUM_TESS_LEVELS);
479abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
480abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	for (int patchNdx = 0; patchNdx < numPatches; ++patchNdx)
481abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
482abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		float* const inner = &tessLevels[patchNdx*NUM_TESS_LEVELS + 0];
483abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		float* const outer = &tessLevels[patchNdx*NUM_TESS_LEVELS + 2];
484abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
485abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		for (int j = 0; j < 2; ++j)
486abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			inner[j] = rnd.getFloat(1.0f, 62.0f);
487abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		for (int j = 0; j < 4; ++j)
488abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			outer[j] = j == constantOuterLevelIndex ? constantOuterLevel : rnd.getFloat(1.0f, 62.0f);
489abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
490abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
491abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return tessLevels;
492abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
493abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
494abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskistd::vector<float> generatePatchTessLevels (const int numPatches, const int constantOuterLevelIndex, const float constantOuterLevel)
495abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
496abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	de::Random rnd(123);
497abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return generateRandomPatchTessLevels(numPatches, constantOuterLevelIndex, constantOuterLevel, rnd);
498abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
499abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
500abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiint multiplePatchReferencePrimitiveCount (const TessPrimitiveType primitiveType, const SpacingMode spacingMode, const bool usePointMode, const float* levels, int numPatches)
501abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
502abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	int result = 0;
503abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	for (int patchNdx = 0; patchNdx < numPatches; ++patchNdx)
504abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		result += referencePrimitiveCount(primitiveType, spacingMode, usePointMode, &levels[NUM_TESS_LEVELS*patchNdx + 0], &levels[NUM_TESS_LEVELS*patchNdx + 2]);
505abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return result;
506abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
507abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
508abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskitemplate<std::size_t N>
509abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiint computeMaxPrimitiveCount (const int numPatchesToDraw, const TessPrimitiveType primitiveType, const SpacingMode spacingMode, const bool usePointMode, const float (&singleOuterEdgeLevels)[N])
510abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
511abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const int                outerEdgeIndex  = 0; // outer-edge index doesn't affect vertex count
512abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const std::vector<float> patchTessLevels = generatePatchTessLevels(numPatchesToDraw, outerEdgeIndex, arrayMax(singleOuterEdgeLevels));
513abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return multiplePatchReferencePrimitiveCount(primitiveType, spacingMode, usePointMode, &patchTessLevels[0], numPatchesToDraw);
514abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
515abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
516abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskivoid logOuterTessellationLevel (tcu::TestLog& log, const float tessLevel, const OuterEdgeDescription& edgeDesc)
517abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
518abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	log << tcu::TestLog::Message
519abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		<< "Testing with outer tessellation level " << tessLevel << " for the " << edgeDesc.description() << " edge, and with various levels for other edges, and with all programs"
520abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		<< tcu::TestLog::EndMessage;
521abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
522abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
523abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskivoid logPrimitiveCountError (tcu::TestLog& log, const int numPatchesToDraw, int numPrimitives, const int refNumPrimitives, const std::vector<float>& patchTessLevels)
524abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
525abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	log << tcu::TestLog::Message
526abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		<< "Failure: the number of generated primitives is " << numPrimitives << ", expected at least " << refNumPrimitives
527abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		<< tcu::TestLog::EndMessage;
528abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
529abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	if (numPatchesToDraw == 1)
530abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		log << tcu::TestLog::Message
531abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "Note: rendered one patch; tessellation levels are (in order [inner0, inner1, outer0, outer1, outer2, outer3]):\n"
532abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< containerStr(patchTessLevels, NUM_TESS_LEVELS)
533abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< tcu::TestLog::EndMessage;
534abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	else
535abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		log << tcu::TestLog::Message
536abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "Note: rendered " << numPatchesToDraw << " patches in one draw call; "
537abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "tessellation levels for each patch are (in order [inner0, inner1, outer0, outer1, outer2, outer3]):\n"
538abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< containerStr(patchTessLevels, NUM_TESS_LEVELS)
539abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< tcu::TestLog::EndMessage;
540abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
541abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
542abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiclass BaseTestInstance : public TestInstance
543abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
544abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskipublic:
545abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	struct DrawResult
546abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
547abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		bool			success;
548abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		int				refNumPrimitives;
549abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		int				numPrimitiveVertices;
550abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		deInt32			numPrimitives;
551abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		PerPrimitiveVec	primitives;
552abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	};
553abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
554abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski											BaseTestInstance		(Context& context, const CaseDefinition caseDef, const int numPatchesToDraw);
555abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	DrawResult								draw					(const deUint32 vertexCount, const std::vector<float>& patchTessLevels, const Winding winding, const bool usePointMode);
556abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	void									uploadVertexAttributes	(const std::vector<float>& vertexData);
557abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
558abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiprotected:
559abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	static const float						m_singleOuterEdgeLevels[];
560abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
561abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const CaseDefinition					m_caseDef;
562abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const int								m_numPatchesToDraw;
563abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const VkFormat							m_vertexFormat;
564abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const deUint32							m_vertexStride;
565abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const std::vector<OuterEdgeDescription>	m_edgeDescriptions;
566abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const int								m_maxNumPrimitivesInDrawCall;
567abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const VkDeviceSize						m_vertexDataSizeBytes;
568abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Buffer							m_vertexBuffer;
569abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const int								m_resultBufferPrimitiveDataOffset;
570abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const VkDeviceSize						m_resultBufferSizeBytes;
571abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Buffer							m_resultBuffer;
572abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	Unique<VkDescriptorSetLayout>			m_descriptorSetLayout;
573abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	Unique<VkDescriptorPool>				m_descriptorPool;
574abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	Unique<VkDescriptorSet>					m_descriptorSet;
575abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	Unique<VkRenderPass>					m_renderPass;
576abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	Unique<VkFramebuffer>					m_framebuffer;
577abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	Unique<VkPipelineLayout>				m_pipelineLayout;
578abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	Unique<VkCommandPool>					m_cmdPool;
579abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	Unique<VkCommandBuffer>					m_cmdBuffer;
580abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
581abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
582abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiconst float BaseTestInstance::m_singleOuterEdgeLevels[] = { 1.0f, 1.2f, 1.9f, 2.3f, 2.8f, 3.3f, 3.8f, 10.2f, 1.6f, 24.4f, 24.7f, 63.0f };
583abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
584abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej JesionowskiBaseTestInstance::BaseTestInstance (Context& context, const CaseDefinition caseDef, const int numPatchesToDraw)
585abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	: TestInstance							(context)
586abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	, m_caseDef								(caseDef)
587abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	, m_numPatchesToDraw					(numPatchesToDraw)
588abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	, m_vertexFormat						(VK_FORMAT_R32_SFLOAT)
589abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	, m_vertexStride						(tcu::getPixelSize(mapVkFormat(m_vertexFormat)))
590abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	, m_edgeDescriptions					(outerEdgeDescriptions(m_caseDef.primitiveType))
591abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	, m_maxNumPrimitivesInDrawCall			(computeMaxPrimitiveCount(m_numPatchesToDraw, caseDef.primitiveType, caseDef.spacingMode, caseDef.usePointMode, m_singleOuterEdgeLevels))
592abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	, m_vertexDataSizeBytes					(NUM_TESS_LEVELS * m_numPatchesToDraw * m_vertexStride)
593abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	, m_vertexBuffer						(m_context.getDeviceInterface(), m_context.getDevice(), m_context.getDefaultAllocator(),
594abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski											makeBufferCreateInfo(m_vertexDataSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible)
5956e5ef4c51158771e71f72c70980b4dbd78f011f2Pyry Haulos	, m_resultBufferPrimitiveDataOffset		((int)sizeof(deInt32) * 4)
596abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	, m_resultBufferSizeBytes				(m_resultBufferPrimitiveDataOffset + m_maxNumPrimitivesInDrawCall * sizeof(PerPrimitive))
597abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	, m_resultBuffer						(m_context.getDeviceInterface(), m_context.getDevice(), m_context.getDefaultAllocator(),
598abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski											makeBufferCreateInfo(m_resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible)
599abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	, m_descriptorSetLayout					(DescriptorSetLayoutBuilder()
600abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski											.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_GEOMETRY_BIT)
601abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski											.build(m_context.getDeviceInterface(), m_context.getDevice()))
602abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	, m_descriptorPool						(DescriptorPoolBuilder()
603abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski											.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
604abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski											.build(m_context.getDeviceInterface(), m_context.getDevice(), VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u))
605abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	, m_descriptorSet						(makeDescriptorSet(m_context.getDeviceInterface(), m_context.getDevice(), *m_descriptorPool, *m_descriptorSetLayout))
606abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	, m_renderPass							(makeRenderPassWithoutAttachments (m_context.getDeviceInterface(), m_context.getDevice()))
607abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	, m_framebuffer							(makeFramebufferWithoutAttachments(m_context.getDeviceInterface(), m_context.getDevice(), *m_renderPass))
608abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	, m_pipelineLayout						(makePipelineLayout               (m_context.getDeviceInterface(), m_context.getDevice(), *m_descriptorSetLayout))
609abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	, m_cmdPool								(makeCommandPool                  (m_context.getDeviceInterface(), m_context.getDevice(), m_context.getUniversalQueueFamilyIndex()))
61055dd4426673bd260dde56addcfea802f21c31304Mika Isojärvi	, m_cmdBuffer							(allocateCommandBuffer            (m_context.getDeviceInterface(), m_context.getDevice(), *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY))
611abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
612abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	requireFeatures(context.getInstanceInterface(), context.getPhysicalDevice(),
613abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					FEATURE_TESSELLATION_SHADER | FEATURE_GEOMETRY_SHADER | FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS);
614abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
615abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const VkDescriptorBufferInfo resultBufferInfo = makeDescriptorBufferInfo(m_resultBuffer.get(), 0ull, m_resultBufferSizeBytes);
616abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
617abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	DescriptorSetUpdateBuilder()
618abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferInfo)
619abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.update(m_context.getDeviceInterface(), m_context.getDevice());
620abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
621abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
622abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski//! patchTessLevels are tessellation levels for all drawn patches.
623abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej JesionowskiBaseTestInstance::DrawResult BaseTestInstance::draw (const deUint32 vertexCount, const std::vector<float>& patchTessLevels, const Winding winding, const bool usePointMode)
624abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
625abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const DeviceInterface&	vk		= m_context.getDeviceInterface();
626abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const VkDevice			device	= m_context.getDevice();
627abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const VkQueue			queue	= m_context.getUniversalQueue();
628abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
629abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Unique<VkPipeline> pipeline(GraphicsPipelineBuilder()
630abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.setPatchControlPoints        (NUM_TESS_LEVELS)
631abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.setVertexInputSingleAttribute(m_vertexFormat, m_vertexStride)
632abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.setShader                    (vk, device, VK_SHADER_STAGE_VERTEX_BIT,					m_context.getBinaryCollection().get("vert"), DE_NULL)
633abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.setShader                    (vk, device, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,	m_context.getBinaryCollection().get("tesc"), DE_NULL)
634abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.setShader                    (vk, device, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, m_context.getBinaryCollection().get(getProgramName("tese", winding, usePointMode)), DE_NULL)
635abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.setShader                    (vk, device, VK_SHADER_STAGE_GEOMETRY_BIT,                m_context.getBinaryCollection().get(getProgramName("geom", usePointMode)), DE_NULL)
636abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.build                        (vk, device, *m_pipelineLayout, *m_renderPass));
637abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
638abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
639abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const Allocation& alloc = m_resultBuffer.getAllocation();
640abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(m_resultBufferSizeBytes));
641abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), m_resultBufferSizeBytes);
642abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
643abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
644abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	beginCommandBuffer(vk, *m_cmdBuffer);
645abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	beginRenderPassWithRasterizationDisabled(vk, *m_cmdBuffer, *m_renderPass, *m_framebuffer);
646abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
647abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
648abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
649abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
650abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const VkDeviceSize vertexBufferOffset = 0ull;
651abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &vertexBufferOffset);
652abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
653abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
654abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	vk.cmdDraw(*m_cmdBuffer, vertexCount, 1u, 0u, 0u);
655abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	endRenderPass(vk, *m_cmdBuffer);
656abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
657abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
658abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const VkBufferMemoryBarrier shaderWriteBarrier = makeBufferMemoryBarrier(
659abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *m_resultBuffer, 0ull, m_resultBufferSizeBytes);
660abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
661abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
662abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			0u, DE_NULL, 1u, &shaderWriteBarrier, 0u, DE_NULL);
663abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
664abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
665abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	endCommandBuffer(vk, *m_cmdBuffer);
666abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	submitCommandsAndWait(vk, device, queue, *m_cmdBuffer);
667abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
668abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	// Read back and check results
669abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
670abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Allocation& resultAlloc = m_resultBuffer.getAllocation();
671abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	invalidateMappedMemoryRange(vk, device, resultAlloc.getMemory(), resultAlloc.getOffset(), m_resultBufferSizeBytes);
672abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
673abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	DrawResult result;
674abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	result.success				= true;
675abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	result.refNumPrimitives     = multiplePatchReferencePrimitiveCount(m_caseDef.primitiveType, m_caseDef.spacingMode, usePointMode, &patchTessLevels[0], m_numPatchesToDraw);
676abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	result.numPrimitiveVertices = numVerticesPerPrimitive(m_caseDef.primitiveType, usePointMode);
677abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	result.numPrimitives        = *static_cast<deInt32*>(resultAlloc.getHostPtr());
678abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	result.primitives           = sorted(readInterleavedData<PerPrimitive>(result.numPrimitives, resultAlloc.getHostPtr(), m_resultBufferPrimitiveDataOffset, sizeof(PerPrimitive)),
679abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski										 byPatchPrimitiveID);
680abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
681abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	// If this fails then we didn't read all vertices from shader and test must be changed to allow more.
682abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	DE_ASSERT(result.numPrimitives <= m_maxNumPrimitivesInDrawCall);
683abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
684abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	tcu::TestLog& log = m_context.getTestContext().getLog();
685abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	if (result.numPrimitives != result.refNumPrimitives)
686abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
687abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		logPrimitiveCountError(log, m_numPatchesToDraw, result.numPrimitives, result.refNumPrimitives, patchTessLevels);
688abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		result.success = false;
689abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
690abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return result;
691abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
692abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
693abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskivoid BaseTestInstance::uploadVertexAttributes (const std::vector<float>& vertexData)
694abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
695abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const DeviceInterface&	vk		= m_context.getDeviceInterface();
696abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const VkDevice			device	= m_context.getDevice();
697abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
698abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Allocation& alloc = m_vertexBuffer.getAllocation();
699abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	deMemcpy(alloc.getHostPtr(), &vertexData[0], sizeInBytes(vertexData));
700abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), sizeInBytes(vertexData));
701abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
702abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
703abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski/*--------------------------------------------------------------------*//*!
704abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * \brief Test invariance rule #2
705abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski *
706abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * Test that the set of vertices along an outer edge of a quad or triangle
707abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * only depends on that edge's tessellation level, and spacing.
708abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski *
709abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * For each (outer) edge in the quad or triangle, draw multiple patches
710abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * with identical tessellation levels for that outer edge but with
711abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * different values for the other outer edges; compare, among the
712abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * primitives, the vertices generated for that outer edge. Repeat with
713abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * different programs, using different winding etc. settings. Compare
714abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * the edge's vertices between different programs.
715abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski *//*--------------------------------------------------------------------*/
716abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiclass OuterEdgeDivisionTestInstance : public BaseTestInstance
717abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
718abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskipublic:
719abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						OuterEdgeDivisionTestInstance	(Context& context, const CaseDefinition caseDef) : BaseTestInstance (context, caseDef, 10) {}
720abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	tcu::TestStatus		iterate							(void);
721abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
722abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
723abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskitcu::TestStatus OuterEdgeDivisionTestInstance::iterate (void)
724abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
725abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	for (int outerEdgeIndex = 0; outerEdgeIndex < static_cast<int>(m_edgeDescriptions.size()); ++outerEdgeIndex)
726abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	for (int outerEdgeLevelCaseNdx = 0; outerEdgeLevelCaseNdx < DE_LENGTH_OF_ARRAY(m_singleOuterEdgeLevels); ++outerEdgeLevelCaseNdx)
727abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
728abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const OuterEdgeDescription& edgeDesc        = m_edgeDescriptions[outerEdgeIndex];
729abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const std::vector<float>    patchTessLevels = generatePatchTessLevels(m_numPatchesToDraw, outerEdgeIndex, m_singleOuterEdgeLevels[outerEdgeLevelCaseNdx]);
730abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
731abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		Vec3Set firstOuterEdgeVertices; // Vertices of the outer edge of the first patch of the first program's draw call; used for comparison with other patches.
732abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
733abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		uploadVertexAttributes(patchTessLevels);
734abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		logOuterTessellationLevel(m_context.getTestContext().getLog(), m_singleOuterEdgeLevels[outerEdgeLevelCaseNdx], edgeDesc);
735abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
736abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		for (int windingNdx = 0; windingNdx < WINDING_LAST; ++windingNdx)
737abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		for (int usePointModeNdx = 0; usePointModeNdx <= 1; ++usePointModeNdx)
738abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
739abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			const Winding winding	     = static_cast<Winding>(windingNdx);
740abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			const bool	  usePointMode   = (usePointModeNdx != 0);
741abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			const bool    isFirstProgram = (windingNdx == 0 && usePointModeNdx == 0);
742abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
743abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			const DrawResult result = draw(static_cast<deUint32>(patchTessLevels.size()), patchTessLevels, winding, usePointMode);
744abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
745abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			if (!result.success)
746abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				return tcu::TestStatus::fail("Invalid set of vertices");
747abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
748abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			// Check the vertices of each patch.
749abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
750abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			int primitiveNdx = 0;
751abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			for (int patchNdx = 0; patchNdx < m_numPatchesToDraw; ++patchNdx)
752abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			{
753abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				DE_ASSERT(primitiveNdx < result.numPrimitives);
754abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
755abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				const float* const	innerLevels	= &patchTessLevels[NUM_TESS_LEVELS*patchNdx + 0];
756abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				const float* const	outerLevels	= &patchTessLevels[NUM_TESS_LEVELS*patchNdx + 2];
757abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
758abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				Vec3Set outerEdgeVertices;
759abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
760abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				// We're interested in just the vertices on the current outer edge.
761abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				for (; primitiveNdx < result.numPrimitives && result.primitives[primitiveNdx].patchPrimitiveID == patchNdx; ++primitiveNdx)
762abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				for (int i = 0; i < result.numPrimitiveVertices; ++i)
763abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				{
764abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					const tcu::Vec3& coord = result.primitives[primitiveNdx].tessCoord[i].swizzle(0, 1, 2);
765abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					if (edgeDesc.contains(coord))
766abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						outerEdgeVertices.insert(coord);
767abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				}
768abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
769abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				// Compare the vertices to those of the first patch (unless this is the first patch).
770abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
771abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				if (isFirstProgram && patchNdx == 0)
772abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					firstOuterEdgeVertices = outerEdgeVertices;
773abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				else if (firstOuterEdgeVertices != outerEdgeVertices)
774abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				{
775abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					tcu::TestLog& log = m_context.getTestContext().getLog();
776abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
777abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					log << tcu::TestLog::Message
778abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						<< "Failure: vertices generated for the edge differ between the following cases:\n"
779abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						<< "  - case A: " << getProgramDescription((Winding)0, (bool)0) << ", tessellation levels: "
780abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						<< getTessellationLevelsString(&patchTessLevels[0], &patchTessLevels[2]) << "\n"
781abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						<< "  - case B: " << getProgramDescription(winding, usePointMode) << ", tessellation levels: "
782abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						<< getTessellationLevelsString(innerLevels, outerLevels)
783abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						<< tcu::TestLog::EndMessage;
784abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
785abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					log << tcu::TestLog::Message
786abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						<< "Note: resulting vertices for the edge for the cases were:\n"
787abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						<< "  - case A: " << containerStr(firstOuterEdgeVertices, 5, 14) << "\n"
788abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						<< "  - case B: " << containerStr(outerEdgeVertices, 5, 14)
789abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						<< tcu::TestLog::EndMessage;
790abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
791abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					return tcu::TestStatus::fail("Invalid set of vertices");
792abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				}
793abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			}
794abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			DE_ASSERT(primitiveNdx == result.numPrimitives);
795abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		} // for windingNdx, usePointModeNdx
796abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	} // for outerEdgeIndex, outerEdgeLevelCaseNdx
797abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
798abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return tcu::TestStatus::pass("OK");
799abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
800abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
801abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski/*--------------------------------------------------------------------*//*!
802abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * \brief Test invariance rule #4
803abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski *
804abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * Test that the vertices on an outer edge don't depend on which of the
805abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * edges it is, other than with respect to component order.
806abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski *//*--------------------------------------------------------------------*/
807abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiclass OuterEdgeIndexIndependenceTestInstance : public BaseTestInstance
808abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
809abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskipublic:
810abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						OuterEdgeIndexIndependenceTestInstance	(Context& context, const CaseDefinition caseDef) : BaseTestInstance (context, caseDef, 1) {}
811abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	tcu::TestStatus		iterate									(void);
812abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
813abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
814abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskitcu::TestStatus OuterEdgeIndexIndependenceTestInstance::iterate (void)
815abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
816abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	for (int outerEdgeLevelCaseNdx = 0; outerEdgeLevelCaseNdx < DE_LENGTH_OF_ARRAY(m_singleOuterEdgeLevels); ++outerEdgeLevelCaseNdx)
817abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
818abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		Vec3Set firstEdgeVertices;
819abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
820abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		for (int outerEdgeIndex = 0; outerEdgeIndex < static_cast<int>(m_edgeDescriptions.size()); ++outerEdgeIndex)
821abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
822abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			const OuterEdgeDescription& edgeDesc        = m_edgeDescriptions[outerEdgeIndex];
823abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			const std::vector<float>    patchTessLevels = generatePatchTessLevels(m_numPatchesToDraw, outerEdgeIndex, m_singleOuterEdgeLevels[outerEdgeLevelCaseNdx]);
824abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
825abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			uploadVertexAttributes(patchTessLevels);
826abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			logOuterTessellationLevel(m_context.getTestContext().getLog(), m_singleOuterEdgeLevels[outerEdgeLevelCaseNdx], edgeDesc);
827abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			const DrawResult result = draw(static_cast<deUint32>(patchTessLevels.size()), patchTessLevels, m_caseDef.winding, m_caseDef.usePointMode);
828abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
829abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			// Verify case result
830abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
831abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			if (!result.success)
832abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				return tcu::TestStatus::fail("Invalid set of vertices");
833abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
834abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			Vec3Set currentEdgeVertices;
835abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
836abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			// Get the vertices on the current outer edge.
837abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			for (int primitiveNdx = 0; primitiveNdx < result.numPrimitives; ++primitiveNdx)
838abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			for (int i = 0; i < result.numPrimitiveVertices; ++i)
839abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			{
840abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				const tcu::Vec3& coord = result.primitives[primitiveNdx].tessCoord[i].swizzle(0, 1, 2);
841abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				if (edgeDesc.contains(coord))
842abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				{
843abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					// Swizzle components to match the order of the first edge.
844abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					if (m_caseDef.primitiveType == TESSPRIMITIVETYPE_TRIANGLES)
845abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						currentEdgeVertices.insert(outerEdgeIndex == 0 ? coord :
846abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski												   outerEdgeIndex == 1 ? coord.swizzle(1, 0, 2) :
847abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski												   outerEdgeIndex == 2 ? coord.swizzle(2, 1, 0) : tcu::Vec3(-1.0f));
848abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					else if (m_caseDef.primitiveType == TESSPRIMITIVETYPE_QUADS)
849abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						currentEdgeVertices.insert(tcu::Vec3(outerEdgeIndex == 0 ? coord.y() :
850abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski															 outerEdgeIndex == 1 ? coord.x() :
851abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski															 outerEdgeIndex == 2 ? coord.y() :
852abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski															 outerEdgeIndex == 3 ? coord.x() : -1.0f,
853abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski															 0.0f, 0.0f));
854abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					else
855abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						DE_ASSERT(false);
856abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				}
857abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			}
858abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
859abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			if (outerEdgeIndex == 0)
860abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				firstEdgeVertices = currentEdgeVertices;
861abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			else
862abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			{
863abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				// Compare vertices of this edge to those of the first edge.
864abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				if (currentEdgeVertices != firstEdgeVertices)
865abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				{
866abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					const char* const swizzleDesc =
867abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						m_caseDef.primitiveType == TESSPRIMITIVETYPE_TRIANGLES ? (outerEdgeIndex == 1 ? "(y, x, z)" :
868abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski																				  outerEdgeIndex == 2 ? "(z, y, x)" : DE_NULL) :
869abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						m_caseDef.primitiveType == TESSPRIMITIVETYPE_QUADS ? (outerEdgeIndex == 1 ? "(x, 0)" :
870abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski																			  outerEdgeIndex == 2 ? "(y, 0)" :
871abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski																			  outerEdgeIndex == 3 ? "(x, 0)" : DE_NULL)
872abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						: DE_NULL;
873abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
874abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					tcu::TestLog& log = m_context.getTestContext().getLog();
875abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					log << tcu::TestLog::Message
876abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						<< "Failure: the set of vertices on the " << edgeDesc.description() << " edge"
877abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						<< " doesn't match the set of vertices on the " << m_edgeDescriptions[0].description() << " edge"
878abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						<< tcu::TestLog::EndMessage;
879abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
880abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					log << tcu::TestLog::Message
881abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						<< "Note: set of vertices on " << edgeDesc.description() << " edge, components swizzled like " << swizzleDesc
882abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						<< " to match component order on first edge:\n" << containerStr(currentEdgeVertices, 5)
883abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						<< "\non " << m_edgeDescriptions[0].description() << " edge:\n" << containerStr(firstEdgeVertices, 5)
884abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						<< tcu::TestLog::EndMessage;
885abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
886abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					return tcu::TestStatus::fail("Invalid set of vertices");
887abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				}
888abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			}
889abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
890abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
891abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return tcu::TestStatus::pass("OK");
892abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
893abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
894abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski/*--------------------------------------------------------------------*//*!
895abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * \brief Test invariance rule #3
896abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski *
897abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * Test that the vertices along an outer edge are placed symmetrically.
898abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski *
899abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * Draw multiple patches with different tessellation levels and different
900abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * point_mode, winding etc. Before outputting tesscoords from shader, mirror
901abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * the vertices in the TES such that every vertex on an outer edge -
902abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * except the possible middle vertex - should be duplicated in the output.
903abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * Check that appropriate duplicates exist.
904abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski *//*--------------------------------------------------------------------*/
905abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiclass SymmetricOuterEdgeTestInstance : public BaseTestInstance
906abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
907abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskipublic:
908abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						SymmetricOuterEdgeTestInstance	(Context& context, const CaseDefinition caseDef) : BaseTestInstance (context, caseDef, 1) {}
909abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	tcu::TestStatus		iterate							(void);
910abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
911abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
912abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskitcu::TestStatus SymmetricOuterEdgeTestInstance::iterate (void)
913abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
914abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	for (int outerEdgeIndex = 0; outerEdgeIndex < static_cast<int>(m_edgeDescriptions.size()); ++outerEdgeIndex)
915abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	for (int outerEdgeLevelCaseNdx = 0; outerEdgeLevelCaseNdx < DE_LENGTH_OF_ARRAY(m_singleOuterEdgeLevels); ++outerEdgeLevelCaseNdx)
916abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
917abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const OuterEdgeDescription& edgeDesc        = m_edgeDescriptions[outerEdgeIndex];
918abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const std::vector<float>    patchTessLevels = generatePatchTessLevels(m_numPatchesToDraw, outerEdgeIndex, m_singleOuterEdgeLevels[outerEdgeLevelCaseNdx]);
919abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
920abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		uploadVertexAttributes(patchTessLevels);
921abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		logOuterTessellationLevel(m_context.getTestContext().getLog(), m_singleOuterEdgeLevels[outerEdgeLevelCaseNdx], edgeDesc);
922abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const DrawResult result = draw(static_cast<deUint32>(patchTessLevels.size()), patchTessLevels, m_caseDef.winding, m_caseDef.usePointMode);
923abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
924abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		// Verify case result
925abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
926abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		if (!result.success)
927abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			return tcu::TestStatus::fail("Invalid set of vertices");
928abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
929abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		Vec3Set nonMirroredEdgeVertices;
930abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		Vec3Set mirroredEdgeVertices;
931abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
932abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		// Get the vertices on the current outer edge.
933abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		for (int primitiveNdx = 0; primitiveNdx < result.numPrimitives; ++primitiveNdx)
934abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		for (int i = 0; i < result.numPrimitiveVertices; ++i)
935abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
936abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			const tcu::Vec3& coord = result.primitives[primitiveNdx].tessCoord[i].swizzle(0, 1, 2);
937abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			if (edgeDesc.contains(coord))
938abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			{
939abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				// Ignore the middle vertex of the outer edge, as it's exactly at the mirroring point;
940abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				// for isolines, also ignore (0, 0) and (1, 0) because there's no mirrored counterpart for them.
941abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				if (m_caseDef.primitiveType == TESSPRIMITIVETYPE_TRIANGLES &&
942abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					coord == tcu::select(tcu::Vec3(0.0f), tcu::Vec3(0.5f), singleTrueMask<3>(edgeDesc.constantCoordinateIndex)))
943abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					continue;
944abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				if (m_caseDef.primitiveType == TESSPRIMITIVETYPE_QUADS &&
945abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					coord.swizzle(0,1) == tcu::select(tcu::Vec2(edgeDesc.constantCoordinateValueChoices[0]), tcu::Vec2(0.5f), singleTrueMask<2>(edgeDesc.constantCoordinateIndex)))
946abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					continue;
947abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				if (m_caseDef.primitiveType == TESSPRIMITIVETYPE_ISOLINES &&
948abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					(coord == tcu::Vec3(0.0f, 0.5f, 0.0f) || coord == tcu::Vec3(1.0f, 0.5f, 0.0f) || coord == tcu::Vec3(0.0f, 0.0f, 0.0f) || coord == tcu::Vec3(1.0f, 0.0f, 0.0f)))
949abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					continue;
950abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
951abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				const bool isMirrored = result.primitives[primitiveNdx].tessCoord[i].w() > 0.5f;
952abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				if (isMirrored)
953abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					mirroredEdgeVertices.insert(coord);
954abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				else
955abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					nonMirroredEdgeVertices.insert(coord);
956abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			}
957abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
958abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
959abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		if (m_caseDef.primitiveType != TESSPRIMITIVETYPE_ISOLINES)
960abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
961abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			// Check that both endpoints are present. Note that endpoints aren't mirrored by the shader, since they belong to more than one edge.
962abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
963abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			tcu::Vec3 endpointA;
964abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			tcu::Vec3 endpointB;
965abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
966abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			if (m_caseDef.primitiveType == TESSPRIMITIVETYPE_TRIANGLES)
967abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			{
968abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				endpointA = tcu::select(tcu::Vec3(1.0f), tcu::Vec3(0.0f), singleTrueMask<3>((edgeDesc.constantCoordinateIndex + 1) % 3));
969abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				endpointB = tcu::select(tcu::Vec3(1.0f), tcu::Vec3(0.0f), singleTrueMask<3>((edgeDesc.constantCoordinateIndex + 2) % 3));
970abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			}
971abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			else if (m_caseDef.primitiveType == TESSPRIMITIVETYPE_QUADS)
972abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			{
973abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				endpointA.xy() = tcu::select(tcu::Vec2(edgeDesc.constantCoordinateValueChoices[0]), tcu::Vec2(0.0f), singleTrueMask<2>(edgeDesc.constantCoordinateIndex));
974abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				endpointB.xy() = tcu::select(tcu::Vec2(edgeDesc.constantCoordinateValueChoices[0]), tcu::Vec2(1.0f), singleTrueMask<2>(edgeDesc.constantCoordinateIndex));
975abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			}
976abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			else
977abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				DE_ASSERT(false);
978abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
979abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			if (!contains(nonMirroredEdgeVertices, endpointA) ||
980abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				!contains(nonMirroredEdgeVertices, endpointB))
981abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			{
982abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				m_context.getTestContext().getLog()
983abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					<< tcu::TestLog::Message << "Failure: edge doesn't contain both endpoints, " << endpointA << " and " << endpointB << tcu::TestLog::EndMessage
984abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					<< tcu::TestLog::Message << "Note: non-mirrored vertices:\n" << containerStr(nonMirroredEdgeVertices, 5)
985abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski											 << "\nmirrored vertices:\n" << containerStr(mirroredEdgeVertices, 5) << tcu::TestLog::EndMessage;
986abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
987abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				return tcu::TestStatus::fail("Invalid set of vertices");
988abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			}
989abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			nonMirroredEdgeVertices.erase(endpointA);
990abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			nonMirroredEdgeVertices.erase(endpointB);
991abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
992abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
993abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		if (nonMirroredEdgeVertices != mirroredEdgeVertices)
994abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
995abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			m_context.getTestContext().getLog()
996abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< tcu::TestLog::Message << "Failure: the set of mirrored edges isn't equal to the set of non-mirrored edges (ignoring endpoints and possible middle)" << tcu::TestLog::EndMessage
997abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< tcu::TestLog::Message << "Note: non-mirrored vertices:\n" << containerStr(nonMirroredEdgeVertices, 5)
998abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski										 << "\nmirrored vertices:\n" << containerStr(mirroredEdgeVertices, 5) << tcu::TestLog::EndMessage;
999abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1000abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			return tcu::TestStatus::fail("Invalid set of vertices");
1001abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
1002abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
1003abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return tcu::TestStatus::pass("OK");
1004abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
1005abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1006abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiclass OuterEdgeDivisionTest : public TestCase
1007abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1008abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskipublic:
1009abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	OuterEdgeDivisionTest (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const CaseDefinition caseDef)
1010abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		: TestCase	(testCtx, name, description)
1011abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		, m_caseDef	(caseDef)
1012abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1013abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
1014abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1015abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	void initPrograms (vk::SourceCollections& programCollection) const
1016abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1017abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		addDefaultPrograms(programCollection, m_caseDef.primitiveType, m_caseDef.spacingMode, WINDING_USAGE_VARY, POINT_MODE_USAGE_VARY);
1018abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
1019abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1020abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	TestInstance* createInstance (Context& context) const
1021abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1022abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		return new OuterEdgeDivisionTestInstance(context, m_caseDef);
1023abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	};
1024abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1025abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiprivate:
1026abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const CaseDefinition m_caseDef;
1027abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
1028abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1029abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiclass OuterEdgeIndexIndependenceTest : public TestCase
1030abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1031abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskipublic:
1032abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	OuterEdgeIndexIndependenceTest (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const CaseDefinition caseDef)
1033abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		: TestCase	(testCtx, name, description)
1034abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		, m_caseDef	(caseDef)
1035abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1036abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		DE_ASSERT(m_caseDef.primitiveType == TESSPRIMITIVETYPE_TRIANGLES || m_caseDef.primitiveType == TESSPRIMITIVETYPE_QUADS);
1037abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
1038abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1039abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	void initPrograms (vk::SourceCollections& programCollection) const
1040abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1041abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		addDefaultPrograms(programCollection, m_caseDef.primitiveType, m_caseDef.spacingMode, getWindingUsage(m_caseDef.winding), getPointModeUsage(m_caseDef.usePointMode));
1042abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
1043abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1044abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	TestInstance* createInstance (Context& context) const
1045abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1046abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		return new OuterEdgeIndexIndependenceTestInstance(context, m_caseDef);
1047abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	};
1048abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1049abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiprivate:
1050abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const CaseDefinition m_caseDef;
1051abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
1052abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1053abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiclass SymmetricOuterEdgeTest : public TestCase
1054abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1055abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskipublic:
1056abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	SymmetricOuterEdgeTest (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const CaseDefinition caseDef)
1057abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		: TestCase	(testCtx, name, description)
1058abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		, m_caseDef	(caseDef)
1059abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1060abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
1061abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1062abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	void initPrograms (vk::SourceCollections& programCollection) const
1063abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1064abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const bool mirrorCoords = true;
1065abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		addDefaultPrograms(programCollection, m_caseDef.primitiveType, m_caseDef.spacingMode, getWindingUsage(m_caseDef.winding), getPointModeUsage(m_caseDef.usePointMode), mirrorCoords);
1066abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
1067abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1068abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	TestInstance* createInstance (Context& context) const
1069abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1070abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		return new SymmetricOuterEdgeTestInstance(context, m_caseDef);
1071abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	};
1072abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1073abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiprivate:
1074abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const CaseDefinition m_caseDef;
1075abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
1076abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1077abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskitcu::TestCase* makeOuterEdgeDivisionTest (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TessPrimitiveType primitiveType, const SpacingMode spacingMode)
1078abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1079abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const CaseDefinition caseDef = { primitiveType, spacingMode, WINDING_LAST, false };  // winding is ignored by this test
1080abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return new OuterEdgeDivisionTest(testCtx, name, description, caseDef);
1081abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
1082abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1083abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskitcu::TestCase* makeOuterEdgeIndexIndependenceTest (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TessPrimitiveType primitiveType, const SpacingMode spacingMode, const Winding winding, const bool usePointMode)
1084abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1085abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const CaseDefinition caseDef = { primitiveType, spacingMode, winding, usePointMode };
1086abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return new OuterEdgeIndexIndependenceTest(testCtx, name, description, caseDef);
1087abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
1088abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1089abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskitcu::TestCase* makeSymmetricOuterEdgeTest (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TessPrimitiveType primitiveType, const SpacingMode spacingMode, const Winding winding, const bool usePointMode)
1090abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1091abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const CaseDefinition caseDef = { primitiveType, spacingMode, winding, usePointMode };
1092abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return new SymmetricOuterEdgeTest(testCtx, name, description, caseDef);
1093abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
1094abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1095abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski} // InvariantOuterEdge ns
1096abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1097abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskinamespace PrimitiveSetInvariance
1098abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1099abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1100abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskienum CaseType
1101abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1102abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	CASETYPE_INVARIANT_PRIMITIVE_SET,
1103abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	CASETYPE_INVARIANT_TRIANGLE_SET,
1104abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	CASETYPE_INVARIANT_OUTER_TRIANGLE_SET,
1105abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	CASETYPE_INVARIANT_INNER_TRIANGLE_SET,
1106abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
1107abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1108abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskistruct CaseDefinition
1109abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1110abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	CaseType				caseType;
1111abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	TessPrimitiveType		primitiveType;
1112abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	SpacingMode				spacingMode;
1113abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	WindingUsage			windingUsage;
1114abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	bool					usePointMode;
1115abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
1116abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1117abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskistruct LevelCase
1118abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1119abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::vector<TessLevels>	levels;
1120abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	int						mem; //!< Subclass-defined arbitrary piece of data, for type of the levelcase, if needed.
1121abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1122abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	LevelCase (const TessLevels& lev) : levels(std::vector<TessLevels>(1, lev)), mem(0) {}
1123abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	LevelCase (void) : mem(0) {}
1124abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
1125abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1126abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskitypedef tcu::Vector<tcu::Vec3, 3> Triangle;
1127abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1128abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiinline Triangle makeTriangle (const PerPrimitive& primitive)
1129abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1130abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return Triangle(primitive.tessCoord[0].swizzle(0, 1, 2),
1131abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					primitive.tessCoord[1].swizzle(0, 1, 2),
1132abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					primitive.tessCoord[2].swizzle(0, 1, 2));
1133abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
1134abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1135abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski//! Compare triangle sets, ignoring triangle order and vertex order within triangle, and possibly exclude some triangles too.
1136abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskitemplate <typename IsTriangleRelevantT>
1137abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskibool compareTriangleSets (const PerPrimitiveVec&		primitivesA,
1138abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						  const PerPrimitiveVec&		primitivesB,
1139abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						  tcu::TestLog&					log,
1140abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						  const IsTriangleRelevantT&	isTriangleRelevant,
1141abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						  const char*					ignoredTriangleDescription = DE_NULL)
1142abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1143abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	typedef LexCompare<Triangle, 3, VecLexLessThan<3> >		TriangleLexLessThan;
1144abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	typedef std::set<Triangle, TriangleLexLessThan>			TriangleSet;
1145abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1146abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const int		numTrianglesA = static_cast<int>(primitivesA.size());
1147abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const int		numTrianglesB = static_cast<int>(primitivesB.size());
1148abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	TriangleSet		trianglesA;
1149abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	TriangleSet		trianglesB;
1150abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1151abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	for (int aOrB = 0; aOrB < 2; ++aOrB)
1152abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1153abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const PerPrimitiveVec& primitives	= aOrB == 0 ? primitivesA	: primitivesB;
1154abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const int			   numTriangles	= aOrB == 0 ? numTrianglesA	: numTrianglesB;
1155abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		TriangleSet&		   triangles	= aOrB == 0 ? trianglesA	: trianglesB;
1156abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1157abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		for (int triNdx = 0; triNdx < numTriangles; ++triNdx)
1158abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
1159abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			Triangle triangle = makeTriangle(primitives[triNdx]);
1160abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1161abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			if (isTriangleRelevant(triangle.getPtr()))
1162abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			{
1163abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				std::sort(triangle.getPtr(), triangle.getPtr()+3, VecLexLessThan<3>());
1164abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				triangles.insert(triangle);
1165abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			}
1166abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
1167abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
1168abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1169abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		TriangleSet::const_iterator aIt = trianglesA.begin();
1170abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		TriangleSet::const_iterator bIt = trianglesB.begin();
1171abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1172abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		while (aIt != trianglesA.end() || bIt != trianglesB.end())
1173abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
1174abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			const bool aEnd = aIt == trianglesA.end();
1175abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			const bool bEnd = bIt == trianglesB.end();
1176abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1177abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			if (aEnd || bEnd || *aIt != *bIt)
1178abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			{
1179abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				log << tcu::TestLog::Message << "Failure: triangle sets in two cases are not equal (when ignoring triangle and vertex order"
1180abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					<< (ignoredTriangleDescription == DE_NULL ? "" : std::string() + ", and " + ignoredTriangleDescription) << ")" << tcu::TestLog::EndMessage;
1181abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1182abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				if (!aEnd && (bEnd || TriangleLexLessThan()(*aIt, *bIt)))
1183abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					log << tcu::TestLog::Message << "Note: e.g. triangle " << *aIt << " exists for first case but not for second" << tcu::TestLog::EndMessage;
1184abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				else
1185abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					log << tcu::TestLog::Message << "Note: e.g. triangle " << *bIt << " exists for second case but not for first" << tcu::TestLog::EndMessage;
1186abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1187abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				return false;
1188abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			}
1189abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1190abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			++aIt;
1191abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			++bIt;
1192abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
1193abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1194abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		return true;
1195abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
1196abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
1197abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1198abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskitemplate <typename ArgT, bool res>
1199abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskistruct ConstantUnaryPredicate
1200abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1201abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	bool operator() (const ArgT&) const { return res; }
1202abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
1203abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1204abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskibool compareTriangleSets (const PerPrimitiveVec& primitivesA, const PerPrimitiveVec& primitivesB, tcu::TestLog& log)
1205abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1206abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return compareTriangleSets(primitivesA, primitivesB, log, ConstantUnaryPredicate<const tcu::Vec3*, true>());
1207abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
1208abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1209abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski//! Compare two sets of primitives. Order of primitives in each set is undefined, but within each primitive
1210abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski//! vertex order and coordinates are expected to match exactly.
1211abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskibool comparePrimitivesExact (const PerPrimitive* const primitivesA, const PerPrimitive* const primitivesB, const int numPrimitivesPerPatch)
1212abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1213abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	int ndxB = 0;
1214abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	for (int ndxA = 0; ndxA < numPrimitivesPerPatch; ++ndxA)
1215abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1216abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const tcu::Vec4 (&coordsA)[3] = primitivesA[ndxA].tessCoord;
1217abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		bool match = false;
1218abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1219abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		// Actually both sets are usually somewhat sorted, so don't reset ndxB after each match. Instead, continue from the next index.
1220abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		for (int i = 0; i < numPrimitivesPerPatch; ++i)
1221abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
1222abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			const tcu::Vec4 (&coordsB)[3] = primitivesB[ndxB].tessCoord;
1223abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			ndxB = (ndxB + 1) % numPrimitivesPerPatch;
1224abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1225abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			if (coordsA[0] == coordsB[0] && coordsA[1] == coordsB[1] && coordsA[2] == coordsB[2])
1226abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			{
1227abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				match = true;
1228abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				break;
1229abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			}
1230abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
1231abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1232abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		if (!match)
1233abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			return false;
1234abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
1235abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return true;
1236abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
1237abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1238abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski/*--------------------------------------------------------------------*//*!
1239abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * \brief Base class for testing invariance of entire primitive set
1240abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski *
1241abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * Draws two patches with identical tessellation levels and compares the
1242abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * results. Repeats the same with other programs that are only different
1243abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * in irrelevant ways; compares the results between these two programs.
1244abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * Also potentially compares to results produced by different tessellation
1245abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * levels (see e.g. invariance rule #6).
1246abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * Furthermore, repeats the above with multiple different tessellation
1247abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * value sets.
1248abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski *
1249abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * The manner of primitive set comparison is defined by subclass. E.g.
1250abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * case for invariance rule #1 tests that same vertices come out, in same
1251abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * order; rule #5 only requires that the same triangles are output, but
1252abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * not necessarily in the same order.
1253abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski *//*--------------------------------------------------------------------*/
1254abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiclass InvarianceTestCase : public TestCase
1255abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1256abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskipublic:
1257abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski									InvarianceTestCase			(tcu::TestContext& context, const std::string& name, const std::string& description, const CaseDefinition& caseDef)
1258abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski										: TestCase	(context, name, description)
1259abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski										, m_caseDef	(caseDef) {}
1260abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1261abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	virtual							~InvarianceTestCase			(void) {}
1262abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1263abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	void							initPrograms				(SourceCollections& programCollection) const;
1264abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	TestInstance*					createInstance				(Context& context) const;
1265abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1266abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiprivate:
1267abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const CaseDefinition			m_caseDef;
1268abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
1269abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1270abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskivoid InvarianceTestCase::initPrograms (SourceCollections& programCollection) const
1271abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1272abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	addDefaultPrograms(programCollection, m_caseDef.primitiveType, m_caseDef.spacingMode, m_caseDef.windingUsage, getPointModeUsage(m_caseDef.usePointMode));
1273abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
1274abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1275abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiclass InvarianceTestInstance : public TestInstance
1276abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1277abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskipublic:
1278abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski									InvarianceTestInstance		(Context& context, const CaseDefinition& caseDef) : TestInstance(context), m_caseDef(caseDef) {}
1279abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	virtual							~InvarianceTestInstance		(void) {}
1280abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1281abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	tcu::TestStatus					iterate						(void);
1282abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1283abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiprotected:
1284abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	virtual std::vector<LevelCase>	genTessLevelCases			(void) const;
1285abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	virtual bool					compare						(const PerPrimitiveVec& primitivesA, const PerPrimitiveVec& primitivesB, const int levelCaseMem) const = 0;
1286abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1287abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const CaseDefinition			m_caseDef;
1288abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
1289abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1290abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskistd::vector<LevelCase> InvarianceTestInstance::genTessLevelCases (void) const
1291abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1292abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	static const TessLevels basicTessLevelCases[] =
1293abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1294abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{ { 1.0f,	1.0f	},	{ 1.0f,		1.0f,	1.0f,	1.0f	} },
1295abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{ { 63.0f,	24.0f	},	{ 15.0f,	42.0f,	10.0f,	12.0f	} },
1296abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{ { 3.0f,	2.0f	},	{ 6.0f,		8.0f,	7.0f,	9.0f	} },
1297abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{ { 4.0f,	6.0f	},	{ 2.0f,		3.0f,	1.0f,	4.0f	} },
1298abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{ { 2.0f,	2.0f	},	{ 6.0f,		8.0f,	7.0f,	9.0f	} },
1299abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{ { 5.0f,	6.0f	},	{ 1.0f,		1.0f,	1.0f,	1.0f	} },
1300abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{ { 1.0f,	6.0f	},	{ 2.0f,		3.0f,	1.0f,	4.0f	} },
1301abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{ { 5.0f,	1.0f	},	{ 2.0f,		3.0f,	1.0f,	4.0f	} },
1302abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{ { 5.2f,	1.6f	},	{ 2.9f,		3.4f,	1.5f,	4.1f	} }
1303abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	};
1304abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1305abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::vector<LevelCase> result;
1306abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	for (int i = 0; i < DE_LENGTH_OF_ARRAY(basicTessLevelCases); ++i)
1307abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		result.push_back(LevelCase(basicTessLevelCases[i]));
1308abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1309abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1310abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		de::Random rnd(123);
1311abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		for (int i = 0; i < 10; ++i)
1312abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
1313abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			TessLevels levels;
1314abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			for (int j = 0; j < DE_LENGTH_OF_ARRAY(levels.inner); ++j)
1315abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				levels.inner[j] = rnd.getFloat(1.0f, 16.0f);
1316abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			for (int j = 0; j < DE_LENGTH_OF_ARRAY(levels.outer); ++j)
1317abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				levels.outer[j] = rnd.getFloat(1.0f, 16.0f);
1318abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			result.push_back(LevelCase(levels));
1319abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
1320abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
1321abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1322abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return result;
1323abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
1324abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1325abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskitcu::TestStatus InvarianceTestInstance::iterate (void)
1326abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1327abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	requireFeatures(m_context.getInstanceInterface(), m_context.getPhysicalDevice(),
1328abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					FEATURE_TESSELLATION_SHADER | FEATURE_GEOMETRY_SHADER | FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS);
1329abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1330abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const DeviceInterface&	vk					= m_context.getDeviceInterface();
1331abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const VkDevice			device				= m_context.getDevice();
1332abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const VkQueue			queue				= m_context.getUniversalQueue();
1333abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const deUint32			queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
1334abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	Allocator&				allocator			= m_context.getDefaultAllocator();
1335abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1336abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const std::vector<LevelCase>	tessLevelCases				= genTessLevelCases();
1337abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const int						numPatchesPerDrawCall		= 2;
1338abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	int								maxNumPrimitivesPerPatch	= 0;  // computed below
1339abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::vector<std::vector<int> >	primitiveCounts;
1340abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1341abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	for (int caseNdx = 0; caseNdx < static_cast<int>(tessLevelCases.size()); ++caseNdx)
1342abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1343abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		primitiveCounts.push_back(std::vector<int>());
1344abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		for (int levelNdx = 0; levelNdx < static_cast<int>(tessLevelCases[caseNdx].levels.size()); ++levelNdx)
1345abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
1346abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			const int primitiveCount = referencePrimitiveCount(m_caseDef.primitiveType, m_caseDef.spacingMode, m_caseDef.usePointMode,
1347abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski															   &tessLevelCases[caseNdx].levels[levelNdx].inner[0], &tessLevelCases[caseNdx].levels[levelNdx].outer[0]);
1348abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			primitiveCounts.back().push_back(primitiveCount);
1349abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			maxNumPrimitivesPerPatch = de::max(maxNumPrimitivesPerPatch, primitiveCount);
1350abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
1351abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
1352abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1353abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	// Vertex input attributes buffer: to pass tessellation levels
1354abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1355abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const VkFormat     vertexFormat        = VK_FORMAT_R32_SFLOAT;
1356abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const deUint32     vertexStride        = tcu::getPixelSize(mapVkFormat(vertexFormat));
1357abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const VkDeviceSize vertexDataSizeBytes = NUM_TESS_LEVELS * numPatchesPerDrawCall * vertexStride;
1358abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Buffer       vertexBuffer        (vk, device, allocator, makeBufferCreateInfo(vertexDataSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible);
1359abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1360abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	// Output buffer: number of primitives and an array of PerPrimitive structures
1361abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1362abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const int		   resultBufferMaxVertices		= numPatchesPerDrawCall * maxNumPrimitivesPerPatch * numVerticesPerPrimitive(m_caseDef.primitiveType, m_caseDef.usePointMode);
13636e5ef4c51158771e71f72c70980b4dbd78f011f2Pyry Haulos	const int		   resultBufferTessCoordsOffset = (int)sizeof(deInt32) * 4;
1364abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const VkDeviceSize resultBufferSizeBytes        = resultBufferTessCoordsOffset + resultBufferMaxVertices * sizeof(PerPrimitive);
1365abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Buffer       resultBuffer                 (vk, device, allocator, makeBufferCreateInfo(resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible);
1366abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1367abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	// Descriptors
1368abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1369abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
1370abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_GEOMETRY_BIT)
1371abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.build(vk, device));
1372abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1373abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
1374abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
1375abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1376abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1377abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Unique<VkDescriptorSet> descriptorSet    (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
1378abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const VkDescriptorBufferInfo  resultBufferInfo = makeDescriptorBufferInfo(resultBuffer.get(), 0ull, resultBufferSizeBytes);
1379abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1380abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	DescriptorSetUpdateBuilder()
1381abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferInfo)
1382abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.update(vk, device);
1383abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1384abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Unique<VkRenderPass>     renderPass    (makeRenderPassWithoutAttachments (vk, device));
1385abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Unique<VkFramebuffer>    framebuffer   (makeFramebufferWithoutAttachments(vk, device, *renderPass));
1386abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout               (vk, device, *descriptorSetLayout));
1387abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Unique<VkCommandPool>    cmdPool       (makeCommandPool                  (vk, device, queueFamilyIndex));
138855dd4426673bd260dde56addcfea802f21c31304Mika Isojärvi	const Unique<VkCommandBuffer>  cmdBuffer     (allocateCommandBuffer            (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1389abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1390abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	for (int tessLevelCaseNdx = 0; tessLevelCaseNdx < static_cast<int>(tessLevelCases.size()); ++tessLevelCaseNdx)
1391abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1392abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const LevelCase& levelCase = tessLevelCases[tessLevelCaseNdx];
1393abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		PerPrimitiveVec  firstPrim;
1394abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1395abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
1396abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			tcu::TestLog& log = m_context.getTestContext().getLog();
1397abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			std::ostringstream tessLevelsStr;
1398abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1399abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			for (int i = 0; i < static_cast<int>(levelCase.levels.size()); ++i)
1400abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				tessLevelsStr << (levelCase.levels.size() > 1u ? "\n" : "") << getTessellationLevelsString(levelCase.levels[i], m_caseDef.primitiveType);
1401abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1402abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			log << tcu::TestLog::Message << "Tessellation level sets: " << tessLevelsStr.str() << tcu::TestLog::EndMessage;
1403abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
1404abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1405abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		for (int subTessLevelCaseNdx = 0; subTessLevelCaseNdx < static_cast<int>(levelCase.levels.size()); ++subTessLevelCaseNdx)
1406abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
1407abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			const TessLevels& tessLevels = levelCase.levels[subTessLevelCaseNdx];
1408abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			{
1409abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				TessLevels data[2];
1410abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				data[0] = tessLevels;
1411abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				data[1] = tessLevels;
1412abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1413abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				const Allocation& alloc = vertexBuffer.getAllocation();
1414abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				deMemcpy(alloc.getHostPtr(), data, sizeof(data));
1415abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), sizeof(data));
1416abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			}
1417abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1418abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			int programNdx = 0;
1419abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			const std::vector<Winding> windingCases = getWindingCases(m_caseDef.windingUsage);
1420abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			for (std::vector<Winding>::const_iterator windingIter = windingCases.begin(); windingIter != windingCases.end(); ++windingIter)
1421abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			{
1422abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				const Unique<VkPipeline> pipeline(GraphicsPipelineBuilder()
1423abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					.setPatchControlPoints        (NUM_TESS_LEVELS)
1424abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					.setVertexInputSingleAttribute(vertexFormat, vertexStride)
1425abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					.setShader                    (vk, device, VK_SHADER_STAGE_VERTEX_BIT,					m_context.getBinaryCollection().get("vert"), DE_NULL)
1426abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					.setShader                    (vk, device, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,	m_context.getBinaryCollection().get("tesc"), DE_NULL)
1427abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					.setShader                    (vk, device, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, m_context.getBinaryCollection().get(getProgramName("tese", *windingIter, m_caseDef.usePointMode)), DE_NULL)
1428abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					.setShader                    (vk, device, VK_SHADER_STAGE_GEOMETRY_BIT,                m_context.getBinaryCollection().get(getProgramName("geom", m_caseDef.usePointMode)), DE_NULL)
1429abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					.build                        (vk, device, *pipelineLayout, *renderPass));
1430abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1431abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				{
1432abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					const Allocation& alloc = resultBuffer.getAllocation();
1433abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(resultBufferSizeBytes));
1434abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), resultBufferSizeBytes);
1435abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				}
1436abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1437abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				beginCommandBuffer(vk, *cmdBuffer);
1438abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				beginRenderPassWithRasterizationDisabled(vk, *cmdBuffer, *renderPass, *framebuffer);
1439abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1440abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1441abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
1442abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				{
1443abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					const VkDeviceSize vertexBufferOffset = 0ull;
1444abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1445abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				}
1446abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1447abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				vk.cmdDraw(*cmdBuffer, numPatchesPerDrawCall * NUM_TESS_LEVELS, 1u, 0u, 0u);
1448abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				endRenderPass(vk, *cmdBuffer);
1449abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1450abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				{
1451abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					const VkBufferMemoryBarrier shaderWriteBarrier = makeBufferMemoryBarrier(
1452abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *resultBuffer, 0ull, resultBufferSizeBytes);
1453abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1454abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1455abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						0u, DE_NULL, 1u, &shaderWriteBarrier, 0u, DE_NULL);
1456abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				}
1457abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1458abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				endCommandBuffer(vk, *cmdBuffer);
1459abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1460abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1461abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				// Verify case result
1462abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				{
1463abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					const Allocation& resultAlloc = resultBuffer.getAllocation();
1464abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					invalidateMappedMemoryRange(vk, device, resultAlloc.getMemory(), resultAlloc.getOffset(), resultBufferSizeBytes);
1465abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1466abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					const int				refNumPrimitives     = numPatchesPerDrawCall * primitiveCounts[tessLevelCaseNdx][subTessLevelCaseNdx];
1467abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					const int				numPrimitiveVertices = numVerticesPerPrimitive(m_caseDef.primitiveType, m_caseDef.usePointMode);
1468abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					const deInt32			numPrimitives        = *static_cast<deInt32*>(resultAlloc.getHostPtr());
1469abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					const PerPrimitiveVec	primitives           = sorted(readInterleavedData<PerPrimitive>(numPrimitives, resultAlloc.getHostPtr(), resultBufferTessCoordsOffset, sizeof(PerPrimitive)),
1470abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski																		  byPatchPrimitiveID);
1471abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1472abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					// If this fails then we didn't read all vertices from shader and test must be changed to allow more.
1473abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					DE_ASSERT(numPrimitiveVertices * numPrimitives <= resultBufferMaxVertices);
1474079a481256d63e8498f7adf38a234bfe74bb04dePyry Haulos					DE_UNREF(numPrimitiveVertices);
1475abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1476abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					tcu::TestLog& log = m_context.getTestContext().getLog();
1477abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1478abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					if (numPrimitives != refNumPrimitives)
1479abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					{
1480abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						log << tcu::TestLog::Message << "Failure: got " << numPrimitives << " primitives, but expected " << refNumPrimitives << tcu::TestLog::EndMessage;
1481abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1482abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						return tcu::TestStatus::fail("Invalid set of primitives");
1483abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					}
1484abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1485abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					const int					half  = static_cast<int>(primitives.size() / 2);
1486abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					const PerPrimitiveVec		prim0 = PerPrimitiveVec(primitives.begin(), primitives.begin() + half);
1487abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					const PerPrimitive* const	prim1 = &primitives[half];
1488abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1489abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					if (!comparePrimitivesExact(&prim0[0], prim1, half))
1490abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					{
1491abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski							log << tcu::TestLog::Message << "Failure: tessellation coordinates differ between two primitives drawn in one draw call" << tcu::TestLog::EndMessage
1492abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski								<< tcu::TestLog::Message << "Note: tessellation levels for both primitives were: " << getTessellationLevelsString(tessLevels, m_caseDef.primitiveType) << tcu::TestLog::EndMessage;
1493abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1494abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski							return tcu::TestStatus::fail("Invalid set of primitives");
1495abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					}
1496abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1497abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					if (programNdx == 0 && subTessLevelCaseNdx == 0)
1498abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						firstPrim = prim0;
1499abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					else
1500abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					{
1501abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						const bool compareOk = compare(firstPrim, prim0, levelCase.mem);
1502abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						if (!compareOk)
1503abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						{
1504abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski							log << tcu::TestLog::Message
1505abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski								<< "Note: comparison of tessellation coordinates failed; comparison was made between following cases:\n"
1506abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski								<< "  - case A: program 0, tessellation levels: " << getTessellationLevelsString(tessLevelCases[tessLevelCaseNdx].levels[0], m_caseDef.primitiveType) << "\n"
1507abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski								<< "  - case B: program " << programNdx << ", tessellation levels: " << getTessellationLevelsString(tessLevels, m_caseDef.primitiveType)
1508abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski								<< tcu::TestLog::EndMessage;
1509abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1510abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski							return tcu::TestStatus::fail("Invalid set of primitives");
1511abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						}
1512abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					}
1513abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				}
1514abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				++programNdx;
1515abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			}
1516abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
1517abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
1518abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return tcu::TestStatus::pass("OK");
1519abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
1520abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1521abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski/*--------------------------------------------------------------------*//*!
1522abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * \brief Test invariance rule #1
1523abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski *
1524abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * Test that the sequence of primitives input to the TES only depends on
1525abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * the tessellation levels, tessellation mode, spacing mode, winding, and
1526abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * point mode.
1527abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski *//*--------------------------------------------------------------------*/
1528abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiclass InvariantPrimitiveSetTestInstance : public InvarianceTestInstance
1529abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1530abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskipublic:
1531abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	InvariantPrimitiveSetTestInstance (Context& context, const CaseDefinition& caseDef) : InvarianceTestInstance(context, caseDef) {}
1532abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1533abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiprotected:
1534abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	bool compare (const PerPrimitiveVec& primitivesA, const PerPrimitiveVec& primitivesB, const int) const
1535abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1536abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		if (!comparePrimitivesExact(&primitivesA[0], &primitivesB[0], static_cast<int>(primitivesA.size())))
1537abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
1538abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			m_context.getTestContext().getLog()
1539abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				<< tcu::TestLog::Message << "Failure: tessellation coordinates differ between two programs" << tcu::TestLog::EndMessage;
1540abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1541abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			return false;
1542abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
1543abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		return true;
1544abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
1545abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
1546abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1547abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski/*--------------------------------------------------------------------*//*!
1548abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * \brief Test invariance rule #5
1549abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski *
1550abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * Test that the set of triangles input to the TES only depends on the
1551abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * tessellation levels, tessellation mode and spacing mode. Specifically,
1552abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * winding doesn't change the set of triangles, though it can change the
1553abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * order in which they are input to TES, and can (and will) change the
1554abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * vertex order within a triangle.
1555abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski *//*--------------------------------------------------------------------*/
1556abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiclass InvariantTriangleSetTestInstance : public InvarianceTestInstance
1557abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1558abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskipublic:
1559abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	InvariantTriangleSetTestInstance (Context& context, const CaseDefinition& caseDef) : InvarianceTestInstance(context, caseDef) {}
1560abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1561abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiprotected:
1562abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	bool compare (const PerPrimitiveVec& primitivesA, const PerPrimitiveVec& primitivesB, const int) const
1563abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1564abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		return compareTriangleSets(primitivesA, primitivesB, m_context.getTestContext().getLog());
1565abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
1566abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
1567abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1568abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski/*--------------------------------------------------------------------*//*!
1569abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * \brief Test invariance rule #6
1570abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski *
1571abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * Test that the set of inner triangles input to the TES only depends on
1572abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * the inner tessellation levels, tessellation mode and spacing mode.
1573abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski *//*--------------------------------------------------------------------*/
1574abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiclass InvariantInnerTriangleSetTestInstance : public InvarianceTestInstance
1575abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1576abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskipublic:
1577abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	InvariantInnerTriangleSetTestInstance (Context& context, const CaseDefinition& caseDef) : InvarianceTestInstance(context, caseDef) {}
1578abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1579abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiprotected:
1580abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::vector<LevelCase> genTessLevelCases (void) const
1581abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1582abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const int						numSubCases		= 4;
1583abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const std::vector<LevelCase>	baseResults		= InvarianceTestInstance::genTessLevelCases();
1584abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		std::vector<LevelCase>			result;
1585abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		de::Random						rnd				(123);
1586abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1587abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		// Generate variants with different values for irrelevant levels.
1588abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		for (int baseNdx = 0; baseNdx < static_cast<int>(baseResults.size()); ++baseNdx)
1589abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
1590abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			const TessLevels&	base	= baseResults[baseNdx].levels[0];
1591abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			TessLevels			levels	= base;
1592abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			LevelCase			levelCase;
1593abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1594abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			for (int subNdx = 0; subNdx < numSubCases; ++subNdx)
1595abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			{
1596abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				levelCase.levels.push_back(levels);
1597abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1598abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				for (int i = 0; i < DE_LENGTH_OF_ARRAY(levels.outer); ++i)
1599abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					levels.outer[i] = rnd.getFloat(2.0f, 16.0f);
1600abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				if (m_caseDef.primitiveType == TESSPRIMITIVETYPE_TRIANGLES)
1601abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					levels.inner[1] = rnd.getFloat(2.0f, 16.0f);
1602abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			}
1603abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1604abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			result.push_back(levelCase);
1605abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
1606abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1607abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		return result;
1608abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
1609abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1610abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	struct IsInnerTriangleTriangle
1611abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1612abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		bool operator() (const tcu::Vec3* vertices) const
1613abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
1614abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			for (int v = 0; v < 3; ++v)
1615abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				for (int c = 0; c < 3; ++c)
1616abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					if (vertices[v][c] == 0.0f)
1617abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						return false;
1618abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			return true;
1619abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
1620abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	};
1621abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1622abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	struct IsInnerQuadTriangle
1623abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1624abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		bool operator() (const tcu::Vec3* vertices) const
1625abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
1626abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			for (int v = 0; v < 3; ++v)
1627abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				for (int c = 0; c < 2; ++c)
1628abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					if (vertices[v][c] == 0.0f || vertices[v][c] == 1.0f)
1629abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						return false;
1630abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			return true;
1631abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
1632abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	};
1633abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1634abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	bool compare (const PerPrimitiveVec& primitivesA, const PerPrimitiveVec& primitivesB, const int) const
1635abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1636abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		if (m_caseDef.primitiveType == TESSPRIMITIVETYPE_TRIANGLES)
1637abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			return compareTriangleSets(primitivesA, primitivesB, m_context.getTestContext().getLog(), IsInnerTriangleTriangle(), "outer triangles");
1638abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		else if (m_caseDef.primitiveType == TESSPRIMITIVETYPE_QUADS)
1639abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			return compareTriangleSets(primitivesA, primitivesB, m_context.getTestContext().getLog(), IsInnerQuadTriangle(), "outer triangles");
1640abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		else
1641abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
1642abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			DE_ASSERT(false);
1643abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			return false;
1644abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
1645abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
1646abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
1647abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1648abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski/*--------------------------------------------------------------------*//*!
1649abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * \brief Test invariance rule #7
1650abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski *
1651abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * Test that the set of outer triangles input to the TES only depends on
1652abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * tessellation mode, spacing mode and the inner and outer tessellation
1653abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * levels corresponding to the inner and outer edges relevant to that
1654abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski * triangle.
1655abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski *//*--------------------------------------------------------------------*/
1656abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiclass InvariantOuterTriangleSetTestInstance : public InvarianceTestInstance
1657abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1658abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskipublic:
1659abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	InvariantOuterTriangleSetTestInstance (Context& context, const CaseDefinition& caseDef) : InvarianceTestInstance(context, caseDef) {}
1660abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1661abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskiprotected:
1662abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::vector<LevelCase> genTessLevelCases (void) const
1663abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1664abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const int						numSubCasesPerEdge	= 4;
1665abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const int						numEdges			= m_caseDef.primitiveType == TESSPRIMITIVETYPE_TRIANGLES	? 3
1666abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski															: m_caseDef.primitiveType == TESSPRIMITIVETYPE_QUADS		? 4 : 0;
1667abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const std::vector<LevelCase>	baseResult			= InvarianceTestInstance::genTessLevelCases();
1668abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		std::vector<LevelCase>			result;
1669abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		de::Random						rnd					(123);
1670abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1671abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		// Generate variants with different values for irrelevant levels.
1672abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		for (int baseNdx = 0; baseNdx < static_cast<int>(baseResult.size()); ++baseNdx)
1673abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
1674abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			const TessLevels& base = baseResult[baseNdx].levels[0];
1675abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			if (base.inner[0] == 1.0f || (m_caseDef.primitiveType == TESSPRIMITIVETYPE_QUADS && base.inner[1] == 1.0f))
1676abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				continue;
1677abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1678abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			for (int edgeNdx = 0; edgeNdx < numEdges; ++edgeNdx)
1679abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			{
1680abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				TessLevels	levels = base;
1681abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				LevelCase	levelCase;
1682abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				levelCase.mem = edgeNdx;
1683abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1684abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				for (int subCaseNdx = 0; subCaseNdx < numSubCasesPerEdge; ++subCaseNdx)
1685abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				{
1686abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					levelCase.levels.push_back(levels);
1687abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1688abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					for (int i = 0; i < DE_LENGTH_OF_ARRAY(levels.outer); ++i)
1689abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					{
1690abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						if (i != edgeNdx)
1691abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski							levels.outer[i] = rnd.getFloat(2.0f, 16.0f);
1692abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					}
1693abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1694abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					if (m_caseDef.primitiveType == TESSPRIMITIVETYPE_TRIANGLES)
1695abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						levels.inner[1] = rnd.getFloat(2.0f, 16.0f);
1696abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				}
1697abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1698abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				result.push_back(levelCase);
1699abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			}
1700abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
1701abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1702abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		return result;
1703abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
1704abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1705abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	class IsTriangleTriangleOnOuterEdge
1706abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1707abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	public:
1708abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		IsTriangleTriangleOnOuterEdge (int edgeNdx) : m_edgeNdx(edgeNdx) {}
1709abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		bool operator() (const tcu::Vec3* vertices) const
1710abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
1711abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			bool touchesAppropriateEdge = false;
1712abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			for (int v = 0; v < 3; ++v)
1713abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				if (vertices[v][m_edgeNdx] == 0.0f)
1714abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					touchesAppropriateEdge = true;
1715abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1716abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			if (touchesAppropriateEdge)
1717abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			{
1718abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				const tcu::Vec3 avg = (vertices[0] + vertices[1] + vertices[2]) / 3.0f;
1719abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				return avg[m_edgeNdx] < avg[(m_edgeNdx+1)%3] &&
1720abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					   avg[m_edgeNdx] < avg[(m_edgeNdx+2)%3];
1721abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			}
1722abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			return false;
1723abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
1724abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1725abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	private:
1726abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const int m_edgeNdx;
1727abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	};
1728abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1729abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	class IsQuadTriangleOnOuterEdge
1730abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1731abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	public:
1732abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		IsQuadTriangleOnOuterEdge (int edgeNdx) : m_edgeNdx(edgeNdx) {}
1733abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1734abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		bool onEdge (const tcu::Vec3& v) const
1735abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
1736abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			return v[m_edgeNdx%2] == (m_edgeNdx <= 1 ? 0.0f : 1.0f);
1737abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
1738abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1739abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		static inline bool onAnyEdge (const tcu::Vec3& v)
1740abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
1741abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			return v[0] == 0.0f || v[0] == 1.0f || v[1] == 0.0f || v[1] == 1.0f;
1742abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
1743abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1744abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		bool operator() (const tcu::Vec3* vertices) const
1745abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
1746abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			for (int v = 0; v < 3; ++v)
1747abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			{
1748abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				const tcu::Vec3& a = vertices[v];
1749abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				const tcu::Vec3& b = vertices[(v+1)%3];
1750abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				const tcu::Vec3& c = vertices[(v+2)%3];
1751abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				if (onEdge(a) && onEdge(b))
1752abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					return true;
1753abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				if (onEdge(c) && !onAnyEdge(a) && !onAnyEdge(b) && a[m_edgeNdx%2] == b[m_edgeNdx%2])
1754abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski					return true;
1755abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			}
1756abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1757abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			return false;
1758abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
1759abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1760abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	private:
1761abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const int m_edgeNdx;
1762abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	};
1763abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1764abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	bool compare (const PerPrimitiveVec& primitivesA, const PerPrimitiveVec& primitivesB, const int outerEdgeNdx) const
1765abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1766abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		if (m_caseDef.primitiveType == TESSPRIMITIVETYPE_TRIANGLES)
1767abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
1768abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			return compareTriangleSets(primitivesA, primitivesB, m_context.getTestContext().getLog(),
1769abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski									   IsTriangleTriangleOnOuterEdge(outerEdgeNdx),
1770abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski									   ("inner triangles, and outer triangles corresponding to other edge than edge "
1771abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski										+ outerEdgeDescriptions(m_caseDef.primitiveType)[outerEdgeNdx].description()).c_str());
1772abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
1773abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		else if (m_caseDef.primitiveType == TESSPRIMITIVETYPE_QUADS)
1774abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
1775abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			return compareTriangleSets(primitivesA, primitivesB, m_context.getTestContext().getLog(),
1776abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski									   IsQuadTriangleOnOuterEdge(outerEdgeNdx),
1777abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski									   ("inner triangles, and outer triangles corresponding to other edge than edge "
1778abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski										+ outerEdgeDescriptions(m_caseDef.primitiveType)[outerEdgeNdx].description()).c_str());
1779abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
1780abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		else
1781abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			DE_ASSERT(false);
1782abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1783abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		return true;
1784abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
1785abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
1786abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1787abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej JesionowskiTestInstance* InvarianceTestCase::createInstance (Context& context) const
1788abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1789abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	switch (m_caseDef.caseType)
1790abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1791abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		case CASETYPE_INVARIANT_PRIMITIVE_SET:			return new InvariantPrimitiveSetTestInstance    (context, m_caseDef);
1792abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		case CASETYPE_INVARIANT_TRIANGLE_SET:			return new InvariantTriangleSetTestInstance     (context, m_caseDef);
1793abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		case CASETYPE_INVARIANT_OUTER_TRIANGLE_SET:		return new InvariantOuterTriangleSetTestInstance(context, m_caseDef);
1794abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		case CASETYPE_INVARIANT_INNER_TRIANGLE_SET:		return new InvariantInnerTriangleSetTestInstance(context, m_caseDef);
1795abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		default:
1796abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			DE_ASSERT(false);
1797abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			return DE_NULL;
1798abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
1799abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
1800abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1801abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej JesionowskiTestCase* makeInvariantPrimitiveSetTest (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TessPrimitiveType primitiveType, const SpacingMode spacingMode, const Winding winding, const bool usePointMode)
1802abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1803abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const CaseDefinition caseDef = { CASETYPE_INVARIANT_PRIMITIVE_SET, primitiveType, spacingMode, getWindingUsage(winding), usePointMode };
1804abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return new InvarianceTestCase(testCtx, name, description, caseDef);
1805abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
1806abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1807abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej JesionowskiTestCase* makeInvariantTriangleSetTest (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TessPrimitiveType primitiveType, const SpacingMode spacingMode)
1808abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1809abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	DE_ASSERT(primitiveType == TESSPRIMITIVETYPE_TRIANGLES || primitiveType == TESSPRIMITIVETYPE_QUADS);
1810abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const CaseDefinition caseDef = { CASETYPE_INVARIANT_TRIANGLE_SET, primitiveType, spacingMode, WINDING_USAGE_VARY, false };
1811abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return new InvarianceTestCase(testCtx, name, description, caseDef);
1812abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
1813abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1814abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej JesionowskiTestCase* makeInvariantInnerTriangleSetTest (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TessPrimitiveType primitiveType, const SpacingMode spacingMode)
1815abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1816abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	DE_ASSERT(primitiveType == TESSPRIMITIVETYPE_TRIANGLES || primitiveType == TESSPRIMITIVETYPE_QUADS);
1817abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const CaseDefinition caseDef = { CASETYPE_INVARIANT_INNER_TRIANGLE_SET, primitiveType, spacingMode, WINDING_USAGE_VARY, false };
1818abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return new InvarianceTestCase(testCtx, name, description, caseDef);
1819abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
1820abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1821abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej JesionowskiTestCase* makeInvariantOuterTriangleSetTest (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TessPrimitiveType primitiveType, const SpacingMode spacingMode)
1822abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1823abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	DE_ASSERT(primitiveType == TESSPRIMITIVETYPE_TRIANGLES || primitiveType == TESSPRIMITIVETYPE_QUADS);
1824abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const CaseDefinition caseDef = { CASETYPE_INVARIANT_OUTER_TRIANGLE_SET, primitiveType, spacingMode, WINDING_USAGE_VARY, false };
1825abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return new InvarianceTestCase(testCtx, name, description, caseDef);
1826abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
1827abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1828abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski} // PrimitiveSetInvariance ns
1829abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1830abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskinamespace TessCoordComponent
1831abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1832abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1833abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskienum CaseType
1834abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1835abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	CASETYPE_TESS_COORD_RANGE = 0,		//!< Test that all (relevant) components of tess coord are in [0,1].
1836abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	CASETYPE_ONE_MINUS_TESS_COORD,		//!< Test that for every (relevant) component c of a tess coord, 1.0-c is exact.
1837abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1838abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	CASETYPE_LAST
1839abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
1840abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1841abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskistruct CaseDefinition
1842abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1843abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	CaseType			caseType;
1844abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	TessPrimitiveType	primitiveType;
1845abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	SpacingMode			spacingMode;
1846abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	Winding				winding;
1847abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	bool				usePointMode;
1848abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski};
1849abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1850abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskistd::vector<TessLevels> genTessLevelCases (const int numCases)
1851abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1852abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	de::Random				rnd(123);
1853abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	std::vector<TessLevels>	result;
1854abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1855abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	for (int i = 0; i < numCases; ++i)
1856abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1857abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		TessLevels levels;
1858abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		levels.inner[0] = rnd.getFloat(1.0f, 63.0f);
1859abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		levels.inner[1] = rnd.getFloat(1.0f, 63.0f);
1860abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		levels.outer[0] = rnd.getFloat(1.0f, 63.0f);
1861abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		levels.outer[1] = rnd.getFloat(1.0f, 63.0f);
1862abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		levels.outer[2] = rnd.getFloat(1.0f, 63.0f);
1863abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		levels.outer[3] = rnd.getFloat(1.0f, 63.0f);
1864abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		result.push_back(levels);
1865abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
1866abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1867abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return result;
1868abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
1869abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1870abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskitypedef bool (*CompareFunc)(tcu::TestLog& log, const float value);
1871abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1872abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskibool compareTessCoordRange (tcu::TestLog& log, const float value)
1873abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1874abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	if (!de::inRange(value, 0.0f, 1.0f))
1875abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1876abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		log << tcu::TestLog::Message << "Failure: tess coord component isn't in range [0,1]" << tcu::TestLog::EndMessage;
1877abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		return false;
1878abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
1879abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return true;
1880abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
1881abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1882abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskibool compareOneMinusTessCoord (tcu::TestLog& log, const float value)
1883abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1884abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	if (value != 1.0f)
1885abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1886abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		log << tcu::TestLog::Message << "Failure: comp + (1.0-comp) doesn't equal 1.0 for some component of tessellation coordinate" << tcu::TestLog::EndMessage;
1887abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		return false;
1888abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
1889abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return true;
1890abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
1891abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1892abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskivoid initPrograms (vk::SourceCollections& programCollection, const CaseDefinition caseDef)
1893abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1894abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	// Vertex shader
1895abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1896abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		std::ostringstream src;
1897abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
1898abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
1899abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "layout(location = 0) in  highp float in_v_attr;\n"
1900abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "layout(location = 0) out highp float in_tc_attr;\n"
1901abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
1902abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "void main (void)\n"
1903abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "{\n"
1904abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "    in_tc_attr = in_v_attr;\n"
1905abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "}\n";
1906abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1907abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1908abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
1909abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1910abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	// Tessellation control shader
1911abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1912abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		std::ostringstream src;
1913abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
1914abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "#extension GL_EXT_tessellation_shader : require\n"
1915abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
1916abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "layout(vertices = 1) out;\n"
1917abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
1918abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "layout(location = 0) in highp float in_tc_attr[];\n"
1919abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
1920abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "void main (void)\n"
1921abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "{\n"
1922abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "    gl_TessLevelInner[0] = in_tc_attr[0];\n"
1923abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "    gl_TessLevelInner[1] = in_tc_attr[1];\n"
1924abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
1925abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "    gl_TessLevelOuter[0] = in_tc_attr[2];\n"
1926abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "    gl_TessLevelOuter[1] = in_tc_attr[3];\n"
1927abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "    gl_TessLevelOuter[2] = in_tc_attr[4];\n"
1928abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "    gl_TessLevelOuter[3] = in_tc_attr[5];\n"
1929abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "}\n";
1930abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1931abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
1932abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
1933abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1934abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	// Tessellation evaluation shader
1935abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
1936abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		std::ostringstream tessCoordSrc;
1937abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1938abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		if (caseDef.caseType == CASETYPE_TESS_COORD_RANGE)
1939abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			tessCoordSrc << "    sb_out.tessCoord[index] = gl_TessCoord;\n";
1940abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		else if (caseDef.caseType == CASETYPE_ONE_MINUS_TESS_COORD)
1941abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
1942abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			const char* components[]  = { "x" , "y", "z" };
1943abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			const int   numComponents = (caseDef.primitiveType == TESSPRIMITIVETYPE_TRIANGLES ? 3 : 2);
1944abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1945abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			for (int i = 0; i < numComponents; ++i)
1946abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				tessCoordSrc << "    {\n"
1947abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski							 << "        float oneMinusComp        = 1.0 - gl_TessCoord." << components[i] << ";\n"
1948abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski							 << "        sb_out.tessCoord[index]." << components[i] << " = gl_TessCoord." << components[i] << " + oneMinusComp;\n"
1949abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski							 << "    }\n";
1950abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
1951abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		else
1952abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
1953abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			DE_ASSERT(false);
1954abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			return;
1955abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
1956abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1957abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		std::ostringstream src;
1958abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
1959abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "#extension GL_EXT_tessellation_shader : require\n"
1960abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
1961abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "layout(" << getTessPrimitiveTypeShaderName(caseDef.primitiveType) << ", "
1962abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						 << getSpacingModeShaderName(caseDef.spacingMode) << ", "
1963abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						 << getWindingShaderName(caseDef.winding)
1964abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						 << (caseDef.usePointMode ? ", point_mode" : "") << ") in;\n"
1965abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
1966abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "layout(set = 0, binding = 0, std430) coherent restrict buffer Output {\n"
1967abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "    int  numInvocations;\n"
1968abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "    vec3 tessCoord[];\n"
1969abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "} sb_out;\n"
1970abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "\n"
1971abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "void main (void)\n"
1972abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "{\n"
1973abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "    int index = atomicAdd(sb_out.numInvocations, 1);\n"
1974abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< tessCoordSrc.str()
1975abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "}\n";
1976abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1977abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
1978abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
1979abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
1980abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1981abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskitcu::TestStatus test (Context& context, const CaseDefinition caseDef)
1982abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
1983abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	requireFeatures(context.getInstanceInterface(), context.getPhysicalDevice(), FEATURE_TESSELLATION_SHADER | FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS);
1984abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1985abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const DeviceInterface&	vk					= context.getDeviceInterface();
1986abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const VkDevice			device				= context.getDevice();
1987abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const VkQueue			queue				= context.getUniversalQueue();
1988abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const deUint32			queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
1989abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	Allocator&				allocator			= context.getDefaultAllocator();
1990abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1991abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const int						numTessLevelCases	= 32;
1992abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const std::vector<TessLevels>	tessLevelCases		= genTessLevelCases(numTessLevelCases);
1993abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1994abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	int maxNumVerticesInDrawCall = 0;
1995abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	for (int i = 0; i < numTessLevelCases; ++i)
1996abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		maxNumVerticesInDrawCall = de::max(maxNumVerticesInDrawCall, referenceVertexCount(caseDef.primitiveType, caseDef.spacingMode, caseDef.usePointMode,
1997abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski										   &tessLevelCases[i].inner[0], &tessLevelCases[i].outer[0]));
1998abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
1999abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	// We may get more invocations than expected, so add some more space (arbitrary number).
2000abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	maxNumVerticesInDrawCall += 4;
2001abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2002abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	// Vertex input attributes buffer: to pass tessellation levels
2003abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2004abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const VkFormat		vertexFormat        = VK_FORMAT_R32_SFLOAT;
2005abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const deUint32		vertexStride        = tcu::getPixelSize(mapVkFormat(vertexFormat));
2006abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const VkDeviceSize	vertexDataSizeBytes = NUM_TESS_LEVELS * vertexStride;
2007abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Buffer		vertexBuffer        (vk, device, allocator, makeBufferCreateInfo(vertexDataSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible);
2008abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2009abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	DE_ASSERT(vertexDataSizeBytes == sizeof(TessLevels));
2010abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2011abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	// Output buffer: number of invocations and array of tess coords
2012abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
20136e5ef4c51158771e71f72c70980b4dbd78f011f2Pyry Haulos	const int		   resultBufferTessCoordsOffset = (int)sizeof(deInt32) * 4;
2014abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const VkDeviceSize resultBufferSizeBytes        = resultBufferTessCoordsOffset + maxNumVerticesInDrawCall * sizeof(tcu::Vec4);
2015abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Buffer       resultBuffer                 (vk, device, allocator, makeBufferCreateInfo(resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible);
2016abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2017abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	// Descriptors
2018abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2019abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
2020abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
2021abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.build(vk, device));
2022abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2023abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
2024abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
2025abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
2026abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2027abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Unique<VkDescriptorSet> descriptorSet    (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
2028abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const VkDescriptorBufferInfo  resultBufferInfo = makeDescriptorBufferInfo(resultBuffer.get(), 0ull, resultBufferSizeBytes);
2029abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2030abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	DescriptorSetUpdateBuilder()
2031abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferInfo)
2032abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.update(vk, device);
2033abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2034abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Unique<VkRenderPass>     renderPass    (makeRenderPassWithoutAttachments (vk, device));
2035abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Unique<VkFramebuffer>    framebuffer   (makeFramebufferWithoutAttachments(vk, device, *renderPass));
2036abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout               (vk, device, *descriptorSetLayout));
2037abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Unique<VkCommandPool>    cmdPool       (makeCommandPool                  (vk, device, queueFamilyIndex));
203855dd4426673bd260dde56addcfea802f21c31304Mika Isojärvi	const Unique<VkCommandBuffer>  cmdBuffer     (allocateCommandBuffer            (vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2039abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2040abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const Unique<VkPipeline> pipeline(GraphicsPipelineBuilder()
2041abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.setPatchControlPoints        (NUM_TESS_LEVELS)
2042abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.setVertexInputSingleAttribute(vertexFormat, vertexStride)
2043abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.setShader                    (vk, device, VK_SHADER_STAGE_VERTEX_BIT,					context.getBinaryCollection().get("vert"), DE_NULL)
2044abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.setShader                    (vk, device, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,	context.getBinaryCollection().get("tesc"), DE_NULL)
2045abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.setShader                    (vk, device, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, context.getBinaryCollection().get("tese"), DE_NULL)
2046abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		.build                        (vk, device, *pipelineLayout, *renderPass));
2047abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2048abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	for (int tessLevelCaseNdx = 0; tessLevelCaseNdx < numTessLevelCases; ++tessLevelCaseNdx)
2049abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
2050abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		context.getTestContext().getLog()
2051abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< tcu::TestLog::Message
2052abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< "Testing with tessellation levels: " << getTessellationLevelsString(tessLevelCases[tessLevelCaseNdx], caseDef.primitiveType)
2053abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			<< tcu::TestLog::EndMessage;
2054abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2055abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
2056abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			const Allocation& alloc = vertexBuffer.getAllocation();
2057abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			deMemcpy(alloc.getHostPtr(), &tessLevelCases[tessLevelCaseNdx], sizeof(TessLevels));
2058abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), sizeof(TessLevels));
2059abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
2060abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
2061abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			const Allocation& alloc = resultBuffer.getAllocation();
2062abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(resultBufferSizeBytes));
2063abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), resultBufferSizeBytes);
2064abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
2065abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2066abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		beginCommandBuffer(vk, *cmdBuffer);
2067abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		beginRenderPassWithRasterizationDisabled(vk, *cmdBuffer, *renderPass, *framebuffer);
2068abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2069abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
2070abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
2071abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
2072abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			const VkDeviceSize vertexBufferOffset = 0ull;
2073abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
2074abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
2075abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2076abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		vk.cmdDraw(*cmdBuffer, NUM_TESS_LEVELS, 1u, 0u, 0u);
2077abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		endRenderPass(vk, *cmdBuffer);
2078abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2079abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
2080abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			const VkBufferMemoryBarrier shaderWriteBarrier = makeBufferMemoryBarrier(
2081abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *resultBuffer, 0ull, resultBufferSizeBytes);
2082abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2083abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
2084abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				0u, DE_NULL, 1u, &shaderWriteBarrier, 0u, DE_NULL);
2085abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
2086abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2087abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		endCommandBuffer(vk, *cmdBuffer);
2088abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
2089abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2090abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		// Verify case result
2091abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
2092abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			const Allocation& resultAlloc = resultBuffer.getAllocation();
2093abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			invalidateMappedMemoryRange(vk, device, resultAlloc.getMemory(), resultAlloc.getOffset(), resultBufferSizeBytes);
2094abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2095abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			const deInt32				 numVertices = *static_cast<deInt32*>(resultAlloc.getHostPtr());
2096abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			const std::vector<tcu::Vec3> vertices    = readInterleavedData<tcu::Vec3>(numVertices, resultAlloc.getHostPtr(), resultBufferTessCoordsOffset, sizeof(tcu::Vec4));
2097abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2098abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			// If this fails then we didn't read all vertices from shader and test must be changed to allow more.
2099abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			DE_ASSERT(numVertices <= maxNumVerticesInDrawCall);
2100abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2101abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			tcu::TestLog& log           = context.getTestContext().getLog();
2102abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			const int     numComponents = (caseDef.primitiveType == TESSPRIMITIVETYPE_TRIANGLES ? 3 : 2);
2103abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2104abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			CompareFunc compare = (caseDef.caseType == CASETYPE_TESS_COORD_RANGE     ? compareTessCoordRange :
2105abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski								   caseDef.caseType == CASETYPE_ONE_MINUS_TESS_COORD ? compareOneMinusTessCoord : DE_NULL);
2106abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2107abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			DE_ASSERT(compare != DE_NULL);
2108abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2109abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			for (std::vector<tcu::Vec3>::const_iterator vertexIter = vertices.begin(); vertexIter != vertices.end(); ++vertexIter)
2110abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			for (int i = 0; i < numComponents; ++i)
2111abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				if (!compare(log, (*vertexIter)[i]))
2112abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				{
2113abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						log << tcu::TestLog::Message << "Note: got a wrong tessellation coordinate "
2114abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski							<< (numComponents == 3 ? de::toString(*vertexIter) : de::toString(vertexIter->swizzle(0,1))) << tcu::TestLog::EndMessage;
2115abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2116abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski						tcu::TestStatus::fail("Invalid tessellation coordinate component");
2117abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				}
2118abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
2119abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
2120abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return tcu::TestStatus::pass("OK");
2121abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
2122abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2123abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskitcu::TestCase* makeTessCoordRangeTest (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TessPrimitiveType primitiveType, const SpacingMode spacingMode, const Winding winding, const bool usePointMode)
2124abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
2125abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const CaseDefinition caseDef = { CASETYPE_TESS_COORD_RANGE, primitiveType, spacingMode, winding, usePointMode };
2126abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return createFunctionCaseWithPrograms(testCtx, tcu::NODETYPE_SELF_VALIDATE, name, description, initPrograms, test, caseDef);
2127abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
2128abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2129abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskitcu::TestCase* makeOneMinusTessCoordTest (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TessPrimitiveType primitiveType, const SpacingMode spacingMode, const Winding winding, const bool usePointMode)
2130abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
2131abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	const CaseDefinition caseDef = { CASETYPE_ONE_MINUS_TESS_COORD, primitiveType, spacingMode, winding, usePointMode };
2132abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return createFunctionCaseWithPrograms(testCtx, tcu::NODETYPE_SELF_VALIDATE, name, description, initPrograms, test, caseDef);
2133abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
2134abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2135abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski} // TessCoordComponent ns
2136abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2137abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski} // anonymous
2138abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2139abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski//! These tests correspond to dEQP-GLES31.functional.tessellation.invariance.*
2140abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski//! Original OpenGL ES tests used transform feedback to get vertices in primitive order. To emulate this behavior we have to use geometry shader,
2141abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski//! which allows us to intercept verticess of final output primitives. This can't be done with tessellation shaders alone as number and order of
2142abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski//! invocation is undefined.
2143abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowskitcu::TestCaseGroup* createInvarianceTests (tcu::TestContext& testCtx)
2144abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski{
2145abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "invariance", "Test tessellation invariance rules"));
2146abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2147abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	de::MovePtr<tcu::TestCaseGroup> invariantPrimitiveSetGroup              (new tcu::TestCaseGroup(testCtx, "primitive_set",					"Test invariance rule #1"));
2148abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	de::MovePtr<tcu::TestCaseGroup> invariantOuterEdgeGroup					(new tcu::TestCaseGroup(testCtx, "outer_edge_division",				"Test invariance rule #2"));
2149abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	de::MovePtr<tcu::TestCaseGroup> symmetricOuterEdgeGroup					(new tcu::TestCaseGroup(testCtx, "outer_edge_symmetry",				"Test invariance rule #3"));
2150abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	de::MovePtr<tcu::TestCaseGroup> outerEdgeVertexSetIndexIndependenceGroup(new tcu::TestCaseGroup(testCtx, "outer_edge_index_independence",	"Test invariance rule #4"));
2151abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	de::MovePtr<tcu::TestCaseGroup> invariantTriangleSetGroup				(new tcu::TestCaseGroup(testCtx, "triangle_set",					"Test invariance rule #5"));
2152abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	de::MovePtr<tcu::TestCaseGroup> invariantInnerTriangleSetGroup			(new tcu::TestCaseGroup(testCtx, "inner_triangle_set",				"Test invariance rule #6"));
2153abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	de::MovePtr<tcu::TestCaseGroup> invariantOuterTriangleSetGroup			(new tcu::TestCaseGroup(testCtx, "outer_triangle_set",				"Test invariance rule #7"));
2154abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	de::MovePtr<tcu::TestCaseGroup> tessCoordComponentRangeGroup			(new tcu::TestCaseGroup(testCtx, "tess_coord_component_range",		"Test invariance rule #8, first part"));
2155abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	de::MovePtr<tcu::TestCaseGroup> oneMinusTessCoordComponentGroup			(new tcu::TestCaseGroup(testCtx, "one_minus_tess_coord_component",	"Test invariance rule #8, second part"));
2156abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2157abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	for (int primitiveTypeNdx = 0; primitiveTypeNdx < TESSPRIMITIVETYPE_LAST; ++primitiveTypeNdx)
2158abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	for (int spacingModeNdx = 0; spacingModeNdx < SPACINGMODE_LAST; ++spacingModeNdx)
2159abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	{
2160abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const TessPrimitiveType primitiveType = static_cast<TessPrimitiveType>(primitiveTypeNdx);
2161abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const SpacingMode       spacingMode   = static_cast<SpacingMode>(spacingModeNdx);
2162abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const bool              triOrQuad     = primitiveType == TESSPRIMITIVETYPE_TRIANGLES || primitiveType == TESSPRIMITIVETYPE_QUADS;
2163abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const std::string       primName      = getTessPrimitiveTypeShaderName(primitiveType);
2164abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		const std::string       primSpacName  = primName + "_" + getSpacingModeShaderName(spacingMode);
2165abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2166abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		if (triOrQuad)
2167abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
2168abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			invariantOuterEdgeGroup->addChild       (    InvariantOuterEdge::makeOuterEdgeDivisionTest        (testCtx, primSpacName, "", primitiveType, spacingMode));
2169abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			invariantTriangleSetGroup->addChild     (PrimitiveSetInvariance::makeInvariantTriangleSetTest     (testCtx, primSpacName, "", primitiveType, spacingMode));
2170abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			invariantInnerTriangleSetGroup->addChild(PrimitiveSetInvariance::makeInvariantInnerTriangleSetTest(testCtx, primSpacName, "", primitiveType, spacingMode));
2171abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			invariantOuterTriangleSetGroup->addChild(PrimitiveSetInvariance::makeInvariantOuterTriangleSetTest(testCtx, primSpacName, "", primitiveType, spacingMode));
2172abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
2173abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2174abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		for (int windingNdx = 0; windingNdx < WINDING_LAST; ++windingNdx)
2175abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		for (int usePointModeNdx = 0; usePointModeNdx <= 1; ++usePointModeNdx)
2176abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		{
2177abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			const Winding     winding               = static_cast<Winding>(windingNdx);
2178abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			const bool        usePointMode          = (usePointModeNdx != 0);
2179abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			const std::string primSpacWindPointName = primSpacName + "_" + getWindingShaderName(winding) + (usePointMode ? "_point_mode" : "");
2180abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2181abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			invariantPrimitiveSetGroup->addChild     (PrimitiveSetInvariance::makeInvariantPrimitiveSetTest(testCtx, primSpacWindPointName, "", primitiveType, spacingMode, winding, usePointMode));
2182abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			tessCoordComponentRangeGroup->addChild   (    TessCoordComponent::makeTessCoordRangeTest       (testCtx, primSpacWindPointName, "", primitiveType, spacingMode, winding, usePointMode));
2183abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			oneMinusTessCoordComponentGroup->addChild(    TessCoordComponent::makeOneMinusTessCoordTest    (testCtx, primSpacWindPointName, "", primitiveType, spacingMode, winding, usePointMode));
2184abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			symmetricOuterEdgeGroup->addChild        (    InvariantOuterEdge::makeSymmetricOuterEdgeTest   (testCtx, primSpacWindPointName, "", primitiveType, spacingMode, winding, usePointMode));
2185abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2186abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski			if (triOrQuad)
2187abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski				outerEdgeVertexSetIndexIndependenceGroup->addChild(InvariantOuterEdge::makeOuterEdgeIndexIndependenceTest(testCtx, primSpacWindPointName, "", primitiveType, spacingMode, winding, usePointMode));
2188abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski		}
2189abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	}
2190abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2191abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	group->addChild(invariantPrimitiveSetGroup.release());
2192abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	group->addChild(invariantOuterEdgeGroup.release());
2193abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	group->addChild(symmetricOuterEdgeGroup.release());
2194abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	group->addChild(outerEdgeVertexSetIndexIndependenceGroup.release());
2195abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	group->addChild(invariantTriangleSetGroup.release());
2196abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	group->addChild(invariantInnerTriangleSetGroup.release());
2197abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	group->addChild(invariantOuterTriangleSetGroup.release());
2198abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	group->addChild(tessCoordComponentRangeGroup.release());
2199abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	group->addChild(oneMinusTessCoordComponentGroup.release());
2200abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2201abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski	return group.release();
2202abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski}
2203abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski
2204abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski} // tessellation
2205abbf1c4efd3388dcfe59d125e5f33140c444a53aMaciej Jesionowski} // vkt
2206