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