1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2014 The Android Open Source Project
6  * Copyright (c) 2016 The Khronos Group Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Tessellation Shader Input/Output Tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktTessellationShaderInputOutputTests.hpp"
26 #include "vktTestCaseUtil.hpp"
27 #include "vktTessellationUtil.hpp"
28 
29 #include "tcuTestLog.hpp"
30 #include "tcuImageIO.hpp"
31 #include "tcuTexture.hpp"
32 #include "tcuImageCompare.hpp"
33 
34 #include "vkDefs.hpp"
35 #include "vkBarrierUtil.hpp"
36 #include "vkQueryUtil.hpp"
37 #include "vkBuilderUtil.hpp"
38 #include "vkImageUtil.hpp"
39 #include "vkTypeUtil.hpp"
40 #include "vkStrUtil.hpp"
41 #include "vkCmdUtil.hpp"
42 #include "vkObjUtil.hpp"
43 
44 #include "deUniquePtr.hpp"
45 #include "deStringUtil.hpp"
46 
47 #include <string>
48 #include <vector>
49 
50 namespace vkt
51 {
52 namespace tessellation
53 {
54 
55 using namespace vk;
56 
57 namespace
58 {
59 
60 enum Constants
61 {
62 	RENDER_SIZE = 256,
63 };
64 
65 //! Generic test code used by all test cases.
runTest(Context & context,const int numPrimitives,const int inPatchSize,const int outPatchSize,const VkFormat vertexFormat,const void * vertexData,const VkDeviceSize vertexDataSizeBytes,const tcu::ConstPixelBufferAccess & referenceImageAccess)66 tcu::TestStatus runTest (Context&							context,
67 						 const int							numPrimitives,
68 						 const int							inPatchSize,
69 						 const int							outPatchSize,
70 						 const VkFormat						vertexFormat,
71 						 const void*						vertexData,
72 						 const VkDeviceSize					vertexDataSizeBytes,
73 						 const tcu::ConstPixelBufferAccess&	referenceImageAccess)
74 {
75 	requireFeatures(context.getInstanceInterface(), context.getPhysicalDevice(), FEATURE_TESSELLATION_SHADER);
76 
77 	const DeviceInterface&	vk					= context.getDeviceInterface();
78 	const VkDevice			device				= context.getDevice();
79 	const VkQueue			queue				= context.getUniversalQueue();
80 	const deUint32			queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
81 	Allocator&				allocator			= context.getDefaultAllocator();
82 
83 	// Vertex input: may be just some abstract numbers
84 
85 	const Buffer vertexBuffer(vk, device, allocator,
86 		makeBufferCreateInfo(vertexDataSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible);
87 
88 	{
89 		const Allocation& alloc = vertexBuffer.getAllocation();
90 		deMemcpy(alloc.getHostPtr(), vertexData, static_cast<std::size_t>(vertexDataSizeBytes));
91 
92 		flushMappedMemoryRange(vk, device, alloc.getMemory(), alloc.getOffset(), vertexDataSizeBytes);
93 		// No barrier needed, flushed memory is automatically visible
94 	}
95 
96 	// Color attachment
97 
98 	const tcu::IVec2			  renderSize				 = tcu::IVec2(RENDER_SIZE, RENDER_SIZE);
99 	const VkFormat				  colorFormat				 = VK_FORMAT_R8G8B8A8_UNORM;
100 	const VkImageSubresourceRange colorImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
101 	const Image					  colorAttachmentImage		 (vk, device, allocator,
102 															 makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 1u),
103 															 MemoryRequirement::Any);
104 
105 	// Color output buffer: image will be copied here for verification
106 
107 	const VkDeviceSize	colorBufferSizeBytes = renderSize.x()*renderSize.y() * tcu::getPixelSize(mapVkFormat(colorFormat));
108 	const Buffer		colorBuffer			 (vk, device, allocator, makeBufferCreateInfo(colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible);
109 
110 	// Pipeline
111 
112 	const Unique<VkImageView>		colorAttachmentView(makeImageView						(vk, device, *colorAttachmentImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorImageSubresourceRange));
113 	const Unique<VkRenderPass>		renderPass		   (makeRenderPass						(vk, device, colorFormat));
114 	const Unique<VkFramebuffer>		framebuffer		   (makeFramebuffer						(vk, device, *renderPass, *colorAttachmentView, renderSize.x(), renderSize.y(), 1u));
115 	const Unique<VkPipelineLayout>	pipelineLayout	   (makePipelineLayoutWithoutDescriptors(vk, device));
116 	const Unique<VkCommandPool>		cmdPool			   (makeCommandPool						(vk, device, queueFamilyIndex));
117 	const Unique<VkCommandBuffer>	cmdBuffer		   (allocateCommandBuffer				(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
118 
119 	const Unique<VkPipeline> pipeline(GraphicsPipelineBuilder()
120 		.setRenderSize				  (renderSize)
121 		.setVertexInputSingleAttribute(vertexFormat, tcu::getPixelSize(mapVkFormat(vertexFormat)))
122 		.setPatchControlPoints		  (inPatchSize)
123 		.setShader					  (vk, device, VK_SHADER_STAGE_VERTEX_BIT,					context.getBinaryCollection().get("vert"), DE_NULL)
124 		.setShader					  (vk, device, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,	context.getBinaryCollection().get("tesc"), DE_NULL)
125 		.setShader					  (vk, device, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, context.getBinaryCollection().get("tese"), DE_NULL)
126 		.setShader					  (vk, device, VK_SHADER_STAGE_FRAGMENT_BIT,				context.getBinaryCollection().get("frag"), DE_NULL)
127 		.build						  (vk, device, *pipelineLayout, *renderPass));
128 
129 	{
130 		tcu::TestLog& log = context.getTestContext().getLog();
131 		log << tcu::TestLog::Message
132 			<< "Note: input patch size is " << inPatchSize << ", output patch size is " << outPatchSize
133 			<< tcu::TestLog::EndMessage;
134 	}
135 
136 	// Draw commands
137 
138 	beginCommandBuffer(vk, *cmdBuffer);
139 
140 	// Change color attachment image layout
141 	{
142 		const VkImageMemoryBarrier colorAttachmentLayoutBarrier = makeImageMemoryBarrier(
143 			(VkAccessFlags)0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
144 			VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
145 			*colorAttachmentImage, colorImageSubresourceRange);
146 
147 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
148 			0u, DE_NULL, 0u, DE_NULL, 1u, &colorAttachmentLayoutBarrier);
149 	}
150 
151 	// Begin render pass
152 	{
153 		const VkRect2D	renderArea	= makeRect2D(renderSize);
154 		const tcu::Vec4	clearColor	(0.0f, 0.0f, 0.0f, 1.0f);
155 
156 		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor);
157 	}
158 
159 	vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
160 	{
161 		const VkDeviceSize vertexBufferOffset = 0ull;
162 		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
163 	}
164 
165 	// Process enough vertices to make a patch.
166 	vk.cmdDraw(*cmdBuffer, numPrimitives * inPatchSize, 1u, 0u, 0u);
167 	endRenderPass(vk, *cmdBuffer);
168 
169 	// Copy render result to a host-visible buffer
170 	copyImageToBuffer(vk, *cmdBuffer, *colorAttachmentImage, *colorBuffer, renderSize);
171 
172 	endCommandBuffer(vk, *cmdBuffer);
173 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
174 
175 	{
176 		const Allocation& colorBufferAlloc = colorBuffer.getAllocation();
177 		invalidateMappedMemoryRange(vk, device, colorBufferAlloc.getMemory(), colorBufferAlloc.getOffset(), colorBufferSizeBytes);
178 
179 		// Verify case result
180 		const tcu::ConstPixelBufferAccess resultImageAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAlloc.getHostPtr());
181 		tcu::TestLog& log = context.getTestContext().getLog();
182 		const bool ok = tcu::fuzzyCompare(log, "ImageComparison", "Image Comparison", referenceImageAccess, resultImageAccess, 0.002f, tcu::COMPARE_LOG_RESULT);
183 
184 		return (ok ? tcu::TestStatus::pass("OK") : tcu::TestStatus::fail("Failure"));
185 	}
186 }
187 
188 //! Resize an image and fill with white color.
initializeWhiteReferenceImage(tcu::TextureLevel & image,const int width,const int height)189 void initializeWhiteReferenceImage (tcu::TextureLevel& image, const int width, const int height)
190 {
191 	DE_ASSERT(width > 0 && height > 0);
192 
193 	image.setStorage(mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM), width, height);
194 	tcu::PixelBufferAccess access = image.getAccess();
195 
196 	const tcu::Vec4 white(1.0f, 1.0f, 1.0f, 1.0f);
197 
198 	for (int y = 0; y < height; ++y)
199 	for (int x = 0; x < width; ++x)
200 		access.setPixel(white, x, y);
201 }
202 
203 namespace PatchVertexCount
204 {
205 
206 struct CaseDefinition
207 {
208 	int				inPatchSize;
209 	int				outPatchSize;
210 	std::string		referenceImagePath;
211 };
212 
initPrograms(vk::SourceCollections & programCollection,const CaseDefinition caseDef)213 void initPrograms (vk::SourceCollections& programCollection, const CaseDefinition caseDef)
214 {
215 	// Vertex shader
216 	{
217 		std::ostringstream src;
218 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
219 			<< "\n"
220 			<< "layout(location = 0) in  highp float in_v_attr;\n"
221 			<< "layout(location = 0) out highp float in_tc_attr;\n"
222 			<< "\n"
223 			<< "void main (void)\n"
224 			<< "{\n"
225 			<< "    in_tc_attr = in_v_attr;\n"
226 			<< "}\n";
227 
228 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
229 	}
230 
231 	// Tessellation control shader
232 	{
233 		std::ostringstream src;
234 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
235 			<< "#extension GL_EXT_tessellation_shader : require\n"
236 			<< "\n"
237 			<< "layout(vertices = " << caseDef.outPatchSize << ") out;\n"
238 			<< "\n"
239 			<< "layout(location = 0) in  highp float in_tc_attr[];\n"
240 			<< "layout(location = 0) out highp float in_te_attr[];\n"
241 			<< "\n"
242 			<< "void main (void)\n"
243 			<< "{\n"
244 			<< "    in_te_attr[gl_InvocationID] = in_tc_attr[gl_InvocationID*" << caseDef.inPatchSize << "/" << caseDef.outPatchSize << "];\n"
245 			<< "\n"
246 			<< "    gl_TessLevelInner[0] = 5.0;\n"
247 			<< "    gl_TessLevelInner[1] = 5.0;\n"
248 			<< "\n"
249 			<< "    gl_TessLevelOuter[0] = 5.0;\n"
250 			<< "    gl_TessLevelOuter[1] = 5.0;\n"
251 			<< "    gl_TessLevelOuter[2] = 5.0;\n"
252 			<< "    gl_TessLevelOuter[3] = 5.0;\n"
253 			<< "}\n";
254 
255 		programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
256 	}
257 
258 	// Tessellation evaluation shader
259 	{
260 		std::ostringstream src;
261 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
262 			<< "#extension GL_EXT_tessellation_shader : require\n"
263 			<< "\n"
264 			<< "layout(" << getTessPrimitiveTypeShaderName(TESSPRIMITIVETYPE_QUADS) << ") in;\n"
265 			<< "\n"
266 			<< "layout(location = 0) in  highp   float in_te_attr[];\n"
267 			<< "layout(location = 0) out mediump vec4  in_f_color;\n"
268 			<< "\n"
269 			<< "void main (void)\n"
270 			<< "{\n"
271 			<< "    highp float x = gl_TessCoord.x*2.0 - 1.0;\n"
272 			<< "    highp float y = gl_TessCoord.y - in_te_attr[int(round(gl_TessCoord.x*float(" << caseDef.outPatchSize << "-1)))];\n"
273 			<< "    gl_Position = vec4(x, y, 0.0, 1.0);\n"
274 			<< "    in_f_color = vec4(1.0);\n"
275 			<< "}\n";
276 
277 		programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
278 	}
279 
280 	// Fragment shader
281 	{
282 		std::ostringstream src;
283 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
284 			<< "\n"
285 			<< "layout(location = 0) in  mediump vec4 in_f_color;\n"
286 			<< "layout(location = 0) out mediump vec4 o_color;\n"
287 			<< "\n"
288 			<< "void main (void)\n"
289 			<< "{\n"
290 			<< "    o_color = in_f_color;\n"
291 			<< "}\n";
292 
293 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
294 	}
295 }
296 
test(Context & context,const CaseDefinition caseDef)297 tcu::TestStatus test (Context& context, const CaseDefinition caseDef)
298 {
299 	// Input vertex attribute data
300 	std::vector<float> vertexData;
301 	vertexData.reserve(caseDef.inPatchSize);
302 	for (int i = 0; i < caseDef.inPatchSize; ++i)
303 	{
304 		const float f = static_cast<float>(i) / static_cast<float>(caseDef.inPatchSize - 1);
305 		vertexData.push_back(f*f);
306 	}
307 	const VkDeviceSize vertexBufferSize = sizeof(float) * vertexData.size();
308 
309 	// Load reference image
310 	tcu::TextureLevel referenceImage;
311 	tcu::ImageIO::loadPNG(referenceImage, context.getTestContext().getArchive(), caseDef.referenceImagePath.c_str());
312 
313 	const int numPrimitives = 1;
314 
315 	return runTest(context, numPrimitives, caseDef.inPatchSize, caseDef.outPatchSize,
316 				   VK_FORMAT_R32_SFLOAT, &vertexData[0], vertexBufferSize, referenceImage.getAccess());
317 }
318 
319 } // PatchVertexCountTest ns
320 
321 namespace PerPatchData
322 {
323 
324 enum CaseType
325 {
326 	CASETYPE_PRIMITIVE_ID_TCS,
327 	CASETYPE_PRIMITIVE_ID_TES,
328 	CASETYPE_PATCH_VERTICES_IN_TCS,
329 	CASETYPE_PATCH_VERTICES_IN_TES,
330 	CASETYPE_TESS_LEVEL_INNER0_TES,
331 	CASETYPE_TESS_LEVEL_INNER1_TES,
332 	CASETYPE_TESS_LEVEL_OUTER0_TES,
333 	CASETYPE_TESS_LEVEL_OUTER1_TES,
334 	CASETYPE_TESS_LEVEL_OUTER2_TES,
335 	CASETYPE_TESS_LEVEL_OUTER3_TES,
336 };
337 
338 enum Constants
339 {
340 	OUTPUT_PATCH_SIZE	= 5,
341 	INPUT_PATCH_SIZE	= 10,
342 };
343 
344 struct CaseDefinition
345 {
346 	CaseType		caseType;
347 	std::string		caseName;
348 	bool			usesReferenceImageFromFile;
349 	std::string		referenceImagePath;
350 	std::string		caseDescription;
351 };
352 
getNumPrimitives(const CaseType type)353 int getNumPrimitives (const CaseType type)
354 {
355 	return (type == CASETYPE_PRIMITIVE_ID_TCS || type == CASETYPE_PRIMITIVE_ID_TES ? 8 : 1);
356 }
357 
initPrograms(vk::SourceCollections & programCollection,const CaseDefinition caseDef)358 void initPrograms (vk::SourceCollections& programCollection, const CaseDefinition caseDef)
359 {
360 	// Vertex shader
361 	{
362 		std::ostringstream src;
363 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
364 			<< "\n"
365 			<< "layout(location = 0) in  highp float in_v_attr;\n"
366 			<< "layout(location = 0) out highp float in_tc_attr;\n"
367 			<< "\n"
368 			<< "void main (void)\n"
369 			<< "{\n"
370 			<< "    in_tc_attr = in_v_attr;\n"
371 			<< "}\n";
372 
373 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
374 	}
375 
376 	// Tessellation control shader
377 	{
378 		std::ostringstream src;
379 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
380 			<< "#extension GL_EXT_tessellation_shader : require\n"
381 			<< "\n"
382 			<< "layout(vertices = " << OUTPUT_PATCH_SIZE << ") out;\n"
383 			<< "\n"
384 			<< "layout(location = 0) in  highp float in_tc_attr[];\n"
385 			<< "layout(location = 0) out highp float in_te_attr[];\n"
386 			<< "\n"
387 			<< (caseDef.caseType == CASETYPE_PRIMITIVE_ID_TCS	   ? "layout(location = 1) patch out mediump int in_te_primitiveIDFromTCS;\n" :
388 				caseDef.caseType == CASETYPE_PATCH_VERTICES_IN_TCS ? "layout(location = 1) patch out mediump int in_te_patchVerticesInFromTCS;\n" : "")
389 			<< "\n"
390 			<< "void main (void)\n"
391 			<< "{\n"
392 			<< "    in_te_attr[gl_InvocationID] = in_tc_attr[gl_InvocationID];\n"
393 			<< (caseDef.caseType == CASETYPE_PRIMITIVE_ID_TCS	   ? "    in_te_primitiveIDFromTCS = gl_PrimitiveID;\n" :
394 				caseDef.caseType == CASETYPE_PATCH_VERTICES_IN_TCS ? "    in_te_patchVerticesInFromTCS = gl_PatchVerticesIn;\n" : "")
395 			<< "\n"
396 			<< "    gl_TessLevelInner[0] = 9.0;\n"
397 			<< "    gl_TessLevelInner[1] = 8.0;\n"
398 			<< "\n"
399 			<< "    gl_TessLevelOuter[0] = 7.0;\n"
400 			<< "    gl_TessLevelOuter[1] = 6.0;\n"
401 			<< "    gl_TessLevelOuter[2] = 5.0;\n"
402 			<< "    gl_TessLevelOuter[3] = 4.0;\n"
403 			<< "}\n";
404 
405 		programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
406 	}
407 
408 	// Tessellation evaluation shader
409 	{
410 		const float xScale = 1.0f / static_cast<float>(getNumPrimitives(caseDef.caseType));
411 
412 		std::ostringstream src;
413 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
414 			<< "#extension GL_EXT_tessellation_shader : require\n"
415 			<< "\n"
416 			<< "layout(" << getTessPrimitiveTypeShaderName(TESSPRIMITIVETYPE_QUADS) << ") in;\n"
417 			<< "\n"
418 			<< "layout(location = 0) in  highp   float in_te_attr[];\n"
419 			<< "layout(location = 0) out mediump vec4  in_f_color;\n"
420 			<< "\n"
421 			<< (caseDef.caseType == CASETYPE_PRIMITIVE_ID_TCS	   ? "layout(location = 1) patch in mediump int in_te_primitiveIDFromTCS;\n" :
422 				caseDef.caseType == CASETYPE_PATCH_VERTICES_IN_TCS ? "layout(location = 1) patch in mediump int in_te_patchVerticesInFromTCS;\n" : "")
423 			<< "\n"
424 			<< "void main (void)\n"
425 			<< "{\n"
426 			<< "    highp float x = (gl_TessCoord.x*float(" << xScale << ") + in_te_attr[0]) * 2.0 - 1.0;\n"
427 			<< "    highp float y = gl_TessCoord.y*2.0 - 1.0;\n"
428 			<< "    gl_Position = vec4(x, y, 0.0, 1.0);\n"
429 			<< (caseDef.caseType == CASETYPE_PRIMITIVE_ID_TCS		? "    bool ok = in_te_primitiveIDFromTCS == 3;\n" :
430 				caseDef.caseType == CASETYPE_PRIMITIVE_ID_TES		? "    bool ok = gl_PrimitiveID == 3;\n" :
431 				caseDef.caseType == CASETYPE_PATCH_VERTICES_IN_TCS	? "    bool ok = in_te_patchVerticesInFromTCS == " + de::toString(INPUT_PATCH_SIZE) + ";\n" :
432 				caseDef.caseType == CASETYPE_PATCH_VERTICES_IN_TES	? "    bool ok = gl_PatchVerticesIn == " + de::toString(OUTPUT_PATCH_SIZE) + ";\n" :
433 				caseDef.caseType == CASETYPE_TESS_LEVEL_INNER0_TES	? "    bool ok = abs(gl_TessLevelInner[0] - 9.0) < 0.1f;\n" :
434 				caseDef.caseType == CASETYPE_TESS_LEVEL_INNER1_TES	? "    bool ok = abs(gl_TessLevelInner[1] - 8.0) < 0.1f;\n" :
435 				caseDef.caseType == CASETYPE_TESS_LEVEL_OUTER0_TES	? "    bool ok = abs(gl_TessLevelOuter[0] - 7.0) < 0.1f;\n" :
436 				caseDef.caseType == CASETYPE_TESS_LEVEL_OUTER1_TES	? "    bool ok = abs(gl_TessLevelOuter[1] - 6.0) < 0.1f;\n" :
437 				caseDef.caseType == CASETYPE_TESS_LEVEL_OUTER2_TES	? "    bool ok = abs(gl_TessLevelOuter[2] - 5.0) < 0.1f;\n" :
438 				caseDef.caseType == CASETYPE_TESS_LEVEL_OUTER3_TES	? "    bool ok = abs(gl_TessLevelOuter[3] - 4.0) < 0.1f;\n" : "")
439 			<< "    in_f_color = ok ? vec4(1.0) : vec4(vec3(0.0), 1.0);\n"
440 			<< "}\n";
441 
442 		programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
443 	}
444 
445 	// Fragment shader
446 	{
447 		std::ostringstream src;
448 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
449 			<< "\n"
450 			<< "layout(location = 0) in  mediump vec4 in_f_color;\n"
451 			<< "layout(location = 0) out mediump vec4 o_color;\n"
452 			<< "\n"
453 			<< "void main (void)\n"
454 			<< "{\n"
455 			<< "    o_color = in_f_color;\n"
456 			<< "}\n";
457 
458 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
459 	}
460 }
461 
test(Context & context,const CaseDefinition caseDef)462 tcu::TestStatus test (Context& context, const CaseDefinition caseDef)
463 {
464 	DE_ASSERT(!caseDef.usesReferenceImageFromFile || !caseDef.referenceImagePath.empty());
465 
466 	// Input vertex attribute data
467 	const int		   numPrimitives	= getNumPrimitives(caseDef.caseType);
468 	std::vector<float> vertexData		(INPUT_PATCH_SIZE * numPrimitives, 0.0f);
469 	const VkDeviceSize vertexBufferSize = sizeof(float) * vertexData.size();
470 
471 	for (int i = 0; i < numPrimitives; ++i)
472 		vertexData[INPUT_PATCH_SIZE * i] = static_cast<float>(i) / static_cast<float>(numPrimitives);
473 
474 	tcu::TextureLevel referenceImage;
475 	if (caseDef.usesReferenceImageFromFile)
476 		tcu::ImageIO::loadPNG(referenceImage, context.getTestContext().getArchive(), caseDef.referenceImagePath.c_str());
477 	else
478 		initializeWhiteReferenceImage(referenceImage, RENDER_SIZE, RENDER_SIZE);
479 
480 	return runTest(context, numPrimitives, INPUT_PATCH_SIZE, OUTPUT_PATCH_SIZE,
481 				   VK_FORMAT_R32_SFLOAT, &vertexData[0], vertexBufferSize, referenceImage.getAccess());
482 }
483 
484 } // PerPatchData ns
485 
486 namespace GLPosition
487 {
488 
489 enum CaseType
490 {
491 	CASETYPE_VS_TO_TCS = 0,
492 	CASETYPE_TCS_TO_TES,
493 	CASETYPE_VS_TO_TCS_TO_TES,
494 };
495 
initPrograms(vk::SourceCollections & programCollection,const CaseType caseType)496 void initPrograms (vk::SourceCollections& programCollection, const CaseType caseType)
497 {
498 	const bool vsToTCS  = caseType == CASETYPE_VS_TO_TCS  || caseType == CASETYPE_VS_TO_TCS_TO_TES;
499 	const bool tcsToTES = caseType == CASETYPE_TCS_TO_TES || caseType == CASETYPE_VS_TO_TCS_TO_TES;
500 
501 	// Vertex shader
502 	{
503 		std::ostringstream src;
504 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
505 			<< "\n"
506 			<< "layout(location = 0) in  highp vec4 in_v_attr;\n"
507 			<< (!vsToTCS ? "layout(location = 0) out highp vec4 in_tc_attr;\n" : "")
508 			<< "\n"
509 			<< "void main (void)\n"
510 			<< "{\n"
511 			<< "    " << (vsToTCS ? "gl_Position" : "in_tc_attr") << " = in_v_attr;\n"
512 			<< "}\n";
513 
514 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
515 	}
516 
517 	// Tessellation control shader
518 	{
519 		std::ostringstream src;
520 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
521 			<< "#extension GL_EXT_tessellation_shader : require\n"
522 			<< "\n"
523 			<< "layout(vertices = 3) out;\n"
524 			<< "\n"
525 			<< (!vsToTCS  ? "layout(location = 0) in  highp vec4 in_tc_attr[];\n" : "")
526 			<< (!tcsToTES ? "layout(location = 0) out highp vec4 in_te_attr[];\n" : "")
527 			<< "\n"
528 			<< "void main (void)\n"
529 			<< "{\n"
530 			<< "    " << (tcsToTES ? "gl_out[gl_InvocationID].gl_Position" : "in_te_attr[gl_InvocationID]") << " = "
531 					  << (vsToTCS  ? "gl_in[gl_InvocationID].gl_Position" : "in_tc_attr[gl_InvocationID]") << ";\n"
532 			<< "\n"
533 			<< "    gl_TessLevelInner[0] = 2.0;\n"
534 			<< "    gl_TessLevelInner[1] = 3.0;\n"
535 			<< "\n"
536 			<< "    gl_TessLevelOuter[0] = 4.0;\n"
537 			<< "    gl_TessLevelOuter[1] = 5.0;\n"
538 			<< "    gl_TessLevelOuter[2] = 6.0;\n"
539 			<< "    gl_TessLevelOuter[3] = 7.0;\n"
540 			<< "}\n";
541 
542 		programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
543 	}
544 
545 	// Tessellation evaluation shader
546 	{
547 		const std::string tesIn0 = tcsToTES ? "gl_in[0].gl_Position" : "in_te_attr[0]";
548 		const std::string tesIn1 = tcsToTES ? "gl_in[1].gl_Position" : "in_te_attr[1]";
549 		const std::string tesIn2 = tcsToTES ? "gl_in[2].gl_Position" : "in_te_attr[2]";
550 
551 		std::ostringstream src;
552 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
553 			<< "#extension GL_EXT_tessellation_shader : require\n"
554 			<< "\n"
555 			<< "layout(" << getTessPrimitiveTypeShaderName(TESSPRIMITIVETYPE_TRIANGLES) << ") in;\n"
556 			<< "\n"
557 			<< (!tcsToTES ? "layout(location = 0) in  highp vec4 in_te_attr[];\n" : "")
558 			<< "layout(location = 0) out highp vec4 in_f_color;\n"
559 			<< "\n"
560 			<< "void main (void)\n"
561 			<< "{\n"
562 			<< "    highp vec2 xy = gl_TessCoord.x * " << tesIn0 << ".xy\n"
563 			<< "                  + gl_TessCoord.y * " << tesIn1 << ".xy\n"
564 			<< "                  + gl_TessCoord.z * " << tesIn2 << ".xy;\n"
565 			<< "    gl_Position = vec4(xy, 0.0, 1.0);\n"
566 			<< "    in_f_color = vec4(" << tesIn0 << ".z + " << tesIn1 << ".w,\n"
567 			<< "                      " << tesIn2 << ".z + " << tesIn0 << ".w,\n"
568 			<< "                      " << tesIn1 << ".z + " << tesIn2 << ".w,\n"
569 			<< "                      1.0);\n"
570 			<< "}\n";
571 
572 		programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
573 	}
574 
575 	// Fragment shader
576 	{
577 		std::ostringstream src;
578 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
579 			<< "\n"
580 			<< "layout(location = 0) in  highp   vec4 in_f_color;\n"
581 			<< "layout(location = 0) out mediump vec4 o_color;\n"
582 			<< "\n"
583 			<< "void main (void)\n"
584 			<< "{\n"
585 			<< "    o_color = in_f_color;\n"
586 			<< "}\n";
587 
588 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
589 	}
590 }
591 
test(Context & context,const CaseType caseType)592 tcu::TestStatus test (Context& context, const CaseType caseType)
593 {
594 	DE_UNREF(caseType);
595 
596 	// Input vertex attribute data
597 	static const float vertexData[3*4] =
598 	{
599 		-0.8f, -0.7f, 0.1f, 0.7f,
600 		-0.5f,  0.4f, 0.2f, 0.5f,
601 		 0.3f,  0.2f, 0.3f, 0.45f
602 	};
603 
604 	tcu::TextureLevel referenceImage;
605 	tcu::ImageIO::loadPNG(referenceImage, context.getTestContext().getArchive(), "vulkan/data/tessellation/gl_position_ref.png");
606 
607 	const int numPrimitives = 1;
608 	const int inPatchSize   = 3;
609 	const int outPatchSize  = 3;
610 
611 	return runTest(context, numPrimitives, inPatchSize, outPatchSize,
612 				   VK_FORMAT_R32G32B32A32_SFLOAT, vertexData, sizeof(vertexData), referenceImage.getAccess());
613 }
614 
615 } // GLPosition ns
616 
617 namespace Barrier
618 {
619 
620 enum Constants
621 {
622 	NUM_VERTICES = 32,
623 };
624 
initPrograms(vk::SourceCollections & programCollection)625 void initPrograms (vk::SourceCollections& programCollection)
626 {
627 	// Vertex shader
628 	{
629 		std::ostringstream src;
630 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
631 			<< "\n"
632 			<< "layout(location = 0) in  highp float in_v_attr;\n"
633 			<< "layout(location = 0) out highp float in_tc_attr;\n"
634 			<< "\n"
635 			<< "void main (void)\n"
636 			<< "{\n"
637 			<< "    in_tc_attr = in_v_attr;\n"
638 			<< "}\n";
639 
640 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
641 	}
642 
643 	// Tessellation control shader
644 	{
645 		std::ostringstream src;
646 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
647 			<< "#extension GL_EXT_tessellation_shader : require\n"
648 			<< "\n"
649 			<< "layout(vertices = " << NUM_VERTICES << ") out;\n"
650 			<< "\n"
651 			<< "layout(location = 0) in  highp float in_tc_attr[];\n"
652 			<< "layout(location = 0) out highp float in_te_attr[];\n"
653 			<< "\n"
654 			<< "layout(location = 1) patch out highp float in_te_patchAttr;\n"
655 			<< "\n"
656 			<< "void main (void)\n"
657 			<< "{\n"
658 			<< "    in_te_attr[gl_InvocationID] = in_tc_attr[gl_InvocationID];\n"
659 			<< "    in_te_patchAttr = 0.0f;\n"
660 			<< "\n"
661 			<< "    barrier();\n"
662 			<< "\n"
663 			<< "    if (gl_InvocationID == 5)\n"
664 			<< "		in_te_patchAttr = float(gl_InvocationID)*0.1;\n"
665 			<< "\n"
666 			<< "    barrier();\n"
667 			<< "\n"
668 			<< "    highp float temp = in_te_patchAttr + in_te_attr[gl_InvocationID];\n"
669 			<< "\n"
670 			<< "    barrier();\n"
671 			<< "\n"
672 			<< "    if (gl_InvocationID == " << NUM_VERTICES << "-1)\n"
673 			<< "		in_te_patchAttr = float(gl_InvocationID);\n"
674 			<< "\n"
675 			<< "    barrier();\n"
676 			<< "\n"
677 			<< "    in_te_attr[gl_InvocationID] = temp;\n"
678 			<< "\n"
679 			<< "    barrier();\n"
680 			<< "\n"
681 			<< "    temp = temp + in_te_attr[(gl_InvocationID+1) % " << NUM_VERTICES << "];\n"
682 			<< "\n"
683 			<< "    barrier();\n"
684 			<< "\n"
685 			<< "    in_te_attr[gl_InvocationID] = 0.25*temp;\n"
686 			<< "\n"
687 			<< "    gl_TessLevelInner[0] = 32.0;\n"
688 			<< "    gl_TessLevelInner[1] = 32.0;\n"
689 			<< "\n"
690 			<< "    gl_TessLevelOuter[0] = 32.0;\n"
691 			<< "    gl_TessLevelOuter[1] = 32.0;\n"
692 			<< "    gl_TessLevelOuter[2] = 32.0;\n"
693 			<< "    gl_TessLevelOuter[3] = 32.0;\n"
694 			<< "}\n";
695 
696 		programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
697 	}
698 
699 	// Tessellation evaluation shader
700 	{
701 		std::ostringstream src;
702 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
703 			<< "#extension GL_EXT_tessellation_shader : require\n"
704 			<< "\n"
705 			<< "layout(" << getTessPrimitiveTypeShaderName(TESSPRIMITIVETYPE_QUADS) << ") in;\n"
706 			<< "\n"
707 			<< "layout(location = 0) in       highp float in_te_attr[];\n"
708 			<< "layout(location = 1) patch in highp float in_te_patchAttr;\n"
709 			<< "\n"
710 			<< "layout(location = 0) out highp float in_f_blue;\n"
711 			<< "\n"
712 			<< "void main (void)\n"
713 			<< "{\n"
714 			<< "    highp float x = gl_TessCoord.x*2.0 - 1.0;\n"
715 			<< "    highp float y = gl_TessCoord.y - in_te_attr[int(round(gl_TessCoord.x*float(" << NUM_VERTICES << "-1)))];\n"
716 			<< "    gl_Position = vec4(x, y, 0.0, 1.0);\n"
717 			<< "    in_f_blue = abs(in_te_patchAttr - float(" << NUM_VERTICES << "-1));\n"
718 			<< "}\n";
719 
720 		programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
721 	}
722 
723 	// Fragment shader
724 	{
725 		std::ostringstream src;
726 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
727 			<< "\n"
728 			<< "layout(location = 0) in  highp   float in_f_blue;\n"
729 			<< "layout(location = 0) out mediump vec4  o_color;\n"
730 			<< "\n"
731 			<< "void main (void)\n"
732 			<< "{\n"
733 			<< "    o_color = vec4(1.0, 0.0, in_f_blue, 1.0);\n"
734 			<< "}\n";
735 
736 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
737 	}
738 }
739 
test(Context & context)740 tcu::TestStatus test (Context& context)
741 {
742 	// Input vertex attribute data
743 	std::vector<float> vertexData		(NUM_VERTICES);
744 	const VkDeviceSize vertexBufferSize = sizeof(float) * vertexData.size();
745 
746 	for (int i = 0; i < NUM_VERTICES; ++i)
747 		vertexData[i] = static_cast<float>(i) / (NUM_VERTICES - 1);
748 
749 	tcu::TextureLevel referenceImage;
750 	tcu::ImageIO::loadPNG(referenceImage, context.getTestContext().getArchive(), "vulkan/data/tessellation/barrier_ref.png");
751 
752 	const int numPrimitives = 1;
753 	const int inPatchSize   = NUM_VERTICES;
754 	const int outPatchSize  = NUM_VERTICES;
755 
756 	return runTest(context, numPrimitives, inPatchSize, outPatchSize,
757 				   VK_FORMAT_R32_SFLOAT, &vertexData[0], vertexBufferSize, referenceImage.getAccess());
758 }
759 
760 } // Barrier ns
761 
762 namespace CrossInvocation
763 {
764 
765 enum Constants
766 {
767 	OUTPUT_PATCH_SIZE	= 3,
768 	INPUT_PATCH_SIZE	= 10
769 };
770 
771 enum CaseType
772 {
773 	CASETYPE_PER_VERTEX,
774 	CASETYPE_PER_PATCH
775 };
776 
777 enum DataType
778 {
779 	DATATYPE_INT,
780 	DATATYPE_UINT,
781 	DATATYPE_FLOAT,
782 	DATATYPE_VEC3,
783 	DATATYPE_VEC4,
784 	DATATYPE_MAT4X3
785 };
786 
787 struct CaseDefinition
788 {
789 	CaseType	caseType;
790 	DataType	dataType;
791 };
792 
initPrograms(vk::SourceCollections & programCollection,const CaseDefinition caseDef)793 void initPrograms (vk::SourceCollections& programCollection, const CaseDefinition caseDef)
794 {
795 	static const std::string	typeStr[]		=
796 	{
797 		"int",
798 		"uint",
799 		"float",
800 		"vec3",
801 		"vec4",
802 		"mat4x3"
803 	};
804 	const std::string			dataType		= typeStr[caseDef.dataType];
805 	const int					varyingSize[]	= { 1, 1, 1, 1, 1, 4 };
806 
807 	// Vertex shader
808 	{
809 		std::ostringstream src;
810 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
811 			<< "\n"
812 			<< "layout(location = 0) in  highp float in_v_attr;\n"
813 			<< "layout(location = 0) out highp float in_tc_attr;\n"
814 			<< "\n"
815 			<< "void main (void)\n"
816 			<< "{\n"
817 			<< "    in_tc_attr = in_v_attr;\n"
818 			<< "}\n";
819 
820 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
821 	}
822 
823 	// Tessellation control shader
824 	{
825 		std::ostringstream src;
826 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
827 			<< "#extension GL_EXT_tessellation_shader : require\n"
828 			<< "\n"
829 			<< "layout(vertices = " << OUTPUT_PATCH_SIZE << ") out;\n"
830 			<< "\n"
831 			<< "layout(location = 0) in  highp float in_tc_attr[];\n"
832 			<< "layout(location = 0) out highp float in_te_attr[];\n"
833 			<< "\n";
834 
835 		if (caseDef.caseType == CASETYPE_PER_VERTEX)
836 			src << "layout(location = 1) out mediump " << dataType << " in_te_data0[];\n"
837 				<< "layout(location = " << varyingSize[caseDef.dataType] + 1 << ") out mediump " << dataType << " in_te_data1[];\n";
838 		else
839 			src << "layout(location = 1) patch out mediump " << dataType << " in_te_data0[" << OUTPUT_PATCH_SIZE << "];\n"
840 				<< "layout(location = " << OUTPUT_PATCH_SIZE * varyingSize[caseDef.dataType] + 1 << ") patch out mediump " << dataType << " in_te_data1[" << OUTPUT_PATCH_SIZE << "];\n";
841 
842 		src	<< "\n"
843 			<< "void main (void)\n"
844 			<< "{\n"
845 			<< "    " << dataType << " d = " << dataType << "(gl_InvocationID);\n"
846 			<< "    in_te_data0[gl_InvocationID] = d;\n"
847 			<< "    barrier();\n"
848 			<< "    in_te_data1[gl_InvocationID] = d + in_te_data0[(gl_InvocationID + 1) % " << OUTPUT_PATCH_SIZE << "];\n"
849 			<< "\n"
850 			<< "    in_te_attr[gl_InvocationID] = in_tc_attr[gl_InvocationID];\n"
851 			<< "\n"
852 			<< "    gl_TessLevelInner[0] = 1.0;\n"
853 			<< "    gl_TessLevelInner[1] = 1.0;\n"
854 			<< "\n"
855 			<< "    gl_TessLevelOuter[0] = 1.0;\n"
856 			<< "    gl_TessLevelOuter[1] = 1.0;\n"
857 			<< "    gl_TessLevelOuter[2] = 1.0;\n"
858 			<< "    gl_TessLevelOuter[3] = 1.0;\n"
859 			<< "}\n";
860 
861 		programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
862 	}
863 
864 	// Tessellation evaluation shader
865 	{
866 		const float xScale = 1.0f / 8.0f;
867 
868 		std::ostringstream src;
869 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
870 			<< "#extension GL_EXT_tessellation_shader : require\n"
871 			<< "\n"
872 			<< "layout(" << getTessPrimitiveTypeShaderName(TESSPRIMITIVETYPE_QUADS) << ") in;\n"
873 			<< "\n"
874 			<< "layout(location = 0) in  highp   float in_te_attr[];\n"
875 			<< "layout(location = 0) out mediump vec4  in_f_color;\n"
876 			<< "\n";
877 
878 		if (caseDef.caseType == CASETYPE_PER_VERTEX)
879 			src << "layout(location = 1) in mediump " << dataType << " in_te_data0[];\n"
880 				<< "layout(location = " << varyingSize[caseDef.dataType] + 1 << ") in mediump " << dataType << " in_te_data1[];\n";
881 		else
882 			src << "layout(location = 1) patch in mediump " << dataType << " in_te_data0[" << OUTPUT_PATCH_SIZE << "];\n"
883 				<< "layout(location = " << OUTPUT_PATCH_SIZE * varyingSize[caseDef.dataType] + 1 << ") patch in mediump " << dataType << " in_te_data1[" << OUTPUT_PATCH_SIZE << "];\n";
884 
885 		src << "\n"
886 			<< "void main (void)\n"
887 			<< "{\n"
888 			<< "    highp float x = (gl_TessCoord.x*float(" << xScale << ") + in_te_attr[0]) * 2.0 - 1.0;\n"
889 			<< "    highp float y = gl_TessCoord.y*2.0 - 1.0;\n"
890 			<< "    gl_Position = vec4(x, y, 0.0, 1.0);\n"
891 			<< "    bool ok = true;\n"
892 			<< "    for (int i = 0; i < " << OUTPUT_PATCH_SIZE << "; i++)\n"
893 			<< "    {\n"
894 			<< "         int ref = i + (i + 1) % " << OUTPUT_PATCH_SIZE << ";\n"
895 			<< "         if (in_te_data1[i] != " << dataType << "(ref)) ok = false;\n"
896 			<< "    }\n"
897 			<< "    in_f_color = ok ? vec4(1.0) : vec4(vec3(0.0), 1.0);\n"
898 			<< "}\n";
899 
900 		programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
901 	}
902 
903 	// Fragment shader
904 	{
905 		std::ostringstream src;
906 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
907 			<< "\n"
908 			<< "layout(location = 0) in  mediump vec4 in_f_color;\n"
909 			<< "layout(location = 0) out mediump vec4 o_color;\n"
910 			<< "\n"
911 			<< "void main (void)\n"
912 			<< "{\n"
913 			<< "    o_color = in_f_color;\n"
914 			<< "}\n";
915 
916 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
917 	}
918 }
919 
test(Context & context,const CaseDefinition caseDef)920 tcu::TestStatus test (Context& context, const CaseDefinition caseDef)
921 {
922 	DE_UNREF(caseDef);
923 	// Input vertex attribute data
924 	const int		   numPrimitives	= 8;
925 	std::vector<float> vertexData		(INPUT_PATCH_SIZE * numPrimitives, 0.0f);
926 	const VkDeviceSize vertexBufferSize = sizeof(float) * vertexData.size();
927 
928 	for (int i = 0; i < numPrimitives; ++i)
929 		vertexData[INPUT_PATCH_SIZE * i] = static_cast<float>(i) / static_cast<float>(numPrimitives);
930 
931 	tcu::TextureLevel referenceImage;
932 	initializeWhiteReferenceImage(referenceImage, RENDER_SIZE, RENDER_SIZE);
933 
934 	return runTest(context, numPrimitives, INPUT_PATCH_SIZE, OUTPUT_PATCH_SIZE,
935 				   VK_FORMAT_R32_SFLOAT, &vertexData[0], vertexBufferSize, referenceImage.getAccess());
936 }
937 
938 } // CrossInvocation ns
939 
940 } // anonymous
941 
942 //! These tests correspond to dEQP-GLES31.functional.tessellation.shader_input_output.*
createShaderInputOutputTests(tcu::TestContext & testCtx)943 tcu::TestCaseGroup* createShaderInputOutputTests (tcu::TestContext& testCtx)
944 {
945 	de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "shader_input_output", "Test tessellation control and evaluation shader inputs and outputs"));
946 
947 	// Patch vertex counts
948 	{
949 		static const struct
950 		{
951 			int inPatchSize;
952 			int outPatchSize;
953 		} patchVertexCountCases[] =
954 		{
955 			{  5, 10 },
956 			{ 10,  5 }
957 		};
958 
959 		for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(patchVertexCountCases); caseNdx++)
960 		{
961 			const int inSize	= patchVertexCountCases[caseNdx].inPatchSize;
962 			const int outSize	= patchVertexCountCases[caseNdx].outPatchSize;
963 
964 			const std::string caseName = "patch_vertices_" + de::toString(inSize) + "_in_" + de::toString(outSize) + "_out";
965 			const PatchVertexCount::CaseDefinition caseDef =
966 			{
967 				inSize, outSize, "vulkan/data/tessellation/" + caseName + "_ref.png"
968 			};
969 
970 			addFunctionCaseWithPrograms(group.get(), caseName, "Test input and output patch vertex counts",
971 										PatchVertexCount::initPrograms, PatchVertexCount::test, caseDef);
972 		}
973 	}
974 
975 	// Per patch data
976 	{
977 		static const PerPatchData::CaseDefinition cases[] =
978 		{
979 			{ PerPatchData::CASETYPE_PRIMITIVE_ID_TCS,		"primitive_id_tcs",		  true, "vulkan/data/tessellation/primitive_id_tcs_ref.png", "Read gl_PrimitiveID in TCS and pass it as patch output to TES" },
980 			{ PerPatchData::CASETYPE_PRIMITIVE_ID_TES,		"primitive_id_tes",		  true, "vulkan/data/tessellation/primitive_id_tes_ref.png", "Read gl_PrimitiveID in TES" },
981 			{ PerPatchData::CASETYPE_PATCH_VERTICES_IN_TCS,	"patch_vertices_in_tcs",  false, "", "Read gl_PatchVerticesIn in TCS and pass it as patch output to TES" },
982 			{ PerPatchData::CASETYPE_PATCH_VERTICES_IN_TES,	"patch_vertices_in_tes",  false, "", "Read gl_PatchVerticesIn in TES" },
983 			{ PerPatchData::CASETYPE_TESS_LEVEL_INNER0_TES,	"tess_level_inner_0_tes", false, "", "Read gl_TessLevelInner[0] in TES" },
984 			{ PerPatchData::CASETYPE_TESS_LEVEL_INNER1_TES,	"tess_level_inner_1_tes", false, "", "Read gl_TessLevelInner[1] in TES" },
985 			{ PerPatchData::CASETYPE_TESS_LEVEL_OUTER0_TES,	"tess_level_outer_0_tes", false, "", "Read gl_TessLevelOuter[0] in TES" },
986 			{ PerPatchData::CASETYPE_TESS_LEVEL_OUTER1_TES,	"tess_level_outer_1_tes", false, "", "Read gl_TessLevelOuter[1] in TES" },
987 			{ PerPatchData::CASETYPE_TESS_LEVEL_OUTER2_TES,	"tess_level_outer_2_tes", false, "", "Read gl_TessLevelOuter[2] in TES" },
988 			{ PerPatchData::CASETYPE_TESS_LEVEL_OUTER3_TES,	"tess_level_outer_3_tes", false, "", "Read gl_TessLevelOuter[3] in TES" },
989 		};
990 
991 		for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); ++caseNdx)
992 			addFunctionCaseWithPrograms(group.get(), cases[caseNdx].caseName, cases[caseNdx].caseDescription,
993 										PerPatchData::initPrograms, PerPatchData::test, cases[caseNdx]);
994 	}
995 
996 	// gl_Position
997 	{
998 		static const struct
999 		{
1000 			GLPosition::CaseType	type;
1001 			std::string				caseName;
1002 		} cases[] =
1003 		{
1004 			{ GLPosition::CASETYPE_VS_TO_TCS,		 "gl_position_vs_to_tcs"		},
1005 			{ GLPosition::CASETYPE_TCS_TO_TES,		 "gl_position_tcs_to_tes"		},
1006 			{ GLPosition::CASETYPE_VS_TO_TCS_TO_TES, "gl_position_vs_to_tcs_to_tes" },
1007 		};
1008 
1009 		for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); ++caseNdx)
1010 			addFunctionCaseWithPrograms(group.get(), cases[caseNdx].caseName, "Pass gl_Position between VS and TCS, or between TCS and TES",
1011 										GLPosition::initPrograms, GLPosition::test, cases[caseNdx].type);
1012 	}
1013 
1014 	// Barrier
1015 	addFunctionCaseWithPrograms(group.get(), "barrier", "Basic barrier usage", Barrier::initPrograms, Barrier::test);
1016 
1017 	// Cross invocation communication
1018 	{
1019 		static const struct
1020 		{
1021 			CrossInvocation::CaseType	caseType;
1022 			std::string					name;
1023 		} caseTypes[] =
1024 		{
1025 			{ CrossInvocation::CASETYPE_PER_VERTEX,	 "cross_invocation_per_vertex"	},
1026 			{ CrossInvocation::CASETYPE_PER_PATCH,	 "cross_invocation_per_patch"	}
1027 		};
1028 
1029 		static const struct
1030 		{
1031 			CrossInvocation::DataType	dataType;
1032 			std::string					name;
1033 		} dataTypes[] =
1034 		{
1035 			{ CrossInvocation::DATATYPE_INT,	"int"		},
1036 			{ CrossInvocation::DATATYPE_UINT,	"uint"		},
1037 			{ CrossInvocation::DATATYPE_FLOAT,	"float"		},
1038 			{ CrossInvocation::DATATYPE_VEC3,	"vec3"		},
1039 			{ CrossInvocation::DATATYPE_VEC4,	"vec4"		},
1040 			{ CrossInvocation::DATATYPE_MAT4X3,	"mat4x3"	}
1041 		};
1042 
1043 		for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(caseTypes); ++caseNdx)
1044 			for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(dataTypes); ++dataTypeNdx)
1045 			{
1046 				std::string						testName	= caseTypes[caseNdx].name + "_" + dataTypes[dataTypeNdx].name;
1047 				CrossInvocation::CaseDefinition	caseDef		= { caseTypes[caseNdx].caseType, dataTypes[dataTypeNdx].dataType };
1048 
1049 				addFunctionCaseWithPrograms(group.get(), testName, "Write output varyings from multiple invocations.",
1050 						CrossInvocation::initPrograms, CrossInvocation::test, caseDef);
1051 			}
1052 	}
1053 
1054 	return group.release();
1055 }
1056 
1057 } // tessellation
1058 } // vkt
1059