• 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 	std::string		caseDescription;
355 };
356 
getNumPrimitives(const CaseType type)357 int getNumPrimitives (const CaseType type)
358 {
359 	return (type == CASETYPE_PRIMITIVE_ID_TCS || type == CASETYPE_PRIMITIVE_ID_TES ? 8 : 1);
360 }
361 
initPrograms(vk::SourceCollections & programCollection,const CaseDefinition caseDef)362 void initPrograms (vk::SourceCollections& programCollection, const CaseDefinition caseDef)
363 {
364 	// Vertex shader
365 	{
366 		std::ostringstream src;
367 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
368 			<< "\n"
369 			<< "layout(location = 0) in  highp float in_v_attr;\n"
370 			<< "layout(location = 0) out highp float in_tc_attr;\n"
371 			<< "\n"
372 			<< "void main (void)\n"
373 			<< "{\n"
374 			<< "    in_tc_attr = in_v_attr;\n"
375 			<< "}\n";
376 
377 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
378 	}
379 
380 	// Tessellation control shader
381 	{
382 		std::ostringstream src;
383 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
384 			<< "#extension GL_EXT_tessellation_shader : require\n"
385 			<< "\n"
386 			<< "layout(vertices = " << OUTPUT_PATCH_SIZE << ") out;\n"
387 			<< "\n"
388 			<< "layout(location = 0) in  highp float in_tc_attr[];\n"
389 			<< "layout(location = 0) out highp float in_te_attr[];\n"
390 			<< "\n"
391 			<< (caseDef.caseType == CASETYPE_PRIMITIVE_ID_TCS	   ? "layout(location = 1) patch out mediump int in_te_primitiveIDFromTCS;\n" :
392 				caseDef.caseType == CASETYPE_PATCH_VERTICES_IN_TCS ? "layout(location = 1) patch out mediump int in_te_patchVerticesInFromTCS;\n" : "")
393 			<< "\n"
394 			<< "void main (void)\n"
395 			<< "{\n"
396 			<< "    in_te_attr[gl_InvocationID] = in_tc_attr[gl_InvocationID];\n"
397 			<< (caseDef.caseType == CASETYPE_PRIMITIVE_ID_TCS	   ? "    in_te_primitiveIDFromTCS = gl_PrimitiveID;\n" :
398 				caseDef.caseType == CASETYPE_PATCH_VERTICES_IN_TCS ? "    in_te_patchVerticesInFromTCS = gl_PatchVerticesIn;\n" : "")
399 			<< "\n"
400 			<< "    gl_TessLevelInner[0] = 9.0;\n"
401 			<< "    gl_TessLevelInner[1] = 8.0;\n"
402 			<< "\n"
403 			<< "    gl_TessLevelOuter[0] = 7.0;\n"
404 			<< "    gl_TessLevelOuter[1] = 6.0;\n"
405 			<< "    gl_TessLevelOuter[2] = 5.0;\n"
406 			<< "    gl_TessLevelOuter[3] = 4.0;\n"
407 			<< "}\n";
408 
409 		programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
410 	}
411 
412 	// Tessellation evaluation shader
413 	{
414 		const float xScale = 1.0f / static_cast<float>(getNumPrimitives(caseDef.caseType));
415 
416 		std::ostringstream src;
417 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
418 			<< "#extension GL_EXT_tessellation_shader : require\n"
419 			<< "\n"
420 			<< "layout(" << getTessPrimitiveTypeShaderName(TESSPRIMITIVETYPE_QUADS) << ") in;\n"
421 			<< "\n"
422 			<< "layout(location = 0) in  highp   float in_te_attr[];\n"
423 			<< "layout(location = 0) out mediump vec4  in_f_color;\n"
424 			<< "\n"
425 			<< (caseDef.caseType == CASETYPE_PRIMITIVE_ID_TCS	   ? "layout(location = 1) patch in mediump int in_te_primitiveIDFromTCS;\n" :
426 				caseDef.caseType == CASETYPE_PATCH_VERTICES_IN_TCS ? "layout(location = 1) patch in mediump int in_te_patchVerticesInFromTCS;\n" : "")
427 			<< "\n"
428 			<< "void main (void)\n"
429 			<< "{\n"
430 			<< "    highp float x = (gl_TessCoord.x*float(" << xScale << ") + in_te_attr[0]) * 2.0 - 1.0;\n"
431 			<< "    highp float y = gl_TessCoord.y*2.0 - 1.0;\n"
432 			<< "    gl_Position = vec4(x, y, 0.0, 1.0);\n"
433 			<< (caseDef.caseType == CASETYPE_PRIMITIVE_ID_TCS		? "    bool ok = in_te_primitiveIDFromTCS == 3;\n" :
434 				caseDef.caseType == CASETYPE_PRIMITIVE_ID_TES		? "    bool ok = gl_PrimitiveID == 3;\n" :
435 				caseDef.caseType == CASETYPE_PATCH_VERTICES_IN_TCS	? "    bool ok = in_te_patchVerticesInFromTCS == " + de::toString(INPUT_PATCH_SIZE) + ";\n" :
436 				caseDef.caseType == CASETYPE_PATCH_VERTICES_IN_TES	? "    bool ok = gl_PatchVerticesIn == " + de::toString(OUTPUT_PATCH_SIZE) + ";\n" :
437 				caseDef.caseType == CASETYPE_TESS_LEVEL_INNER0_TES	? "    bool ok = abs(gl_TessLevelInner[0] - 9.0) < 0.1f;\n" :
438 				caseDef.caseType == CASETYPE_TESS_LEVEL_INNER1_TES	? "    bool ok = abs(gl_TessLevelInner[1] - 8.0) < 0.1f;\n" :
439 				caseDef.caseType == CASETYPE_TESS_LEVEL_OUTER0_TES	? "    bool ok = abs(gl_TessLevelOuter[0] - 7.0) < 0.1f;\n" :
440 				caseDef.caseType == CASETYPE_TESS_LEVEL_OUTER1_TES	? "    bool ok = abs(gl_TessLevelOuter[1] - 6.0) < 0.1f;\n" :
441 				caseDef.caseType == CASETYPE_TESS_LEVEL_OUTER2_TES	? "    bool ok = abs(gl_TessLevelOuter[2] - 5.0) < 0.1f;\n" :
442 				caseDef.caseType == CASETYPE_TESS_LEVEL_OUTER3_TES	? "    bool ok = abs(gl_TessLevelOuter[3] - 4.0) < 0.1f;\n" : "")
443 			<< "    in_f_color = ok ? vec4(1.0) : vec4(vec3(0.0), 1.0);\n"
444 			<< "}\n";
445 
446 		programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
447 	}
448 
449 	// Fragment shader
450 	{
451 		std::ostringstream src;
452 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
453 			<< "\n"
454 			<< "layout(location = 0) in  mediump vec4 in_f_color;\n"
455 			<< "layout(location = 0) out mediump vec4 o_color;\n"
456 			<< "\n"
457 			<< "void main (void)\n"
458 			<< "{\n"
459 			<< "    o_color = in_f_color;\n"
460 			<< "}\n";
461 
462 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
463 	}
464 }
465 
test(Context & context,const CaseDefinition caseDef)466 tcu::TestStatus test (Context& context, const CaseDefinition caseDef)
467 {
468 	DE_ASSERT(!caseDef.usesReferenceImageFromFile || !caseDef.referenceImagePath.empty());
469 
470 	// Input vertex attribute data
471 	const int		   numPrimitives	= getNumPrimitives(caseDef.caseType);
472 	std::vector<float> vertexData		(INPUT_PATCH_SIZE * numPrimitives, 0.0f);
473 	const VkDeviceSize vertexBufferSize = sizeof(float) * vertexData.size();
474 
475 	for (int i = 0; i < numPrimitives; ++i)
476 		vertexData[INPUT_PATCH_SIZE * i] = static_cast<float>(i) / static_cast<float>(numPrimitives);
477 
478 	tcu::TextureLevel referenceImage;
479 	if (caseDef.usesReferenceImageFromFile)
480 		tcu::ImageIO::loadPNG(referenceImage, context.getTestContext().getArchive(), caseDef.referenceImagePath.c_str());
481 	else
482 		initializeWhiteReferenceImage(referenceImage, RENDER_SIZE, RENDER_SIZE);
483 
484 	return runTest(context, numPrimitives, INPUT_PATCH_SIZE, OUTPUT_PATCH_SIZE,
485 				   VK_FORMAT_R32_SFLOAT, &vertexData[0], vertexBufferSize, referenceImage.getAccess());
486 }
487 
488 } // PerPatchData ns
489 
490 namespace GLPosition
491 {
492 
493 enum CaseType
494 {
495 	CASETYPE_VS_TO_TCS = 0,
496 	CASETYPE_TCS_TO_TES,
497 	CASETYPE_VS_TO_TCS_TO_TES,
498 };
499 
initPrograms(vk::SourceCollections & programCollection,const CaseType caseType)500 void initPrograms (vk::SourceCollections& programCollection, const CaseType caseType)
501 {
502 	const bool vsToTCS  = caseType == CASETYPE_VS_TO_TCS  || caseType == CASETYPE_VS_TO_TCS_TO_TES;
503 	const bool tcsToTES = caseType == CASETYPE_TCS_TO_TES || caseType == CASETYPE_VS_TO_TCS_TO_TES;
504 
505 	// Vertex shader
506 	{
507 		std::ostringstream src;
508 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
509 			<< "\n"
510 			<< "layout(location = 0) in  highp vec4 in_v_attr;\n"
511 			<< (!vsToTCS ? "layout(location = 0) out highp vec4 in_tc_attr;\n" : "")
512 			<< "\n"
513 			<< "void main (void)\n"
514 			<< "{\n"
515 			<< "    " << (vsToTCS ? "gl_Position" : "in_tc_attr") << " = in_v_attr;\n"
516 			<< "}\n";
517 
518 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
519 	}
520 
521 	// Tessellation control shader
522 	{
523 		std::ostringstream src;
524 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
525 			<< "#extension GL_EXT_tessellation_shader : require\n"
526 			<< "\n"
527 			<< "layout(vertices = 3) out;\n"
528 			<< "\n"
529 			<< (!vsToTCS  ? "layout(location = 0) in  highp vec4 in_tc_attr[];\n" : "")
530 			<< (!tcsToTES ? "layout(location = 0) out highp vec4 in_te_attr[];\n" : "")
531 			<< "\n"
532 			<< "void main (void)\n"
533 			<< "{\n"
534 			<< "    " << (tcsToTES ? "gl_out[gl_InvocationID].gl_Position" : "in_te_attr[gl_InvocationID]") << " = "
535 					  << (vsToTCS  ? "gl_in[gl_InvocationID].gl_Position" : "in_tc_attr[gl_InvocationID]") << ";\n"
536 			<< "\n"
537 			<< "    gl_TessLevelInner[0] = 2.0;\n"
538 			<< "    gl_TessLevelInner[1] = 3.0;\n"
539 			<< "\n"
540 			<< "    gl_TessLevelOuter[0] = 4.0;\n"
541 			<< "    gl_TessLevelOuter[1] = 5.0;\n"
542 			<< "    gl_TessLevelOuter[2] = 6.0;\n"
543 			<< "    gl_TessLevelOuter[3] = 7.0;\n"
544 			<< "}\n";
545 
546 		programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
547 	}
548 
549 	// Tessellation evaluation shader
550 	{
551 		const std::string tesIn0 = tcsToTES ? "gl_in[0].gl_Position" : "in_te_attr[0]";
552 		const std::string tesIn1 = tcsToTES ? "gl_in[1].gl_Position" : "in_te_attr[1]";
553 		const std::string tesIn2 = tcsToTES ? "gl_in[2].gl_Position" : "in_te_attr[2]";
554 
555 		std::ostringstream src;
556 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
557 			<< "#extension GL_EXT_tessellation_shader : require\n"
558 			<< "\n"
559 			<< "layout(" << getTessPrimitiveTypeShaderName(TESSPRIMITIVETYPE_TRIANGLES) << ") in;\n"
560 			<< "\n"
561 			<< (!tcsToTES ? "layout(location = 0) in  highp vec4 in_te_attr[];\n" : "")
562 			<< "layout(location = 0) out highp vec4 in_f_color;\n"
563 			<< "\n"
564 			<< "void main (void)\n"
565 			<< "{\n"
566 			<< "    highp vec2 xy = gl_TessCoord.x * " << tesIn0 << ".xy\n"
567 			<< "                  + gl_TessCoord.y * " << tesIn1 << ".xy\n"
568 			<< "                  + gl_TessCoord.z * " << tesIn2 << ".xy;\n"
569 			<< "    gl_Position = vec4(xy, 0.0, 1.0);\n"
570 			<< "    in_f_color = vec4(" << tesIn0 << ".z + " << tesIn1 << ".w,\n"
571 			<< "                      " << tesIn2 << ".z + " << tesIn0 << ".w,\n"
572 			<< "                      " << tesIn1 << ".z + " << tesIn2 << ".w,\n"
573 			<< "                      1.0);\n"
574 			<< "}\n";
575 
576 		programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
577 	}
578 
579 	// Fragment shader
580 	{
581 		std::ostringstream src;
582 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
583 			<< "\n"
584 			<< "layout(location = 0) in  highp   vec4 in_f_color;\n"
585 			<< "layout(location = 0) out mediump vec4 o_color;\n"
586 			<< "\n"
587 			<< "void main (void)\n"
588 			<< "{\n"
589 			<< "    o_color = in_f_color;\n"
590 			<< "}\n";
591 
592 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
593 	}
594 }
595 
test(Context & context,const CaseType caseType)596 tcu::TestStatus test (Context& context, const CaseType caseType)
597 {
598 	DE_UNREF(caseType);
599 
600 	// Input vertex attribute data
601 	static const float vertexData[3*4] =
602 	{
603 		-0.8f, -0.7f, 0.1f, 0.7f,
604 		-0.5f,  0.4f, 0.2f, 0.5f,
605 		 0.3f,  0.2f, 0.3f, 0.45f
606 	};
607 
608 	tcu::TextureLevel referenceImage;
609 	tcu::ImageIO::loadPNG(referenceImage, context.getTestContext().getArchive(), "vulkan/data/tessellation/gl_position_ref.png");
610 
611 	const int numPrimitives = 1;
612 	const int inPatchSize   = 3;
613 	const int outPatchSize  = 3;
614 
615 	return runTest(context, numPrimitives, inPatchSize, outPatchSize,
616 				   VK_FORMAT_R32G32B32A32_SFLOAT, vertexData, sizeof(vertexData), referenceImage.getAccess());
617 }
618 
619 } // GLPosition ns
620 
621 namespace Barrier
622 {
623 
624 enum Constants
625 {
626 	NUM_VERTICES = 32,
627 };
628 
initPrograms(vk::SourceCollections & programCollection)629 void initPrograms (vk::SourceCollections& programCollection)
630 {
631 	// Vertex shader
632 	{
633 		std::ostringstream src;
634 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
635 			<< "\n"
636 			<< "layout(location = 0) in  highp float in_v_attr;\n"
637 			<< "layout(location = 0) out highp float in_tc_attr;\n"
638 			<< "\n"
639 			<< "void main (void)\n"
640 			<< "{\n"
641 			<< "    in_tc_attr = in_v_attr;\n"
642 			<< "}\n";
643 
644 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
645 	}
646 
647 	// Tessellation control shader
648 	{
649 		std::ostringstream src;
650 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
651 			<< "#extension GL_EXT_tessellation_shader : require\n"
652 			<< "\n"
653 			<< "layout(vertices = " << NUM_VERTICES << ") out;\n"
654 			<< "\n"
655 			<< "layout(location = 0) in  highp float in_tc_attr[];\n"
656 			<< "layout(location = 0) out highp float in_te_attr[];\n"
657 			<< "\n"
658 			<< "layout(location = 1) patch out highp float in_te_patchAttr;\n"
659 			<< "\n"
660 			<< "void main (void)\n"
661 			<< "{\n"
662 			<< "    in_te_attr[gl_InvocationID] = in_tc_attr[gl_InvocationID];\n"
663 			<< "    in_te_patchAttr = 0.0f;\n"
664 			<< "\n"
665 			<< "    barrier();\n"
666 			<< "\n"
667 			<< "    if (gl_InvocationID == 5)\n"
668 			<< "		in_te_patchAttr = float(gl_InvocationID)*0.1;\n"
669 			<< "\n"
670 			<< "    barrier();\n"
671 			<< "\n"
672 			<< "    highp float temp = in_te_patchAttr + in_te_attr[gl_InvocationID];\n"
673 			<< "\n"
674 			<< "    barrier();\n"
675 			<< "\n"
676 			<< "    if (gl_InvocationID == " << NUM_VERTICES << "-1)\n"
677 			<< "		in_te_patchAttr = float(gl_InvocationID);\n"
678 			<< "\n"
679 			<< "    barrier();\n"
680 			<< "\n"
681 			<< "    in_te_attr[gl_InvocationID] = temp;\n"
682 			<< "\n"
683 			<< "    barrier();\n"
684 			<< "\n"
685 			<< "    temp = temp + in_te_attr[(gl_InvocationID+1) % " << NUM_VERTICES << "];\n"
686 			<< "\n"
687 			<< "    barrier();\n"
688 			<< "\n"
689 			<< "    in_te_attr[gl_InvocationID] = 0.25*temp;\n"
690 			<< "\n"
691 			<< "    gl_TessLevelInner[0] = 32.0;\n"
692 			<< "    gl_TessLevelInner[1] = 32.0;\n"
693 			<< "\n"
694 			<< "    gl_TessLevelOuter[0] = 32.0;\n"
695 			<< "    gl_TessLevelOuter[1] = 32.0;\n"
696 			<< "    gl_TessLevelOuter[2] = 32.0;\n"
697 			<< "    gl_TessLevelOuter[3] = 32.0;\n"
698 			<< "}\n";
699 
700 		programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
701 	}
702 
703 	// Tessellation evaluation shader
704 	{
705 		std::ostringstream src;
706 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
707 			<< "#extension GL_EXT_tessellation_shader : require\n"
708 			<< "\n"
709 			<< "layout(" << getTessPrimitiveTypeShaderName(TESSPRIMITIVETYPE_QUADS) << ") in;\n"
710 			<< "\n"
711 			<< "layout(location = 0) in       highp float in_te_attr[];\n"
712 			<< "layout(location = 1) patch in highp float in_te_patchAttr;\n"
713 			<< "\n"
714 			<< "layout(location = 0) out highp float in_f_blue;\n"
715 			<< "\n"
716 			<< "void main (void)\n"
717 			<< "{\n"
718 			<< "    highp float x = gl_TessCoord.x*2.0 - 1.0;\n"
719 			<< "    highp float y = gl_TessCoord.y - in_te_attr[int(round(gl_TessCoord.x*float(" << NUM_VERTICES << "-1)))];\n"
720 			<< "    gl_Position = vec4(x, y, 0.0, 1.0);\n"
721 			<< "    in_f_blue = abs(in_te_patchAttr - float(" << NUM_VERTICES << "-1));\n"
722 			<< "}\n";
723 
724 		programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
725 	}
726 
727 	// Fragment shader
728 	{
729 		std::ostringstream src;
730 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
731 			<< "\n"
732 			<< "layout(location = 0) in  highp   float in_f_blue;\n"
733 			<< "layout(location = 0) out mediump vec4  o_color;\n"
734 			<< "\n"
735 			<< "void main (void)\n"
736 			<< "{\n"
737 			<< "    o_color = vec4(1.0, 0.0, in_f_blue, 1.0);\n"
738 			<< "}\n";
739 
740 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
741 	}
742 }
743 
test(Context & context)744 tcu::TestStatus test (Context& context)
745 {
746 	// Input vertex attribute data
747 	std::vector<float> vertexData		(NUM_VERTICES);
748 	const VkDeviceSize vertexBufferSize = sizeof(float) * vertexData.size();
749 
750 	for (int i = 0; i < NUM_VERTICES; ++i)
751 		vertexData[i] = static_cast<float>(i) / (NUM_VERTICES - 1);
752 
753 	tcu::TextureLevel referenceImage;
754 	tcu::ImageIO::loadPNG(referenceImage, context.getTestContext().getArchive(), "vulkan/data/tessellation/barrier_ref.png");
755 
756 	const int numPrimitives = 1;
757 	const int inPatchSize   = NUM_VERTICES;
758 	const int outPatchSize  = NUM_VERTICES;
759 
760 	return runTest(context, numPrimitives, inPatchSize, outPatchSize,
761 				   VK_FORMAT_R32_SFLOAT, &vertexData[0], vertexBufferSize, referenceImage.getAccess());
762 }
763 
764 } // Barrier ns
765 
766 namespace CrossInvocation
767 {
768 
769 enum Constants
770 {
771 	OUTPUT_PATCH_SIZE	= 3,
772 	INPUT_PATCH_SIZE	= 10
773 };
774 
775 enum CaseType
776 {
777 	CASETYPE_PER_VERTEX,
778 	CASETYPE_PER_PATCH
779 };
780 
781 enum DataType
782 {
783 	DATATYPE_INT,
784 	DATATYPE_UINT,
785 	DATATYPE_FLOAT,
786 	DATATYPE_VEC3,
787 	DATATYPE_VEC4,
788 	DATATYPE_MAT4X3
789 };
790 
791 struct CaseDefinition
792 {
793 	CaseType	caseType;
794 	DataType	dataType;
795 };
796 
initPrograms(vk::SourceCollections & programCollection,const CaseDefinition caseDef)797 void initPrograms (vk::SourceCollections& programCollection, const CaseDefinition caseDef)
798 {
799 	static const std::string	typeStr[]		=
800 	{
801 		"int",
802 		"uint",
803 		"float",
804 		"vec3",
805 		"vec4",
806 		"mat4x3"
807 	};
808 	const std::string			dataType		= typeStr[caseDef.dataType];
809 	const int					varyingSize[]	= { 1, 1, 1, 1, 1, 4 };
810 
811 	// Vertex shader
812 	{
813 		std::ostringstream src;
814 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
815 			<< "\n"
816 			<< "layout(location = 0) in  highp float in_v_attr;\n"
817 			<< "layout(location = 0) out highp float in_tc_attr;\n"
818 			<< "\n"
819 			<< "void main (void)\n"
820 			<< "{\n"
821 			<< "    in_tc_attr = in_v_attr;\n"
822 			<< "}\n";
823 
824 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
825 	}
826 
827 	// Tessellation control shader
828 	{
829 		std::ostringstream src;
830 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
831 			<< "#extension GL_EXT_tessellation_shader : require\n"
832 			<< "\n"
833 			<< "layout(vertices = " << OUTPUT_PATCH_SIZE << ") out;\n"
834 			<< "\n"
835 			<< "layout(location = 0) in  highp float in_tc_attr[];\n"
836 			<< "layout(location = 0) out highp float in_te_attr[];\n"
837 			<< "\n";
838 
839 		if (caseDef.caseType == CASETYPE_PER_VERTEX)
840 			src << "layout(location = 1) out mediump " << dataType << " in_te_data0[];\n"
841 				<< "layout(location = " << varyingSize[caseDef.dataType] + 1 << ") out mediump " << dataType << " in_te_data1[];\n";
842 		else
843 			src << "layout(location = 1) patch out mediump " << dataType << " in_te_data0[" << OUTPUT_PATCH_SIZE << "];\n"
844 				<< "layout(location = " << OUTPUT_PATCH_SIZE * varyingSize[caseDef.dataType] + 1 << ") patch out mediump " << dataType << " in_te_data1[" << OUTPUT_PATCH_SIZE << "];\n";
845 
846 		src	<< "\n"
847 			<< "void main (void)\n"
848 			<< "{\n"
849 			<< "    " << dataType << " d = " << dataType << "(gl_InvocationID);\n"
850 			<< "    in_te_data0[gl_InvocationID] = d;\n"
851 			<< "    barrier();\n"
852 			<< "    in_te_data1[gl_InvocationID] = d + in_te_data0[(gl_InvocationID + 1) % " << OUTPUT_PATCH_SIZE << "];\n"
853 			<< "\n"
854 			<< "    in_te_attr[gl_InvocationID] = in_tc_attr[gl_InvocationID];\n"
855 			<< "\n"
856 			<< "    gl_TessLevelInner[0] = 1.0;\n"
857 			<< "    gl_TessLevelInner[1] = 1.0;\n"
858 			<< "\n"
859 			<< "    gl_TessLevelOuter[0] = 1.0;\n"
860 			<< "    gl_TessLevelOuter[1] = 1.0;\n"
861 			<< "    gl_TessLevelOuter[2] = 1.0;\n"
862 			<< "    gl_TessLevelOuter[3] = 1.0;\n"
863 			<< "}\n";
864 
865 		programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
866 	}
867 
868 	// Tessellation evaluation shader
869 	{
870 		const float xScale = 1.0f / 8.0f;
871 
872 		std::ostringstream src;
873 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
874 			<< "#extension GL_EXT_tessellation_shader : require\n"
875 			<< "\n"
876 			<< "layout(" << getTessPrimitiveTypeShaderName(TESSPRIMITIVETYPE_QUADS) << ") in;\n"
877 			<< "\n"
878 			<< "layout(location = 0) in  highp   float in_te_attr[];\n"
879 			<< "layout(location = 0) out mediump vec4  in_f_color;\n"
880 			<< "\n";
881 
882 		if (caseDef.caseType == CASETYPE_PER_VERTEX)
883 			src << "layout(location = 1) in mediump " << dataType << " in_te_data0[];\n"
884 				<< "layout(location = " << varyingSize[caseDef.dataType] + 1 << ") in mediump " << dataType << " in_te_data1[];\n";
885 		else
886 			src << "layout(location = 1) patch in mediump " << dataType << " in_te_data0[" << OUTPUT_PATCH_SIZE << "];\n"
887 				<< "layout(location = " << OUTPUT_PATCH_SIZE * varyingSize[caseDef.dataType] + 1 << ") patch in mediump " << dataType << " in_te_data1[" << OUTPUT_PATCH_SIZE << "];\n";
888 
889 		src << "\n"
890 			<< "void main (void)\n"
891 			<< "{\n"
892 			<< "    highp float x = (gl_TessCoord.x*float(" << xScale << ") + in_te_attr[0]) * 2.0 - 1.0;\n"
893 			<< "    highp float y = gl_TessCoord.y*2.0 - 1.0;\n"
894 			<< "    gl_Position = vec4(x, y, 0.0, 1.0);\n"
895 			<< "    bool ok = true;\n"
896 			<< "    for (int i = 0; i < " << OUTPUT_PATCH_SIZE << "; i++)\n"
897 			<< "    {\n"
898 			<< "         int ref = i + (i + 1) % " << OUTPUT_PATCH_SIZE << ";\n"
899 			<< "         if (in_te_data1[i] != " << dataType << "(ref)) ok = false;\n"
900 			<< "    }\n"
901 			<< "    in_f_color = ok ? vec4(1.0) : vec4(vec3(0.0), 1.0);\n"
902 			<< "}\n";
903 
904 		programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
905 	}
906 
907 	// Fragment shader
908 	{
909 		std::ostringstream src;
910 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
911 			<< "\n"
912 			<< "layout(location = 0) in  mediump vec4 in_f_color;\n"
913 			<< "layout(location = 0) out mediump vec4 o_color;\n"
914 			<< "\n"
915 			<< "void main (void)\n"
916 			<< "{\n"
917 			<< "    o_color = in_f_color;\n"
918 			<< "}\n";
919 
920 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
921 	}
922 }
923 
test(Context & context,const CaseDefinition caseDef)924 tcu::TestStatus test (Context& context, const CaseDefinition caseDef)
925 {
926 	DE_UNREF(caseDef);
927 	// Input vertex attribute data
928 	const int		   numPrimitives	= 8;
929 	std::vector<float> vertexData		(INPUT_PATCH_SIZE * numPrimitives, 0.0f);
930 	const VkDeviceSize vertexBufferSize = sizeof(float) * vertexData.size();
931 
932 	for (int i = 0; i < numPrimitives; ++i)
933 		vertexData[INPUT_PATCH_SIZE * i] = static_cast<float>(i) / static_cast<float>(numPrimitives);
934 
935 	tcu::TextureLevel referenceImage;
936 	initializeWhiteReferenceImage(referenceImage, RENDER_SIZE, RENDER_SIZE);
937 
938 	return runTest(context, numPrimitives, INPUT_PATCH_SIZE, OUTPUT_PATCH_SIZE,
939 				   VK_FORMAT_R32_SFLOAT, &vertexData[0], vertexBufferSize, referenceImage.getAccess());
940 }
941 
942 } // CrossInvocation ns
943 
944 } // anonymous
945 
946 //! These tests correspond to dEQP-GLES31.functional.tessellation.shader_input_output.*
createShaderInputOutputTests(tcu::TestContext & testCtx)947 tcu::TestCaseGroup* createShaderInputOutputTests (tcu::TestContext& testCtx)
948 {
949 	de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "shader_input_output", "Test tessellation control and evaluation shader inputs and outputs"));
950 
951 	// Patch vertex counts
952 	{
953 		static const struct
954 		{
955 			int inPatchSize;
956 			int outPatchSize;
957 		} patchVertexCountCases[] =
958 		{
959 			{  5, 10 },
960 			{ 10,  5 }
961 		};
962 
963 		for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(patchVertexCountCases); caseNdx++)
964 		{
965 			const int inSize	= patchVertexCountCases[caseNdx].inPatchSize;
966 			const int outSize	= patchVertexCountCases[caseNdx].outPatchSize;
967 
968 			const std::string caseName = "patch_vertices_" + de::toString(inSize) + "_in_" + de::toString(outSize) + "_out";
969 			const PatchVertexCount::CaseDefinition caseDef =
970 			{
971 				inSize, outSize, "vulkan/data/tessellation/" + caseName + "_ref.png"
972 			};
973 
974 			addFunctionCaseWithPrograms(group.get(), caseName, "Test input and output patch vertex counts",
975 										PatchVertexCount::initPrograms, PatchVertexCount::test, caseDef);
976 		}
977 	}
978 
979 	// Per patch data
980 	{
981 		static const PerPatchData::CaseDefinition cases[] =
982 		{
983 			{ 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" },
984 			{ PerPatchData::CASETYPE_PRIMITIVE_ID_TES,		"primitive_id_tes",		  true, "vulkan/data/tessellation/primitive_id_tes_ref.png", "Read gl_PrimitiveID in TES" },
985 			{ PerPatchData::CASETYPE_PATCH_VERTICES_IN_TCS,	"patch_vertices_in_tcs",  false, "", "Read gl_PatchVerticesIn in TCS and pass it as patch output to TES" },
986 			{ PerPatchData::CASETYPE_PATCH_VERTICES_IN_TES,	"patch_vertices_in_tes",  false, "", "Read gl_PatchVerticesIn in TES" },
987 			{ PerPatchData::CASETYPE_TESS_LEVEL_INNER0_TES,	"tess_level_inner_0_tes", false, "", "Read gl_TessLevelInner[0] in TES" },
988 			{ PerPatchData::CASETYPE_TESS_LEVEL_INNER1_TES,	"tess_level_inner_1_tes", false, "", "Read gl_TessLevelInner[1] in TES" },
989 			{ PerPatchData::CASETYPE_TESS_LEVEL_OUTER0_TES,	"tess_level_outer_0_tes", false, "", "Read gl_TessLevelOuter[0] in TES" },
990 			{ PerPatchData::CASETYPE_TESS_LEVEL_OUTER1_TES,	"tess_level_outer_1_tes", false, "", "Read gl_TessLevelOuter[1] in TES" },
991 			{ PerPatchData::CASETYPE_TESS_LEVEL_OUTER2_TES,	"tess_level_outer_2_tes", false, "", "Read gl_TessLevelOuter[2] in TES" },
992 			{ PerPatchData::CASETYPE_TESS_LEVEL_OUTER3_TES,	"tess_level_outer_3_tes", false, "", "Read gl_TessLevelOuter[3] in TES" },
993 		};
994 
995 		for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); ++caseNdx)
996 			addFunctionCaseWithPrograms(group.get(), cases[caseNdx].caseName, cases[caseNdx].caseDescription,
997 										PerPatchData::initPrograms, PerPatchData::test, cases[caseNdx]);
998 	}
999 
1000 	// gl_Position
1001 	{
1002 		static const struct
1003 		{
1004 			GLPosition::CaseType	type;
1005 			std::string				caseName;
1006 		} cases[] =
1007 		{
1008 			{ GLPosition::CASETYPE_VS_TO_TCS,		 "gl_position_vs_to_tcs"		},
1009 			{ GLPosition::CASETYPE_TCS_TO_TES,		 "gl_position_tcs_to_tes"		},
1010 			{ GLPosition::CASETYPE_VS_TO_TCS_TO_TES, "gl_position_vs_to_tcs_to_tes" },
1011 		};
1012 
1013 		for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); ++caseNdx)
1014 			addFunctionCaseWithPrograms(group.get(), cases[caseNdx].caseName, "Pass gl_Position between VS and TCS, or between TCS and TES",
1015 										GLPosition::initPrograms, GLPosition::test, cases[caseNdx].type);
1016 	}
1017 
1018 	// Barrier
1019 	addFunctionCaseWithPrograms(group.get(), "barrier", "Basic barrier usage", Barrier::initPrograms, Barrier::test);
1020 
1021 	// Cross invocation communication
1022 	{
1023 		static const struct
1024 		{
1025 			CrossInvocation::CaseType	caseType;
1026 			std::string					name;
1027 		} caseTypes[] =
1028 		{
1029 			{ CrossInvocation::CASETYPE_PER_VERTEX,	 "cross_invocation_per_vertex"	},
1030 			{ CrossInvocation::CASETYPE_PER_PATCH,	 "cross_invocation_per_patch"	}
1031 		};
1032 
1033 		static const struct
1034 		{
1035 			CrossInvocation::DataType	dataType;
1036 			std::string					name;
1037 		} dataTypes[] =
1038 		{
1039 			{ CrossInvocation::DATATYPE_INT,	"int"		},
1040 			{ CrossInvocation::DATATYPE_UINT,	"uint"		},
1041 			{ CrossInvocation::DATATYPE_FLOAT,	"float"		},
1042 			{ CrossInvocation::DATATYPE_VEC3,	"vec3"		},
1043 			{ CrossInvocation::DATATYPE_VEC4,	"vec4"		},
1044 			{ CrossInvocation::DATATYPE_MAT4X3,	"mat4x3"	}
1045 		};
1046 
1047 		for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(caseTypes); ++caseNdx)
1048 			for (int dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(dataTypes); ++dataTypeNdx)
1049 			{
1050 				std::string						testName	= caseTypes[caseNdx].name + "_" + dataTypes[dataTypeNdx].name;
1051 				CrossInvocation::CaseDefinition	caseDef		= { caseTypes[caseNdx].caseType, dataTypes[dataTypeNdx].dataType };
1052 
1053 				addFunctionCaseWithPrograms(group.get(), testName, "Write output varyings from multiple invocations.",
1054 						CrossInvocation::initPrograms, CrossInvocation::test, caseDef);
1055 			}
1056 	}
1057 
1058 	return group.release();
1059 }
1060 
1061 } // tessellation
1062 } // vkt
1063