1e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * Vulkan Conformance Tests
3e5c31af7Sopenharmony_ci * ------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright (c) 2014 The Android Open Source Project
6e5c31af7Sopenharmony_ci * Copyright (c) 2016 The Khronos Group Inc.
7e5c31af7Sopenharmony_ci *
8e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
9e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
10e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
11e5c31af7Sopenharmony_ci *
12e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
13e5c31af7Sopenharmony_ci *
14e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
15e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
16e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
18e5c31af7Sopenharmony_ci * limitations under the License.
19e5c31af7Sopenharmony_ci *
20e5c31af7Sopenharmony_ci *//*!
21e5c31af7Sopenharmony_ci * \file
22e5c31af7Sopenharmony_ci * \brief Tessellation Winding Tests
23e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
24e5c31af7Sopenharmony_ci
25e5c31af7Sopenharmony_ci#include "vktTessellationWindingTests.hpp"
26e5c31af7Sopenharmony_ci#include "vktTestCaseUtil.hpp"
27e5c31af7Sopenharmony_ci#include "vktTessellationUtil.hpp"
28e5c31af7Sopenharmony_ci#include "vktTestGroupUtil.hpp"
29e5c31af7Sopenharmony_ci
30e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp"
31e5c31af7Sopenharmony_ci#include "tcuRGBA.hpp"
32e5c31af7Sopenharmony_ci#include "tcuMaybe.hpp"
33e5c31af7Sopenharmony_ci
34e5c31af7Sopenharmony_ci#include "vkDefs.hpp"
35e5c31af7Sopenharmony_ci#include "vkBarrierUtil.hpp"
36e5c31af7Sopenharmony_ci#include "vkQueryUtil.hpp"
37e5c31af7Sopenharmony_ci#include "vkBuilderUtil.hpp"
38e5c31af7Sopenharmony_ci#include "vkImageUtil.hpp"
39e5c31af7Sopenharmony_ci#include "vkTypeUtil.hpp"
40e5c31af7Sopenharmony_ci#include "vkStrUtil.hpp"
41e5c31af7Sopenharmony_ci#include "vkCmdUtil.hpp"
42e5c31af7Sopenharmony_ci#include "vkObjUtil.hpp"
43e5c31af7Sopenharmony_ci#include "vkBufferWithMemory.hpp"
44e5c31af7Sopenharmony_ci#include "vkImageWithMemory.hpp"
45e5c31af7Sopenharmony_ci
46e5c31af7Sopenharmony_ci#include "deUniquePtr.hpp"
47e5c31af7Sopenharmony_ci
48e5c31af7Sopenharmony_cinamespace vkt
49e5c31af7Sopenharmony_ci{
50e5c31af7Sopenharmony_cinamespace tessellation
51e5c31af7Sopenharmony_ci{
52e5c31af7Sopenharmony_ci
53e5c31af7Sopenharmony_ciusing namespace vk;
54e5c31af7Sopenharmony_ci
55e5c31af7Sopenharmony_cinamespace
56e5c31af7Sopenharmony_ci{
57e5c31af7Sopenharmony_ci
58e5c31af7Sopenharmony_cistd::string getCaseName (const TessPrimitiveType primitiveType, const ShaderLanguage shaderLanguage, const Winding winding, bool yFlip)
59e5c31af7Sopenharmony_ci{
60e5c31af7Sopenharmony_ci	std::ostringstream str;
61e5c31af7Sopenharmony_ci	str << getShaderLanguageName(shaderLanguage) << "_" << getTessPrimitiveTypeShaderName(primitiveType) << "_" << getWindingShaderName(winding);
62e5c31af7Sopenharmony_ci	if (yFlip)
63e5c31af7Sopenharmony_ci		str << "_yflip";
64e5c31af7Sopenharmony_ci	return str.str();
65e5c31af7Sopenharmony_ci}
66e5c31af7Sopenharmony_ci
67e5c31af7Sopenharmony_ciinline VkFrontFace mapFrontFace (const Winding winding)
68e5c31af7Sopenharmony_ci{
69e5c31af7Sopenharmony_ci	switch (winding)
70e5c31af7Sopenharmony_ci	{
71e5c31af7Sopenharmony_ci		case WINDING_CCW:	return VK_FRONT_FACE_COUNTER_CLOCKWISE;
72e5c31af7Sopenharmony_ci		case WINDING_CW:	return VK_FRONT_FACE_CLOCKWISE;
73e5c31af7Sopenharmony_ci		default:
74e5c31af7Sopenharmony_ci			DE_ASSERT(false);
75e5c31af7Sopenharmony_ci			return VK_FRONT_FACE_LAST;
76e5c31af7Sopenharmony_ci	}
77e5c31af7Sopenharmony_ci}
78e5c31af7Sopenharmony_ci
79e5c31af7Sopenharmony_ci//! Returns true when the image passes the verification.
80e5c31af7Sopenharmony_cibool verifyResultImage (tcu::TestLog&						log,
81e5c31af7Sopenharmony_ci						const tcu::ConstPixelBufferAccess	image,
82e5c31af7Sopenharmony_ci						const TessPrimitiveType				primitiveType,
83e5c31af7Sopenharmony_ci						const VkTessellationDomainOrigin	domainOrigin,
84e5c31af7Sopenharmony_ci						const Winding						winding,
85e5c31af7Sopenharmony_ci						bool								yFlip,
86e5c31af7Sopenharmony_ci						const Winding						frontFaceWinding)
87e5c31af7Sopenharmony_ci{
88e5c31af7Sopenharmony_ci	const bool			expectVisiblePrimitive	= ((frontFaceWinding == winding) == (domainOrigin == VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT)) != yFlip;
89e5c31af7Sopenharmony_ci
90e5c31af7Sopenharmony_ci	const int			totalNumPixels			= image.getWidth()*image.getHeight();
91e5c31af7Sopenharmony_ci
92e5c31af7Sopenharmony_ci	const tcu::Vec4		white					 = tcu::RGBA::white().toVec();
93e5c31af7Sopenharmony_ci	const tcu::Vec4		red						 = tcu::RGBA::red().toVec();
94e5c31af7Sopenharmony_ci
95e5c31af7Sopenharmony_ci	int					numWhitePixels			= 0;
96e5c31af7Sopenharmony_ci	int					numRedPixels			= 0;
97e5c31af7Sopenharmony_ci
98e5c31af7Sopenharmony_ci	// Count red and white pixels
99e5c31af7Sopenharmony_ci	for (int y = 0; y < image.getHeight();	y++)
100e5c31af7Sopenharmony_ci	for (int x = 0; x < image.getWidth();	x++)
101e5c31af7Sopenharmony_ci	{
102e5c31af7Sopenharmony_ci		numWhitePixels += image.getPixel(x, y) == white ? 1 : 0;
103e5c31af7Sopenharmony_ci		numRedPixels   += image.getPixel(x, y) == red   ? 1 : 0;
104e5c31af7Sopenharmony_ci	}
105e5c31af7Sopenharmony_ci
106e5c31af7Sopenharmony_ci	DE_ASSERT(numWhitePixels + numRedPixels <= totalNumPixels);
107e5c31af7Sopenharmony_ci
108e5c31af7Sopenharmony_ci	log << tcu::TestLog::Message << "Note: got " << numWhitePixels << " white and " << numRedPixels << " red pixels" << tcu::TestLog::EndMessage;
109e5c31af7Sopenharmony_ci
110e5c31af7Sopenharmony_ci	{
111e5c31af7Sopenharmony_ci		const int otherPixels = totalNumPixels - numWhitePixels - numRedPixels;
112e5c31af7Sopenharmony_ci		if (otherPixels > 0)
113e5c31af7Sopenharmony_ci		{
114e5c31af7Sopenharmony_ci			log << tcu::TestLog::Message
115e5c31af7Sopenharmony_ci				<< "Failure: Got " << otherPixels << " other than white or red pixels"
116e5c31af7Sopenharmony_ci				<< tcu::TestLog::EndMessage;
117e5c31af7Sopenharmony_ci			return false;
118e5c31af7Sopenharmony_ci		}
119e5c31af7Sopenharmony_ci	}
120e5c31af7Sopenharmony_ci
121e5c31af7Sopenharmony_ci	if (expectVisiblePrimitive)
122e5c31af7Sopenharmony_ci	{
123e5c31af7Sopenharmony_ci		if (primitiveType == TESSPRIMITIVETYPE_TRIANGLES)
124e5c31af7Sopenharmony_ci		{
125e5c31af7Sopenharmony_ci			const int	badPixelTolerance	= (primitiveType == TESSPRIMITIVETYPE_TRIANGLES ? 5*de::max(image.getWidth(), image.getHeight()) : 0);
126e5c31af7Sopenharmony_ci
127e5c31af7Sopenharmony_ci			if (de::abs(numWhitePixels - totalNumPixels/2) > badPixelTolerance)
128e5c31af7Sopenharmony_ci			{
129e5c31af7Sopenharmony_ci				log << tcu::TestLog::Message << "Failure: wrong number of white pixels; expected approximately " << totalNumPixels/2 << tcu::TestLog::EndMessage;
130e5c31af7Sopenharmony_ci				return false;
131e5c31af7Sopenharmony_ci			}
132e5c31af7Sopenharmony_ci
133e5c31af7Sopenharmony_ci			// Check number of filled pixels (from left) in top and bottom rows to
134e5c31af7Sopenharmony_ci			// determine if triangle is in right orientation.
135e5c31af7Sopenharmony_ci			{
136e5c31af7Sopenharmony_ci				const tcu::IVec2	expectedStart	(0, 1);
137e5c31af7Sopenharmony_ci				const tcu::IVec2	expectedEnd		(image.getWidth()-1, image.getWidth());
138e5c31af7Sopenharmony_ci				const tcu::IVec2	expectedTop		= yFlip ? expectedStart : expectedEnd;
139e5c31af7Sopenharmony_ci				const tcu::IVec2	expectedBottom	= yFlip ? expectedEnd : expectedStart;
140e5c31af7Sopenharmony_ci				int					numTopFilled	= 0;
141e5c31af7Sopenharmony_ci				int					numBottomFilled	= 0;
142e5c31af7Sopenharmony_ci
143e5c31af7Sopenharmony_ci				for (int x = 0; x < image.getWidth(); ++x)
144e5c31af7Sopenharmony_ci				{
145e5c31af7Sopenharmony_ci					if (image.getPixel(x, 0) == white)
146e5c31af7Sopenharmony_ci						numTopFilled += 1;
147e5c31af7Sopenharmony_ci					else
148e5c31af7Sopenharmony_ci						break;
149e5c31af7Sopenharmony_ci				}
150e5c31af7Sopenharmony_ci
151e5c31af7Sopenharmony_ci				for (int x = 0; x < image.getWidth(); ++x)
152e5c31af7Sopenharmony_ci				{
153e5c31af7Sopenharmony_ci					if (image.getPixel(x, image.getHeight()-1) == white)
154e5c31af7Sopenharmony_ci						numBottomFilled += 1;
155e5c31af7Sopenharmony_ci					else
156e5c31af7Sopenharmony_ci						break;
157e5c31af7Sopenharmony_ci				}
158e5c31af7Sopenharmony_ci
159e5c31af7Sopenharmony_ci				if (!de::inBounds(numTopFilled, expectedTop[0], expectedTop[1]) ||
160e5c31af7Sopenharmony_ci					!de::inBounds(numBottomFilled, expectedBottom[0], expectedBottom[1]))
161e5c31af7Sopenharmony_ci				{
162e5c31af7Sopenharmony_ci					log << tcu::TestLog::Message << "Failure: triangle orientation is incorrect" << tcu::TestLog::EndMessage;
163e5c31af7Sopenharmony_ci					return false;
164e5c31af7Sopenharmony_ci				}
165e5c31af7Sopenharmony_ci			}
166e5c31af7Sopenharmony_ci
167e5c31af7Sopenharmony_ci		}
168e5c31af7Sopenharmony_ci		else if (primitiveType == TESSPRIMITIVETYPE_QUADS)
169e5c31af7Sopenharmony_ci		{
170e5c31af7Sopenharmony_ci			if (numWhitePixels != totalNumPixels)
171e5c31af7Sopenharmony_ci			{
172e5c31af7Sopenharmony_ci				log << tcu::TestLog::Message << "Failure: expected only white pixels (full-viewport quad)" << tcu::TestLog::EndMessage;
173e5c31af7Sopenharmony_ci				return false;
174e5c31af7Sopenharmony_ci			}
175e5c31af7Sopenharmony_ci		}
176e5c31af7Sopenharmony_ci		else
177e5c31af7Sopenharmony_ci			DE_ASSERT(false);
178e5c31af7Sopenharmony_ci	}
179e5c31af7Sopenharmony_ci	else
180e5c31af7Sopenharmony_ci	{
181e5c31af7Sopenharmony_ci		if (numWhitePixels != 0)
182e5c31af7Sopenharmony_ci		{
183e5c31af7Sopenharmony_ci			log << tcu::TestLog::Message << "Failure: expected only red pixels (everything culled)" << tcu::TestLog::EndMessage;
184e5c31af7Sopenharmony_ci			return false;
185e5c31af7Sopenharmony_ci		}
186e5c31af7Sopenharmony_ci	}
187e5c31af7Sopenharmony_ci
188e5c31af7Sopenharmony_ci	return true;
189e5c31af7Sopenharmony_ci}
190e5c31af7Sopenharmony_ci
191e5c31af7Sopenharmony_citypedef tcu::Maybe<VkTessellationDomainOrigin> MaybeDomainOrigin;
192e5c31af7Sopenharmony_ci
193e5c31af7Sopenharmony_ciclass WindingTest : public TestCase
194e5c31af7Sopenharmony_ci{
195e5c31af7Sopenharmony_cipublic:
196e5c31af7Sopenharmony_ci								WindingTest		(tcu::TestContext&			testCtx,
197e5c31af7Sopenharmony_ci												 const TessPrimitiveType	primitiveType,
198e5c31af7Sopenharmony_ci												 const MaybeDomainOrigin&	domainOrigin,
199e5c31af7Sopenharmony_ci												 const ShaderLanguage		shaderLanguage,
200e5c31af7Sopenharmony_ci												 const Winding				winding,
201e5c31af7Sopenharmony_ci												 bool						yFlip);
202e5c31af7Sopenharmony_ci
203e5c31af7Sopenharmony_ci	void						initPrograms	(SourceCollections&			programCollection) const;
204e5c31af7Sopenharmony_ci	TestInstance*				createInstance	(Context&					context) const;
205e5c31af7Sopenharmony_ci
206e5c31af7Sopenharmony_ciprivate:
207e5c31af7Sopenharmony_ci	const TessPrimitiveType		m_primitiveType;
208e5c31af7Sopenharmony_ci	const MaybeDomainOrigin		m_domainOrigin;
209e5c31af7Sopenharmony_ci	const ShaderLanguage		m_shaderLanguage;
210e5c31af7Sopenharmony_ci	const Winding				m_winding;
211e5c31af7Sopenharmony_ci	const bool					m_yFlip;
212e5c31af7Sopenharmony_ci};
213e5c31af7Sopenharmony_ci
214e5c31af7Sopenharmony_ciWindingTest::WindingTest (tcu::TestContext&			testCtx,
215e5c31af7Sopenharmony_ci						  const TessPrimitiveType	primitiveType,
216e5c31af7Sopenharmony_ci						  const MaybeDomainOrigin&	domainOrigin,
217e5c31af7Sopenharmony_ci						  const ShaderLanguage		shaderLanguage,
218e5c31af7Sopenharmony_ci						  const Winding				winding,
219e5c31af7Sopenharmony_ci						  bool						yFlip)
220e5c31af7Sopenharmony_ci	: TestCase			(testCtx, getCaseName(primitiveType, shaderLanguage, winding, yFlip))
221e5c31af7Sopenharmony_ci	, m_primitiveType	(primitiveType)
222e5c31af7Sopenharmony_ci	, m_domainOrigin	(domainOrigin)
223e5c31af7Sopenharmony_ci	, m_shaderLanguage	(shaderLanguage)
224e5c31af7Sopenharmony_ci	, m_winding			(winding)
225e5c31af7Sopenharmony_ci	, m_yFlip			(yFlip)
226e5c31af7Sopenharmony_ci{
227e5c31af7Sopenharmony_ci}
228e5c31af7Sopenharmony_ci
229e5c31af7Sopenharmony_civoid WindingTest::initPrograms (SourceCollections& programCollection) const
230e5c31af7Sopenharmony_ci{
231e5c31af7Sopenharmony_ci	if (m_shaderLanguage == SHADER_LANGUAGE_GLSL)
232e5c31af7Sopenharmony_ci	{
233e5c31af7Sopenharmony_ci		// Vertex shader - no inputs
234e5c31af7Sopenharmony_ci		{
235e5c31af7Sopenharmony_ci			std::ostringstream src;
236e5c31af7Sopenharmony_ci			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
237e5c31af7Sopenharmony_ci				<< "\n"
238e5c31af7Sopenharmony_ci				<< "void main (void)\n"
239e5c31af7Sopenharmony_ci				<< "{\n"
240e5c31af7Sopenharmony_ci				<< "}\n";
241e5c31af7Sopenharmony_ci
242e5c31af7Sopenharmony_ci			programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
243e5c31af7Sopenharmony_ci		}
244e5c31af7Sopenharmony_ci
245e5c31af7Sopenharmony_ci		// Tessellation control shader
246e5c31af7Sopenharmony_ci		{
247e5c31af7Sopenharmony_ci			std::ostringstream src;
248e5c31af7Sopenharmony_ci			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
249e5c31af7Sopenharmony_ci				<< "#extension GL_EXT_tessellation_shader : require\n"
250e5c31af7Sopenharmony_ci				<< "\n"
251e5c31af7Sopenharmony_ci				<< "layout(vertices = 1) out;\n"
252e5c31af7Sopenharmony_ci				<< "\n"
253e5c31af7Sopenharmony_ci				<< "void main (void)\n"
254e5c31af7Sopenharmony_ci				<< "{\n"
255e5c31af7Sopenharmony_ci				<< "    gl_TessLevelInner[0] = 5.0;\n"
256e5c31af7Sopenharmony_ci				<< "    gl_TessLevelInner[1] = 5.0;\n"
257e5c31af7Sopenharmony_ci				<< "\n"
258e5c31af7Sopenharmony_ci				<< "    gl_TessLevelOuter[0] = 5.0;\n"
259e5c31af7Sopenharmony_ci				<< "    gl_TessLevelOuter[1] = 5.0;\n"
260e5c31af7Sopenharmony_ci				<< "    gl_TessLevelOuter[2] = 5.0;\n"
261e5c31af7Sopenharmony_ci				<< "    gl_TessLevelOuter[3] = 5.0;\n"
262e5c31af7Sopenharmony_ci				<< "}\n";
263e5c31af7Sopenharmony_ci
264e5c31af7Sopenharmony_ci			programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
265e5c31af7Sopenharmony_ci		}
266e5c31af7Sopenharmony_ci
267e5c31af7Sopenharmony_ci		// Tessellation evaluation shader
268e5c31af7Sopenharmony_ci		{
269e5c31af7Sopenharmony_ci			std::ostringstream src;
270e5c31af7Sopenharmony_ci			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
271e5c31af7Sopenharmony_ci				<< "#extension GL_EXT_tessellation_shader : require\n"
272e5c31af7Sopenharmony_ci				<< "\n"
273e5c31af7Sopenharmony_ci				<< "layout(" << getTessPrimitiveTypeShaderName(m_primitiveType) << ", "
274e5c31af7Sopenharmony_ci							 << getWindingShaderName(m_winding) << ") in;\n"
275e5c31af7Sopenharmony_ci				<< "\n"
276e5c31af7Sopenharmony_ci				<< "void main (void)\n"
277e5c31af7Sopenharmony_ci				<< "{\n"
278e5c31af7Sopenharmony_ci				<< "    gl_Position = vec4(gl_TessCoord.xy*2.0 - 1.0, 0.0, 1.0);\n"
279e5c31af7Sopenharmony_ci				<< "}\n";
280e5c31af7Sopenharmony_ci
281e5c31af7Sopenharmony_ci			programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
282e5c31af7Sopenharmony_ci		}
283e5c31af7Sopenharmony_ci
284e5c31af7Sopenharmony_ci		// Fragment shader
285e5c31af7Sopenharmony_ci		{
286e5c31af7Sopenharmony_ci			std::ostringstream src;
287e5c31af7Sopenharmony_ci			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
288e5c31af7Sopenharmony_ci				<< "\n"
289e5c31af7Sopenharmony_ci				<< "layout(location = 0) out mediump vec4 o_color;\n"
290e5c31af7Sopenharmony_ci				<< "\n"
291e5c31af7Sopenharmony_ci				<< "void main (void)\n"
292e5c31af7Sopenharmony_ci				<< "{\n"
293e5c31af7Sopenharmony_ci				<< "    o_color = vec4(1.0);\n"
294e5c31af7Sopenharmony_ci				<< "}\n";
295e5c31af7Sopenharmony_ci
296e5c31af7Sopenharmony_ci			programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
297e5c31af7Sopenharmony_ci		}
298e5c31af7Sopenharmony_ci	}
299e5c31af7Sopenharmony_ci	else
300e5c31af7Sopenharmony_ci	{
301e5c31af7Sopenharmony_ci		// Vertex shader - no inputs
302e5c31af7Sopenharmony_ci		{
303e5c31af7Sopenharmony_ci			std::ostringstream src;
304e5c31af7Sopenharmony_ci			src << "void main (void)\n"
305e5c31af7Sopenharmony_ci				<< "{\n"
306e5c31af7Sopenharmony_ci				<< "}\n";
307e5c31af7Sopenharmony_ci
308e5c31af7Sopenharmony_ci			programCollection.hlslSources.add("vert") << glu::VertexSource(src.str());
309e5c31af7Sopenharmony_ci		}
310e5c31af7Sopenharmony_ci
311e5c31af7Sopenharmony_ci		// Tessellation control shader
312e5c31af7Sopenharmony_ci		{
313e5c31af7Sopenharmony_ci			std::ostringstream src;
314e5c31af7Sopenharmony_ci			src << "struct HS_CONSTANT_OUT\n"
315e5c31af7Sopenharmony_ci				<< "{\n"
316e5c31af7Sopenharmony_ci				<< "    float tessLevelsOuter[4] : SV_TessFactor;\n"
317e5c31af7Sopenharmony_ci				<< "    float tessLevelsInner[2] : SV_InsideTessFactor;\n"
318e5c31af7Sopenharmony_ci				<< "};\n"
319e5c31af7Sopenharmony_ci				<< "\n"
320e5c31af7Sopenharmony_ci				<< "[domain(\"" << getDomainName(m_primitiveType) << "\")]\n"
321e5c31af7Sopenharmony_ci				<< "[partitioning(\"integer\")]\n"
322e5c31af7Sopenharmony_ci				<< "[outputtopology(\"" << getOutputTopologyName (m_primitiveType, m_winding, false) << "\")]\n"
323e5c31af7Sopenharmony_ci				<< "[outputcontrolpoints(1)]\n"
324e5c31af7Sopenharmony_ci				<< "[patchconstantfunc(\"PCF\")]\n"
325e5c31af7Sopenharmony_ci				<< "void main()\n"
326e5c31af7Sopenharmony_ci				<< "{\n"
327e5c31af7Sopenharmony_ci				<< "}\n"
328e5c31af7Sopenharmony_ci				<< "\n"
329e5c31af7Sopenharmony_ci				<< "HS_CONSTANT_OUT PCF()\n"
330e5c31af7Sopenharmony_ci				<< "{\n"
331e5c31af7Sopenharmony_ci				<< "    HS_CONSTANT_OUT output;\n"
332e5c31af7Sopenharmony_ci				<< "    output.tessLevelsInner[0] = 5.0;\n"
333e5c31af7Sopenharmony_ci				<< "    output.tessLevelsInner[1] = 5.0;\n"
334e5c31af7Sopenharmony_ci				<< "    output.tessLevelsOuter[0] = 5.0;\n"
335e5c31af7Sopenharmony_ci				<< "    output.tessLevelsOuter[1] = 5.0;\n"
336e5c31af7Sopenharmony_ci				<< "    output.tessLevelsOuter[2] = 5.0;\n"
337e5c31af7Sopenharmony_ci				<< "    output.tessLevelsOuter[3] = 5.0;\n"
338e5c31af7Sopenharmony_ci				<< "    return output;\n"
339e5c31af7Sopenharmony_ci				<< "}\n";
340e5c31af7Sopenharmony_ci
341e5c31af7Sopenharmony_ci			programCollection.hlslSources.add("tesc") << glu::TessellationControlSource(src.str());
342e5c31af7Sopenharmony_ci		}
343e5c31af7Sopenharmony_ci
344e5c31af7Sopenharmony_ci		// Tessellation evaluation shader
345e5c31af7Sopenharmony_ci		{
346e5c31af7Sopenharmony_ci			std::ostringstream src;
347e5c31af7Sopenharmony_ci
348e5c31af7Sopenharmony_ci			src	<< "float4 main(" << (m_primitiveType == TESSPRIMITIVETYPE_TRIANGLES ? "float3" : "float2") << " tessCoords : SV_DOMAINLOCATION) : SV_POSITION\n"
349e5c31af7Sopenharmony_ci				<< "{\n"
350e5c31af7Sopenharmony_ci				<< "    return float4(tessCoords.xy*2.0 - 1, 0.0, 1.0);\n"
351e5c31af7Sopenharmony_ci				<< "}\n";
352e5c31af7Sopenharmony_ci
353e5c31af7Sopenharmony_ci			programCollection.hlslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
354e5c31af7Sopenharmony_ci		}
355e5c31af7Sopenharmony_ci
356e5c31af7Sopenharmony_ci		// Fragment shader
357e5c31af7Sopenharmony_ci		{
358e5c31af7Sopenharmony_ci			std::ostringstream src;
359e5c31af7Sopenharmony_ci			src << "float4 main (void) : COLOR0\n"
360e5c31af7Sopenharmony_ci				<< "{\n"
361e5c31af7Sopenharmony_ci				<< "    return float4(1.0);\n"
362e5c31af7Sopenharmony_ci				<< "}\n";
363e5c31af7Sopenharmony_ci
364e5c31af7Sopenharmony_ci			programCollection.hlslSources.add("frag") << glu::FragmentSource(src.str());
365e5c31af7Sopenharmony_ci		}
366e5c31af7Sopenharmony_ci	}
367e5c31af7Sopenharmony_ci}
368e5c31af7Sopenharmony_ci
369e5c31af7Sopenharmony_ciclass WindingTestInstance : public TestInstance
370e5c31af7Sopenharmony_ci{
371e5c31af7Sopenharmony_cipublic:
372e5c31af7Sopenharmony_ci								WindingTestInstance (Context&					context,
373e5c31af7Sopenharmony_ci													 const TessPrimitiveType	primitiveType,
374e5c31af7Sopenharmony_ci													 const MaybeDomainOrigin&	domainOrigin,
375e5c31af7Sopenharmony_ci													 const Winding				winding,
376e5c31af7Sopenharmony_ci													 bool						yFlip);
377e5c31af7Sopenharmony_ci
378e5c31af7Sopenharmony_ci	tcu::TestStatus				iterate				(void);
379e5c31af7Sopenharmony_ci
380e5c31af7Sopenharmony_ciprivate:
381e5c31af7Sopenharmony_ci	void						requireExtension	(const char* name) const;
382e5c31af7Sopenharmony_ci
383e5c31af7Sopenharmony_ci	const TessPrimitiveType		m_primitiveType;
384e5c31af7Sopenharmony_ci	const MaybeDomainOrigin		m_domainOrigin;
385e5c31af7Sopenharmony_ci	const Winding				m_winding;
386e5c31af7Sopenharmony_ci	const bool					m_yFlip;
387e5c31af7Sopenharmony_ci};
388e5c31af7Sopenharmony_ci
389e5c31af7Sopenharmony_ciWindingTestInstance::WindingTestInstance (Context&					context,
390e5c31af7Sopenharmony_ci										  const TessPrimitiveType	primitiveType,
391e5c31af7Sopenharmony_ci										  const MaybeDomainOrigin&	domainOrigin,
392e5c31af7Sopenharmony_ci										  const Winding				winding,
393e5c31af7Sopenharmony_ci										  bool						yFlip)
394e5c31af7Sopenharmony_ci	: TestInstance		(context)
395e5c31af7Sopenharmony_ci	, m_primitiveType	(primitiveType)
396e5c31af7Sopenharmony_ci	, m_domainOrigin	(domainOrigin)
397e5c31af7Sopenharmony_ci	, m_winding			(winding)
398e5c31af7Sopenharmony_ci	, m_yFlip			(yFlip)
399e5c31af7Sopenharmony_ci{
400e5c31af7Sopenharmony_ci	if (m_yFlip)
401e5c31af7Sopenharmony_ci		requireExtension("VK_KHR_maintenance1");
402e5c31af7Sopenharmony_ci
403e5c31af7Sopenharmony_ci	if ((bool)m_domainOrigin)
404e5c31af7Sopenharmony_ci		requireExtension("VK_KHR_maintenance2");
405e5c31af7Sopenharmony_ci}
406e5c31af7Sopenharmony_ci
407e5c31af7Sopenharmony_civoid WindingTestInstance::requireExtension (const char* name) const
408e5c31af7Sopenharmony_ci{
409e5c31af7Sopenharmony_ci	if(!m_context.isDeviceFunctionalitySupported(name))
410e5c31af7Sopenharmony_ci		TCU_THROW(NotSupportedError, (std::string(name) + " is not supported").c_str());
411e5c31af7Sopenharmony_ci}
412e5c31af7Sopenharmony_ci
413e5c31af7Sopenharmony_citcu::TestStatus WindingTestInstance::iterate (void)
414e5c31af7Sopenharmony_ci{
415e5c31af7Sopenharmony_ci	const DeviceInterface&	vk					= m_context.getDeviceInterface();
416e5c31af7Sopenharmony_ci	const VkDevice			device				= m_context.getDevice();
417e5c31af7Sopenharmony_ci	const VkQueue			queue				= m_context.getUniversalQueue();
418e5c31af7Sopenharmony_ci	const deUint32			queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
419e5c31af7Sopenharmony_ci	Allocator&				allocator			= m_context.getDefaultAllocator();
420e5c31af7Sopenharmony_ci
421e5c31af7Sopenharmony_ci	// Color attachment
422e5c31af7Sopenharmony_ci
423e5c31af7Sopenharmony_ci	const tcu::IVec2			  renderSize				 = tcu::IVec2(64, 64);
424e5c31af7Sopenharmony_ci	const VkFormat				  colorFormat				 = VK_FORMAT_R8G8B8A8_UNORM;
425e5c31af7Sopenharmony_ci	const VkImageSubresourceRange colorImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
426e5c31af7Sopenharmony_ci	const ImageWithMemory		  colorAttachmentImage		 (vk, device, allocator,
427e5c31af7Sopenharmony_ci															 makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 1u),
428e5c31af7Sopenharmony_ci															 MemoryRequirement::Any);
429e5c31af7Sopenharmony_ci
430e5c31af7Sopenharmony_ci	// Color output buffer: image will be copied here for verification
431e5c31af7Sopenharmony_ci
432e5c31af7Sopenharmony_ci	const VkDeviceSize		colorBufferSizeBytes = renderSize.x()*renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat));
433e5c31af7Sopenharmony_ci	const BufferWithMemory	colorBuffer			 (vk, device, allocator, makeBufferCreateInfo(colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible);
434e5c31af7Sopenharmony_ci
435e5c31af7Sopenharmony_ci	// Pipeline
436e5c31af7Sopenharmony_ci
437e5c31af7Sopenharmony_ci	const Unique<VkImageView>		colorAttachmentView	(makeImageView		(vk, device, *colorAttachmentImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorImageSubresourceRange));
438e5c31af7Sopenharmony_ci	const Unique<VkRenderPass>		renderPass			(makeRenderPass		(vk, device, colorFormat));
439e5c31af7Sopenharmony_ci	const Unique<VkFramebuffer>		framebuffer			(makeFramebuffer	(vk, device, *renderPass, *colorAttachmentView, renderSize.x(), renderSize.y()));
440e5c31af7Sopenharmony_ci	const Unique<VkPipelineLayout>	pipelineLayout		(makePipelineLayout	(vk, device));
441e5c31af7Sopenharmony_ci
442e5c31af7Sopenharmony_ci	const VkCullModeFlags cullMode = VK_CULL_MODE_BACK_BIT;
443e5c31af7Sopenharmony_ci
444e5c31af7Sopenharmony_ci	// Front face is static state, so we have to create two pipelines.
445e5c31af7Sopenharmony_ci
446e5c31af7Sopenharmony_ci	const Unique<VkPipeline> pipelineCounterClockwise(GraphicsPipelineBuilder()
447e5c31af7Sopenharmony_ci		.setCullModeFlags				(cullMode)
448e5c31af7Sopenharmony_ci		.setFrontFace					(VK_FRONT_FACE_COUNTER_CLOCKWISE)
449e5c31af7Sopenharmony_ci		.setShader						(vk, device, VK_SHADER_STAGE_VERTEX_BIT,					m_context.getBinaryCollection().get("vert"), DE_NULL)
450e5c31af7Sopenharmony_ci		.setShader						(vk, device, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,		m_context.getBinaryCollection().get("tesc"), DE_NULL)
451e5c31af7Sopenharmony_ci		.setShader						(vk, device, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,	m_context.getBinaryCollection().get("tese"), DE_NULL)
452e5c31af7Sopenharmony_ci		.setShader						(vk, device, VK_SHADER_STAGE_FRAGMENT_BIT,					m_context.getBinaryCollection().get("frag"), DE_NULL)
453e5c31af7Sopenharmony_ci		.setTessellationDomainOrigin	(m_domainOrigin)
454e5c31af7Sopenharmony_ci		.build							(vk, device, *pipelineLayout, *renderPass));
455e5c31af7Sopenharmony_ci
456e5c31af7Sopenharmony_ci	const Unique<VkPipeline> pipelineClockwise(GraphicsPipelineBuilder()
457e5c31af7Sopenharmony_ci		.setCullModeFlags				(cullMode)
458e5c31af7Sopenharmony_ci		.setFrontFace					(VK_FRONT_FACE_CLOCKWISE)
459e5c31af7Sopenharmony_ci		.setShader						(vk, device, VK_SHADER_STAGE_VERTEX_BIT,					m_context.getBinaryCollection().get("vert"), DE_NULL)
460e5c31af7Sopenharmony_ci		.setShader						(vk, device, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,		m_context.getBinaryCollection().get("tesc"), DE_NULL)
461e5c31af7Sopenharmony_ci		.setShader						(vk, device, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,	m_context.getBinaryCollection().get("tese"), DE_NULL)
462e5c31af7Sopenharmony_ci		.setShader						(vk, device, VK_SHADER_STAGE_FRAGMENT_BIT,					m_context.getBinaryCollection().get("frag"), DE_NULL)
463e5c31af7Sopenharmony_ci		.setTessellationDomainOrigin	(m_domainOrigin)
464e5c31af7Sopenharmony_ci		.build							(vk, device, *pipelineLayout, *renderPass));
465e5c31af7Sopenharmony_ci
466e5c31af7Sopenharmony_ci	const struct // not static
467e5c31af7Sopenharmony_ci	{
468e5c31af7Sopenharmony_ci		Winding		frontFaceWinding;
469e5c31af7Sopenharmony_ci		VkPipeline	pipeline;
470e5c31af7Sopenharmony_ci	} testCases[] =
471e5c31af7Sopenharmony_ci	{
472e5c31af7Sopenharmony_ci		{ WINDING_CCW,	*pipelineCounterClockwise },
473e5c31af7Sopenharmony_ci		{ WINDING_CW,	*pipelineClockwise		  },
474e5c31af7Sopenharmony_ci	};
475e5c31af7Sopenharmony_ci
476e5c31af7Sopenharmony_ci	tcu::TestLog& log = m_context.getTestContext().getLog();
477e5c31af7Sopenharmony_ci	log << tcu::TestLog::Message << "Pipeline uses " << getCullModeFlagsStr(cullMode) << tcu::TestLog::EndMessage;
478e5c31af7Sopenharmony_ci
479e5c31af7Sopenharmony_ci	bool success = true;
480e5c31af7Sopenharmony_ci
481e5c31af7Sopenharmony_ci	// Draw commands
482e5c31af7Sopenharmony_ci
483e5c31af7Sopenharmony_ci	const Unique<VkCommandPool>   cmdPool  (makeCommandPool  (vk, device, queueFamilyIndex));
484e5c31af7Sopenharmony_ci	const Unique<VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
485e5c31af7Sopenharmony_ci
486e5c31af7Sopenharmony_ci	for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(testCases); ++caseNdx)
487e5c31af7Sopenharmony_ci	{
488e5c31af7Sopenharmony_ci		const Winding frontFaceWinding = testCases[caseNdx].frontFaceWinding;
489e5c31af7Sopenharmony_ci
490e5c31af7Sopenharmony_ci		log << tcu::TestLog::Message << "Setting " << getFrontFaceName(mapFrontFace(frontFaceWinding)) << tcu::TestLog::EndMessage;
491e5c31af7Sopenharmony_ci
492e5c31af7Sopenharmony_ci		// Reset the command buffer and begin.
493e5c31af7Sopenharmony_ci		beginCommandBuffer(vk, *cmdBuffer);
494e5c31af7Sopenharmony_ci
495e5c31af7Sopenharmony_ci		// Change color attachment image layout
496e5c31af7Sopenharmony_ci		{
497e5c31af7Sopenharmony_ci			// State is slightly different on the first iteration.
498e5c31af7Sopenharmony_ci			const VkImageLayout currentLayout = (caseNdx == 0 ? VK_IMAGE_LAYOUT_UNDEFINED : VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
499e5c31af7Sopenharmony_ci			const VkAccessFlags srcFlags	  = (caseNdx == 0 ? (VkAccessFlags)0          : (VkAccessFlags)VK_ACCESS_TRANSFER_READ_BIT);
500e5c31af7Sopenharmony_ci
501e5c31af7Sopenharmony_ci			const VkImageMemoryBarrier colorAttachmentLayoutBarrier = makeImageMemoryBarrier(
502e5c31af7Sopenharmony_ci				srcFlags, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
503e5c31af7Sopenharmony_ci				currentLayout, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
504e5c31af7Sopenharmony_ci				*colorAttachmentImage, colorImageSubresourceRange);
505e5c31af7Sopenharmony_ci
506e5c31af7Sopenharmony_ci			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
507e5c31af7Sopenharmony_ci				0u, DE_NULL, 0u, DE_NULL, 1u, &colorAttachmentLayoutBarrier);
508e5c31af7Sopenharmony_ci		}
509e5c31af7Sopenharmony_ci
510e5c31af7Sopenharmony_ci		// Begin render pass
511e5c31af7Sopenharmony_ci		{
512e5c31af7Sopenharmony_ci			const VkRect2D	renderArea	= makeRect2D(renderSize);
513e5c31af7Sopenharmony_ci			const tcu::Vec4	clearColor	= tcu::RGBA::red().toVec();
514e5c31af7Sopenharmony_ci
515e5c31af7Sopenharmony_ci			beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor);
516e5c31af7Sopenharmony_ci		}
517e5c31af7Sopenharmony_ci
518e5c31af7Sopenharmony_ci		const VkViewport viewport =
519e5c31af7Sopenharmony_ci		{
520e5c31af7Sopenharmony_ci			0.0f,															// float	x;
521e5c31af7Sopenharmony_ci			m_yFlip ? static_cast<float>(renderSize.y()) : 0.0f,			// float	y;
522e5c31af7Sopenharmony_ci			static_cast<float>(renderSize.x()),								// float	width;
523e5c31af7Sopenharmony_ci			static_cast<float>(m_yFlip ? -renderSize.y() : renderSize.y()),	// float	height;
524e5c31af7Sopenharmony_ci			0.0f,															// float	minDepth;
525e5c31af7Sopenharmony_ci			1.0f,															// float	maxDepth;
526e5c31af7Sopenharmony_ci		};
527e5c31af7Sopenharmony_ci		vk.cmdSetViewport(*cmdBuffer, 0, 1, &viewport);
528e5c31af7Sopenharmony_ci
529e5c31af7Sopenharmony_ci		const VkRect2D scissor = makeRect2D(renderSize);
530e5c31af7Sopenharmony_ci		vk.cmdSetScissor(*cmdBuffer, 0, 1, &scissor);
531e5c31af7Sopenharmony_ci
532e5c31af7Sopenharmony_ci		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, testCases[caseNdx].pipeline);
533e5c31af7Sopenharmony_ci
534e5c31af7Sopenharmony_ci		// Process a single abstract vertex.
535e5c31af7Sopenharmony_ci		vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u);
536e5c31af7Sopenharmony_ci		endRenderPass(vk, *cmdBuffer);
537e5c31af7Sopenharmony_ci
538e5c31af7Sopenharmony_ci		// Copy render result to a host-visible buffer
539e5c31af7Sopenharmony_ci		copyImageToBuffer(vk, *cmdBuffer, *colorAttachmentImage, *colorBuffer, renderSize);
540e5c31af7Sopenharmony_ci
541e5c31af7Sopenharmony_ci		endCommandBuffer(vk, *cmdBuffer);
542e5c31af7Sopenharmony_ci		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
543e5c31af7Sopenharmony_ci
544e5c31af7Sopenharmony_ci		{
545e5c31af7Sopenharmony_ci			// Log rendered image
546e5c31af7Sopenharmony_ci			const Allocation&					colorBufferAlloc	= colorBuffer.getAllocation();
547e5c31af7Sopenharmony_ci
548e5c31af7Sopenharmony_ci			invalidateAlloc(vk, device, colorBufferAlloc);
549e5c31af7Sopenharmony_ci
550e5c31af7Sopenharmony_ci			const tcu::ConstPixelBufferAccess	imagePixelAccess	(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAlloc.getHostPtr());
551e5c31af7Sopenharmony_ci
552e5c31af7Sopenharmony_ci			log << tcu::TestLog::Image("color0", "Rendered image", imagePixelAccess);
553e5c31af7Sopenharmony_ci
554e5c31af7Sopenharmony_ci			// Verify case result
555e5c31af7Sopenharmony_ci			success = verifyResultImage(log,
556e5c31af7Sopenharmony_ci										imagePixelAccess,
557e5c31af7Sopenharmony_ci										m_primitiveType,
558e5c31af7Sopenharmony_ci										!m_domainOrigin ? VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT : *m_domainOrigin,
559e5c31af7Sopenharmony_ci										m_winding,
560e5c31af7Sopenharmony_ci										m_yFlip,
561e5c31af7Sopenharmony_ci										frontFaceWinding) && success;
562e5c31af7Sopenharmony_ci		}
563e5c31af7Sopenharmony_ci	}  // for windingNdx
564e5c31af7Sopenharmony_ci
565e5c31af7Sopenharmony_ci	return (success ? tcu::TestStatus::pass("OK") : tcu::TestStatus::fail("Failure"));
566e5c31af7Sopenharmony_ci}
567e5c31af7Sopenharmony_ci
568e5c31af7Sopenharmony_ciTestInstance* WindingTest::createInstance (Context& context) const
569e5c31af7Sopenharmony_ci{
570e5c31af7Sopenharmony_ci	requireFeatures(context.getInstanceInterface(), context.getPhysicalDevice(), FEATURE_TESSELLATION_SHADER);
571e5c31af7Sopenharmony_ci
572e5c31af7Sopenharmony_ci	return new WindingTestInstance(context, m_primitiveType, m_domainOrigin, m_winding, m_yFlip);
573e5c31af7Sopenharmony_ci}
574e5c31af7Sopenharmony_ci
575e5c31af7Sopenharmony_civoid populateWindingGroup (tcu::TestCaseGroup* group, tcu::Maybe<VkTessellationDomainOrigin> domainOrigin)
576e5c31af7Sopenharmony_ci{
577e5c31af7Sopenharmony_ci	static const TessPrimitiveType primitivesNoIsolines[] =
578e5c31af7Sopenharmony_ci	{
579e5c31af7Sopenharmony_ci		TESSPRIMITIVETYPE_TRIANGLES,
580e5c31af7Sopenharmony_ci		TESSPRIMITIVETYPE_QUADS,
581e5c31af7Sopenharmony_ci	};
582e5c31af7Sopenharmony_ci
583e5c31af7Sopenharmony_ci	static const ShaderLanguage shaderLanguage[] =
584e5c31af7Sopenharmony_ci	{
585e5c31af7Sopenharmony_ci		SHADER_LANGUAGE_GLSL,
586e5c31af7Sopenharmony_ci		SHADER_LANGUAGE_HLSL,
587e5c31af7Sopenharmony_ci	};
588e5c31af7Sopenharmony_ci
589e5c31af7Sopenharmony_ci	for (int primitiveTypeNdx = 0; primitiveTypeNdx < DE_LENGTH_OF_ARRAY(primitivesNoIsolines); ++primitiveTypeNdx)
590e5c31af7Sopenharmony_ci	for (int shaderLanguageNdx = 0; shaderLanguageNdx < DE_LENGTH_OF_ARRAY(shaderLanguage); ++shaderLanguageNdx)
591e5c31af7Sopenharmony_ci	for (int windingNdx = 0; windingNdx < WINDING_LAST; ++windingNdx)
592e5c31af7Sopenharmony_ci	{
593e5c31af7Sopenharmony_ci		group->addChild(new WindingTest(group->getTestContext(), primitivesNoIsolines[primitiveTypeNdx], domainOrigin, shaderLanguage[shaderLanguageNdx], (Winding)windingNdx, false));
594e5c31af7Sopenharmony_ci		group->addChild(new WindingTest(group->getTestContext(), primitivesNoIsolines[primitiveTypeNdx], domainOrigin, shaderLanguage[shaderLanguageNdx], (Winding)windingNdx, true));
595e5c31af7Sopenharmony_ci	}
596e5c31af7Sopenharmony_ci}
597e5c31af7Sopenharmony_ci
598e5c31af7Sopenharmony_ci} // anonymous
599e5c31af7Sopenharmony_ci
600e5c31af7Sopenharmony_ci//! These tests correspond to dEQP-GLES31.functional.tessellation.winding.*
601e5c31af7Sopenharmony_citcu::TestCaseGroup* createWindingTests (tcu::TestContext& testCtx)
602e5c31af7Sopenharmony_ci{
603e5c31af7Sopenharmony_ci	// Test the cw and ccw input layout qualifiers
604e5c31af7Sopenharmony_ci	de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "winding"));
605e5c31af7Sopenharmony_ci
606e5c31af7Sopenharmony_ci	// No tessellation domain specified
607e5c31af7Sopenharmony_ci	addTestGroup(group.get(), "default_domain", populateWindingGroup,	tcu::nothing<VkTessellationDomainOrigin>());
608e5c31af7Sopenharmony_ci	// Lower left tessellation domain
609e5c31af7Sopenharmony_ci	addTestGroup(group.get(), "lower_left_domain", populateWindingGroup,	tcu::just(VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT));
610e5c31af7Sopenharmony_ci	// Upper left tessellation domain
611e5c31af7Sopenharmony_ci	addTestGroup(group.get(), "upper_left_domain", populateWindingGroup,	tcu::just(VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT));
612e5c31af7Sopenharmony_ci
613e5c31af7Sopenharmony_ci	return group.release();
614e5c31af7Sopenharmony_ci}
615e5c31af7Sopenharmony_ci
616e5c31af7Sopenharmony_ci} // tessellation
617e5c31af7Sopenharmony_ci} // vkt
618