• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2017 Google Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Shader cross-stage interface tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktSpvAsmCrossStageInterfaceTests.hpp"
25 
26 #include "tcuTestLog.hpp"
27 #include "tcuTextureUtil.hpp"
28 #include "tcuImageCompare.hpp"
29 
30 #include "vkDefs.hpp"
31 #include "vkMemUtil.hpp"
32 #include "deSharedPtr.hpp"
33 #include "vkQueryUtil.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkStrUtil.hpp"
36 #include "vkTypeUtil.hpp"
37 #include "vkImageUtil.hpp"
38 #include "vkCmdUtil.hpp"
39 #include "vkObjUtil.hpp"
40 
41 #include "deUniquePtr.hpp"
42 
43 #include "vktSpvAsmGraphicsShaderTestUtil.hpp"
44 #include "vktTestCaseUtil.hpp"
45 #include "vktTestGroupUtil.hpp"
46 
47 #include <map>
48 #include <vector>
49 
50 namespace vkt
51 {
52 namespace SpirVAssembly
53 {
54 using namespace vk;
55 
56 namespace
57 {
58 using std::string;
59 using std::map;
60 using std::vector;
61 
62 typedef de::SharedPtr<Unique<VkShaderModule> >	ShaderModuleSP;
63 using de::MovePtr;
64 
65 using tcu::Vec4;
66 
67 enum TestType
68 {
69 	TEST_TYPE_FLAT = 0,
70 	TEST_TYPE_NOPERSPECTIVE,
71 	TEST_TYPE_RELAXEDPRECISION,
72 	TEST_TYPE_LAST
73 };
74 
75 struct TestParameters
76 {
TestParametersvkt::SpirVAssembly::__anon9c06815e0111::TestParameters77 	TestParameters (TestType q, size_t s)
78 		:testOptions	(s)
79 		,qualifier		(q)
80 	{}
81 	vector<int>		testOptions;
82 	TestType		qualifier;
83 };
84 
makeImageCreateInfo(const VkImageType imageType,const VkExtent3D & extent,const VkFormat format,const VkImageUsageFlags usage,deUint32 queueFamilyIndex)85 VkImageCreateInfo makeImageCreateInfo (const VkImageType imageType, const VkExtent3D& extent, const VkFormat format, const VkImageUsageFlags usage, deUint32 queueFamilyIndex)
86 {
87 	const VkImageCreateInfo imageInfo	=
88 	{
89 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,		// VkStructureType			sType;
90 		DE_NULL,									// const void*				pNext;
91 		(VkImageCreateFlags)0,						// VkImageCreateFlags		flags;
92 		imageType,									// VkImageType				imageType;
93 		format,										// VkFormat					format;
94 		{extent.width, extent.height, 1u},			// VkExtent3D				extent;
95 		1u,											// uint32_t					mipLevels;
96 		extent.depth,								// uint32_t					arrayLayers;
97 		VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits	samples;
98 		VK_IMAGE_TILING_OPTIMAL,					// VkImageTiling			tiling;
99 		usage,										// VkImageUsageFlags		usage;
100 		VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode			sharingMode;
101 		1u,											// uint32_t					queueFamilyIndexCount;
102 		&queueFamilyIndex,							// const uint32_t*			pQueueFamilyIndices;
103 		VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout			initialLayout;
104 	};
105 	return imageInfo;
106 }
107 
imageBarrier(const DeviceInterface & vk,const VkCommandBuffer cmdBuffer,const VkImage image,const VkImageSubresourceRange subresourceRange,const VkImageLayout oldLayout,const VkImageLayout newLayout,const VkAccessFlags srcAccessMask,const VkAccessFlags dstAccessMask,const VkPipelineStageFlags srcStageMask,const VkPipelineStageFlags dstStageMask)108 void imageBarrier (const DeviceInterface&			vk,
109 				   const VkCommandBuffer			cmdBuffer,
110 				   const VkImage					image,
111 				   const VkImageSubresourceRange	subresourceRange,
112 				   const VkImageLayout				oldLayout,
113 				   const VkImageLayout				newLayout,
114 				   const VkAccessFlags				srcAccessMask,
115 				   const VkAccessFlags				dstAccessMask,
116 				   const VkPipelineStageFlags		srcStageMask,
117 				   const VkPipelineStageFlags		dstStageMask)
118 {
119 	const VkImageMemoryBarrier		barrier				=
120 	{
121 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,	// VkStructureType			sType;
122 		DE_NULL,								// const void*				pNext;
123 		srcAccessMask,							// VkAccessFlags			srcAccessMask;
124 		dstAccessMask,							// VkAccessFlags			dstAccessMask;
125 		oldLayout,								// VkImageLayout			oldLayout;
126 		newLayout,								// VkImageLayout			newLayout;
127 		VK_QUEUE_FAMILY_IGNORED,				// deUint32					srcQueueFamilyIndex;
128 		VK_QUEUE_FAMILY_IGNORED,				// deUint32					dstQueueFamilyIndex;
129 		image,									// VkImage					image;
130 		subresourceRange,						// VkImageSubresourceRange	subresourceRange;
131 	};
132 
133 	vk.cmdPipelineBarrier(cmdBuffer, srcStageMask, dstStageMask, (VkDependencyFlags)0, 0u, (const VkMemoryBarrier*)DE_NULL,
134 		0u, (const VkBufferMemoryBarrier*)DE_NULL,
135 		1u, &barrier);
136 }
137 
138 class CrossStageTestInstance : public TestInstance
139 {
140 public:
CrossStageTestInstance(Context & context,const TestParameters & parameters)141 	CrossStageTestInstance	(Context& context, const TestParameters& parameters)
142 	: TestInstance		(context)
143 	, m_parameters		(parameters)
144 	, m_verticesCount	(4u)
145 	, m_data			(2u * m_verticesCount)
146 	, m_colorFormat		(VK_FORMAT_R8G8B8A8_UNORM)
147 	, m_colorRed		(1.0f, 0.0f, 0.0f, 1.0f)
148 	, m_colorGreen		(0.0f, 1.0f, 0.0f, 1.0f)
149 	{
150 		createVertexData();
151 		m_extent.width	= 51u;
152 		m_extent.height	= 51u;
153 		m_extent.depth	= 1u;
154 	}
155 enum
156 {
157 	DECORATION_IN_VERTEX = 0,
158 	DECORATION_IN_FRAGMENT,
159 	DECORATION_IN_ALL_SHADERS,
160 	DECORATION_LAST
161 };
162 protected:
163 	tcu::TestStatus			iterate					(void);
164 private:
165 	void					createVertexData		(void);
166 	void					makeShaderModule		(map<VkShaderStageFlagBits, ShaderModuleSP>&	shaderModule,
167 													 const VkShaderStageFlagBits					stageFlag,
168 													 const int										optionNdx);
169 
170 	Move<VkPipeline>		makeGraphicsPipeline	(const VkRenderPass								renderPass,
171 													 const VkPipelineLayout							pipelineLayout,
172 													 const VkShaderStageFlagBits					stageFlags,
173 													 map<VkShaderStageFlagBits, ShaderModuleSP>&	shaderModules,
174 													 const VkPrimitiveTopology						primitiveTopology);
175 
176 	bool					checkImage				(VkImage										image,
177 													 VkCommandBuffer								cmdBuffer,
178 													 const string&									description,
179 													 const tcu::Texture2DArray&						referenceFrame);
180 	void					interpolationFill		(tcu::Texture2DArray&							referenceFrame);
181 	void					perspectiveFill			(tcu::Texture2DArray&							referenceFrame);
182 	void					redFill					(tcu::Texture2DArray&							referenceFrame);
183 
184 	const TestParameters	m_parameters;
185 	const deUint32			m_verticesCount;
186 	vector<Vec4>			m_data;
187 	VkExtent3D				m_extent;
188 	const VkFormat			m_colorFormat;
189 	const Vec4				m_colorRed;
190 	const Vec4				m_colorGreen;
191 };
192 
iterate(void)193 tcu::TestStatus CrossStageTestInstance::iterate (void)
194 {
195 	const DeviceInterface&					vk						= m_context.getDeviceInterface();
196 	const VkDevice							vkDevice				= m_context.getDevice();
197 	const VkPhysicalDeviceFeatures&			features				= m_context.getDeviceFeatures();
198 	const bool								supportsGeometry		= features.geometryShader == VK_TRUE;
199 	const bool								supportsTessellation	= features.tessellationShader == VK_TRUE;
200 	const VkDeviceSize						vertexDataSize			= static_cast<VkDeviceSize>(deAlignSize(static_cast<size_t>( m_data.size() * sizeof(Vec4)),
201 																		static_cast<size_t>(m_context.getDeviceProperties().limits.nonCoherentAtomSize)));
202 	const VkBufferCreateInfo				bufferInfo				= makeBufferCreateInfo(vertexDataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
203 	Move<VkBuffer>							vertexBuffer			= createBuffer(vk, vkDevice, &bufferInfo);
204 	MovePtr<Allocation>						allocationVertex		= m_context.getDefaultAllocator().allocate(getBufferMemoryRequirements(vk, vkDevice, *vertexBuffer),  MemoryRequirement::HostVisible);
205 
206 	const VkImageSubresourceRange			imageSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
207 	const VkImageCreateInfo					colorAttachmentInfo		= makeImageCreateInfo(VK_IMAGE_TYPE_2D, m_extent, m_colorFormat,
208 																		VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, m_context.getUniversalQueueFamilyIndex());
209 
210 	Move<VkImage>							colorAttachmentImage	= createImage(vk, vkDevice, &colorAttachmentInfo);
211 	MovePtr<Allocation>						allocationAttachment	= m_context.getDefaultAllocator().allocate(getImageMemoryRequirements(vk, vkDevice, *colorAttachmentImage), MemoryRequirement::Any);
212 	VK_CHECK(vk.bindImageMemory(vkDevice, *colorAttachmentImage, allocationAttachment->getMemory(), allocationAttachment->getOffset()));
213 	Move<VkImageView>						colorAttachmentView		= makeImageView(vk, vkDevice, *colorAttachmentImage, VK_IMAGE_VIEW_TYPE_2D, m_colorFormat, imageSubresourceRange);
214 
215 	MovePtr<tcu::Texture2DArray>			referenceImage1			= MovePtr<tcu::Texture2DArray>(new tcu::Texture2DArray(mapVkFormat(m_colorFormat), m_extent.width, m_extent.height, m_extent.depth));
216 	MovePtr<tcu::Texture2DArray>			referenceImage2			= MovePtr<tcu::Texture2DArray>(new tcu::Texture2DArray(mapVkFormat(m_colorFormat), m_extent.width, m_extent.height, m_extent.depth));
217 
218 	// Init host buffer data
219 	VK_CHECK(vk.bindBufferMemory(vkDevice, *vertexBuffer, allocationVertex->getMemory(), allocationVertex->getOffset()));
220 	deMemcpy(allocationVertex->getHostPtr(), m_data.data(), de::dataSize(m_data));
221 	flushAlloc(vk, vkDevice, *allocationVertex);
222 
223 	Move<VkRenderPass>						renderPass				= makeRenderPass (vk, vkDevice, m_colorFormat);
224 	Move<VkFramebuffer>						frameBuffer				= makeFramebuffer (vk, vkDevice, *renderPass, *colorAttachmentView, m_extent.width, m_extent.height);
225 	Move<VkPipelineLayout>					pipelineLayout			= makePipelineLayout (vk, vkDevice);
226 	Move<VkCommandPool>						cmdPool;
227 	Move<VkCommandBuffer>					cmdBuffer;
228 
229 	// cmdPool
230 	{
231 		const VkCommandPoolCreateInfo cmdPoolParams =
232 		{
233 			VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,			// VkStructureType		sType;
234 			DE_NULL,											// const void*			pNext;
235 			VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,	// VkCmdPoolCreateFlags	flags;
236 			m_context.getUniversalQueueFamilyIndex(),			// deUint32				queueFamilyIndex;
237 		};
238 		cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
239 	}
240 
241 	// cmdBuffer
242 	{
243 		const VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
244 		{
245 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,		// VkStructureType		sType;
246 			DE_NULL,											// const void*			pNext;
247 			*cmdPool,											// VkCommandPool		commandPool;
248 			VK_COMMAND_BUFFER_LEVEL_PRIMARY,					// VkCommandBufferLevel	level;
249 			1u,													// deUint32				bufferCount;
250 		};
251 		cmdBuffer	= allocateCommandBuffer(vk, vkDevice, &cmdBufferAllocateInfo);
252 	}
253 
254 	if (!supportsTessellation)
255 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Tessellation not supported" << tcu::TestLog::EndMessage;
256 
257 	if (!supportsGeometry)
258 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Geometry not supported" << tcu::TestLog::EndMessage;
259 
260 	vector<deUint32> shadersStagesFlagsBits;
261 	shadersStagesFlagsBits.push_back(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
262 
263 	if (supportsTessellation)
264 		shadersStagesFlagsBits.push_back(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
265 
266 	if (supportsGeometry)
267 		shadersStagesFlagsBits.push_back(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
268 
269 	if (supportsTessellation && supportsGeometry)
270 		shadersStagesFlagsBits.push_back(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | VK_SHADER_STAGE_GEOMETRY_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);
271 
272 	referenceImage1->allocLevel(0);
273 	referenceImage2->allocLevel(0);
274 	switch(m_parameters.qualifier)
275 	{
276 	case TEST_TYPE_FLAT:
277 		interpolationFill(*referenceImage1);
278 		redFill(*referenceImage2);
279 		break;
280 	case TEST_TYPE_NOPERSPECTIVE:
281 		perspectiveFill(*referenceImage1);
282 		interpolationFill(*referenceImage2);
283 		break;
284 	case TEST_TYPE_RELAXEDPRECISION:
285 		interpolationFill(*referenceImage1);
286 		interpolationFill(*referenceImage2);
287 		break;
288 	default:
289 		DE_ASSERT(0);
290 	}
291 
292 	for (deUint32 optionNdx = 0; optionNdx < m_parameters.testOptions.size(); optionNdx++)
293 	for (size_t stagesNdx = 0ull; stagesNdx < shadersStagesFlagsBits.size(); stagesNdx++)
294 	{
295 		map<VkShaderStageFlagBits, ShaderModuleSP>	shaderModule;
296 		string										imageDescription;
297 		const VkClearValue							renderPassClearValue = makeClearValueColor(tcu::Vec4(0.0f));
298 		makeShaderModule(shaderModule, (VkShaderStageFlagBits)shadersStagesFlagsBits[stagesNdx], optionNdx);
299 
300 		Move<VkPipeline>			graphicsPipeline		= makeGraphicsPipeline (*renderPass, *pipelineLayout, (VkShaderStageFlagBits)shadersStagesFlagsBits[stagesNdx], shaderModule, ((VkShaderStageFlagBits)shadersStagesFlagsBits[stagesNdx] & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
301 		const VkDeviceSize			vertexBufferOffset		= 0u;
302 
303 		beginCommandBuffer(vk, *cmdBuffer);
304 
305 		imageBarrier(vk, *cmdBuffer, *colorAttachmentImage, imageSubresourceRange,
306 			VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
307 			0u, VK_ACCESS_TRANSFER_WRITE_BIT,
308 			VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
309 
310 		vk.cmdClearColorImage(*cmdBuffer, *colorAttachmentImage,  VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &renderPassClearValue.color, 1, &imageSubresourceRange);
311 
312 		imageBarrier(vk, *cmdBuffer, *colorAttachmentImage, imageSubresourceRange,
313 			VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
314 			VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
315 			VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
316 
317 		beginRenderPass(vk, *cmdBuffer, *renderPass, *frameBuffer, makeRect2D(0, 0, m_extent.width, m_extent.height), tcu::Vec4(0.0f));
318 
319 		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &(*vertexBuffer), &vertexBufferOffset);
320 
321 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
322 
323 		vk.cmdDraw(*cmdBuffer, m_verticesCount, 1u, 0u, 0u);
324 
325 		endRenderPass(vk, *cmdBuffer);
326 
327 		endCommandBuffer(vk, *cmdBuffer);
328 
329 		submitCommandsAndWait(vk, vkDevice, m_context.getUniversalQueue(), *cmdBuffer);
330 
331 		{
332 			const string geometry		= (VK_SHADER_STAGE_GEOMETRY_BIT & (VkShaderStageFlagBits)shadersStagesFlagsBits[stagesNdx]) ? "Geometry->" : "";
333 			const string tessellation	= ( VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT & (VkShaderStageFlagBits)shadersStagesFlagsBits[stagesNdx]) ? "Tessellation->" : "";
334 			imageDescription = "Pipeline: Vertex->" + tessellation +  geometry + "Fragment | ";
335 		}
336 
337 		if (DECORATION_IN_VERTEX == m_parameters.testOptions[optionNdx])
338 			imageDescription+= "decoration in vertex | ";
339 		if (DECORATION_IN_FRAGMENT == m_parameters.testOptions[optionNdx])
340 			imageDescription+= "decoration in fragment | ";
341 		if (DECORATION_IN_ALL_SHADERS == m_parameters.testOptions[optionNdx])
342 			imageDescription+= "decoration in all shaders | ";
343 
344 		{
345 			bool resultComparison = false;
346 			if (TEST_TYPE_RELAXEDPRECISION == m_parameters.qualifier)
347 			{
348 				resultComparison = checkImage(*colorAttachmentImage, *cmdBuffer, imageDescription+" Expected Pass", *referenceImage1);
349 			}
350 			else
351 			{
352 				if (DECORATION_IN_VERTEX == m_parameters.testOptions[optionNdx])
353 					resultComparison = checkImage(*colorAttachmentImage, *cmdBuffer, imageDescription+" Expected Pass", *referenceImage1);
354 				else if ((VkShaderStageFlagBits)(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT) == (VkShaderStageFlagBits)shadersStagesFlagsBits[stagesNdx])
355 					resultComparison = checkImage(*colorAttachmentImage, *cmdBuffer, imageDescription+" Expected Pass", *referenceImage2);
356 				else
357 					resultComparison = !checkImage(*colorAttachmentImage, *cmdBuffer, imageDescription+" Expected Fail", *referenceImage1);
358 			}
359 
360 			if(!resultComparison)
361 				return tcu::TestStatus::fail("Fail");
362 		}
363 	}
364 	return tcu::TestStatus::pass("Pass");
365 }
366 
createVertexData(void)367 void CrossStageTestInstance::createVertexData (void)
368 {
369 	int ndx = -1;
370 	if (TEST_TYPE_NOPERSPECTIVE == m_parameters.qualifier)
371 		m_data[++ndx] = Vec4(-2.0f,-2.0f, 1.0f, 2.0f);	//position
372 	else
373 		m_data[++ndx] = Vec4(-1.0f,-1.0f, 1.0f, 1.0f);	//position
374 	m_data[++ndx] = m_colorRed;
375 
376 	if (TEST_TYPE_NOPERSPECTIVE == m_parameters.qualifier)
377 		m_data[++ndx] = Vec4(-2.0f, 2.0f, 1.0f, 2.0f);	//position
378 	else
379 		m_data[++ndx] = Vec4(-1.0f, 1.0f, 1.0f, 1.0f);	//position
380 	m_data[++ndx] = m_colorRed;
381 
382 	m_data[++ndx] = Vec4( 1.0f,-1.0f, 1.0f, 1.0f);	//position
383 	m_data[++ndx] = m_colorGreen;
384 
385 	m_data[++ndx] = Vec4( 1.0f, 1.0f, 1.0f, 1.0f);	//position
386 	m_data[++ndx] = m_colorGreen;
387 }
388 
makeShaderModule(map<VkShaderStageFlagBits,ShaderModuleSP> & shaderModule,const VkShaderStageFlagBits stageFlag,const int optionNdx)389 void CrossStageTestInstance::makeShaderModule (map<VkShaderStageFlagBits, ShaderModuleSP>&	shaderModule,
390 											   const VkShaderStageFlagBits					stageFlag,
391 											   const int									optionNdx)
392 {
393 	const DeviceInterface&	vk			= m_context.getDeviceInterface();
394 	const VkDevice			vkDevice	= m_context.getDevice();
395 
396 	std::ostringstream vertex;
397 	vertex<<"vertex"<<optionNdx;
398 	std::ostringstream fragment;
399 	fragment<<"fragment"<<optionNdx;
400 
401 	if (stageFlag & VK_SHADER_STAGE_VERTEX_BIT)
402 		shaderModule[VK_SHADER_STAGE_VERTEX_BIT] = (ShaderModuleSP(new Unique<VkShaderModule>(createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get(vertex.str()), 0))));
403 
404 	if (stageFlag & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
405 		shaderModule[VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT] = (ShaderModuleSP(new Unique<VkShaderModule>(createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("tessellation_control"), 0))));
406 
407 	if (stageFlag & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
408 		shaderModule[VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT] = (ShaderModuleSP(new Unique<VkShaderModule>(createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("tessellation_evaluation"), 0))));
409 
410 	if (stageFlag & VK_SHADER_STAGE_GEOMETRY_BIT)
411 		shaderModule[VK_SHADER_STAGE_GEOMETRY_BIT] = (ShaderModuleSP(new Unique<VkShaderModule>(createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("geometry"), 0))));
412 
413 	if (stageFlag & VK_SHADER_STAGE_FRAGMENT_BIT)
414 		shaderModule[VK_SHADER_STAGE_FRAGMENT_BIT] = (ShaderModuleSP(new Unique<VkShaderModule>(createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get(fragment.str()), 0))));
415 }
416 
makeGraphicsPipeline(const VkRenderPass renderPass,const VkPipelineLayout pipelineLayout,const VkShaderStageFlagBits shaderFlags,map<VkShaderStageFlagBits,ShaderModuleSP> & shaderModules,const VkPrimitiveTopology primitiveTopology)417 Move<VkPipeline> CrossStageTestInstance::makeGraphicsPipeline (const VkRenderPass							renderPass,
418 															   const VkPipelineLayout						pipelineLayout,
419 															   const VkShaderStageFlagBits					shaderFlags,
420 															   map<VkShaderStageFlagBits, ShaderModuleSP>&	shaderModules,
421 															   const VkPrimitiveTopology					primitiveTopology)
422 {
423 	const DeviceInterface&	vk			= m_context.getDeviceInterface();
424 	const VkDevice			vkDevice	= m_context.getDevice();
425 
426 	const VkVertexInputBindingDescription			vertexInputBindingDescription		=
427 	{
428 		0u,										// binding;
429 		static_cast<deUint32>(2u*sizeof(Vec4)),	// stride;
430 		VK_VERTEX_INPUT_RATE_VERTEX				// inputRate
431 	};
432 
433 	const VkVertexInputAttributeDescription			vertexInputAttributeDescriptions[]	=
434 	{
435 		{
436 			0u,
437 			0u,
438 			VK_FORMAT_R32G32B32A32_SFLOAT,
439 			0u
440 		},	// VertexElementData::position
441 		{
442 			1u,
443 			0u,
444 			VK_FORMAT_R32G32B32A32_SFLOAT,
445 			static_cast<deUint32>(sizeof(tcu::Vec4))
446 		},	// VertexElementData::color
447 	};
448 
449 	const VkPipelineVertexInputStateCreateInfo		vertexInputStateParams				=
450 	{																	// sType;
451 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// pNext;
452 		NULL,															// flags;
453 		0u,																// vertexBindingDescriptionCount;
454 		1u,																// pVertexBindingDescriptions;
455 		&vertexInputBindingDescription,									// vertexAttributeDescriptionCount;
456 		2u,																// pVertexAttributeDescriptions;
457 		vertexInputAttributeDescriptions
458 	};
459 
460 	const std::vector<VkViewport>					viewports							(1, makeViewport(m_extent));
461 	const std::vector<VkRect2D>						scissors							(1, makeRect2D(m_extent));
462 
463 	VkPipelineDepthStencilStateCreateInfo			depthStencilStateParams				=
464 	{
465 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType;
466 		DE_NULL,													// const void*								pNext;
467 		0u,															// VkPipelineDepthStencilStateCreateFlags	flags;
468 		VK_TRUE,													// VkBool32									depthTestEnable;
469 		VK_TRUE,													// VkBool32									depthWriteEnable;
470 		VK_COMPARE_OP_LESS_OR_EQUAL,								// VkCompareOp								depthCompareOp;
471 		VK_FALSE,													// VkBool32									depthBoundsTestEnable;
472 		VK_FALSE,													// VkBool32									stencilTestEnable;
473 		// VkStencilOpState front;
474 		{
475 			VK_STENCIL_OP_KEEP,		// VkStencilOp	failOp;
476 			VK_STENCIL_OP_KEEP,		// VkStencilOp	passOp;
477 			VK_STENCIL_OP_KEEP,		// VkStencilOp	depthFailOp;
478 			VK_COMPARE_OP_NEVER,	// VkCompareOp	compareOp;
479 			0u,						// deUint32		compareMask;
480 			0u,						// deUint32		writeMask;
481 			0u,						// deUint32		reference;
482 		},
483 		// VkStencilOpState back;
484 		{
485 			VK_STENCIL_OP_KEEP,		// VkStencilOp	failOp;
486 			VK_STENCIL_OP_KEEP,		// VkStencilOp	passOp;
487 			VK_STENCIL_OP_KEEP,		// VkStencilOp	depthFailOp;
488 			VK_COMPARE_OP_NEVER,	// VkCompareOp	compareOp;
489 			0u,						// deUint32		compareMask;
490 			0u,						// deUint32		writeMask;
491 			0u,						// deUint32		reference;
492 		},
493 		0.0f,	// float	minDepthBounds;
494 		1.0f,	// float	maxDepthBounds;
495 	};
496 
497 	const VkShaderModule	vertShader			= shaderFlags & VK_SHADER_STAGE_VERTEX_BIT ? **shaderModules[VK_SHADER_STAGE_VERTEX_BIT] : DE_NULL;
498 	const VkShaderModule	tessControlShader	= shaderFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ? **shaderModules[VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT] : DE_NULL;
499 	const VkShaderModule	tessEvalShader		= shaderFlags & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT ? **shaderModules[VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT] : DE_NULL;
500 	const VkShaderModule	geomShader			= shaderFlags & VK_SHADER_STAGE_GEOMETRY_BIT ? **shaderModules[VK_SHADER_STAGE_GEOMETRY_BIT] : DE_NULL;
501 	const VkShaderModule	fragShader			= shaderFlags & VK_SHADER_STAGE_FRAGMENT_BIT ? **shaderModules[VK_SHADER_STAGE_FRAGMENT_BIT] : DE_NULL;
502 
503 	return vk::makeGraphicsPipeline(vk,							// const DeviceInterface&                        vk
504 									vkDevice,					// const VkDevice                                device
505 									pipelineLayout,				// const VkPipelineLayout                        pipelineLayout
506 									vertShader,					// const VkShaderModule                          vertexShaderModule
507 									tessControlShader,			// const VkShaderModule                          tessellationControlShaderModule
508 									tessEvalShader,				// const VkShaderModule                          tessellationEvalShaderModule
509 									geomShader,					// const VkShaderModule                          geometryShaderModule
510 									fragShader,					// const VkShaderModule                          fragmentShaderModule
511 									renderPass,					// const VkRenderPass                            renderPass
512 									viewports,					// const std::vector<VkViewport>&                viewports
513 									scissors,					// const std::vector<VkRect2D>&                  scissors
514 									primitiveTopology,			// const VkPrimitiveTopology                     topology
515 									0u,							// const deUint32                                subpass
516 									4u,							// const deUint32                                patchControlPoints
517 									&vertexInputStateParams,	// const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
518 									DE_NULL,					// const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
519 									DE_NULL,					// const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
520 									&depthStencilStateParams);	// const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo
521 }
522 
checkImage(VkImage image,VkCommandBuffer cmdBuffer,const string & description,const tcu::Texture2DArray & referenceFrame)523 bool CrossStageTestInstance::checkImage (VkImage image, VkCommandBuffer cmdBuffer, const string& description, const tcu::Texture2DArray& referenceFrame)
524 {
525 	const DeviceInterface&		vk				= m_context.getDeviceInterface();
526 	const VkDevice				vkDevice		= m_context.getDevice();
527 	const int					pixelSize		= referenceFrame.getFormat().getPixelSize();
528 	Move<VkBuffer>				buffer;
529 	MovePtr<Allocation>			bufferAlloc;
530 	vector<deUint8>				pixelAccessData	(m_extent.width * m_extent.height * m_extent.depth * pixelSize);
531 	tcu::PixelBufferAccess		dst				(referenceFrame.getFormat(), m_extent.width, m_extent.height, m_extent.depth, pixelAccessData.data());
532 	const VkDeviceSize			pixelDataSize	= dst.getWidth() * dst.getHeight() * dst.getDepth() * pixelSize;
533 
534 	// Create destination buffer
535 	{
536 		const VkBufferCreateInfo bufferParams =
537 		{
538 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
539 			DE_NULL,									// const void*			pNext;
540 			0u,											// VkBufferCreateFlags	flags;
541 			pixelDataSize,								// VkDeviceSize			size;
542 			VK_BUFFER_USAGE_TRANSFER_DST_BIT,			// VkBufferUsageFlags	usage;
543 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
544 			0u,											// deUint32				queueFamilyIndexCount;
545 			DE_NULL,									// const deUint32*		pQueueFamilyIndices;
546 		};
547 
548 		buffer		= createBuffer(vk, vkDevice, &bufferParams);
549 		bufferAlloc	= m_context.getDefaultAllocator().allocate(getBufferMemoryRequirements(vk, vkDevice, *buffer), MemoryRequirement::HostVisible);
550 		VK_CHECK(vk.bindBufferMemory(vkDevice, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
551 
552 		deMemset(bufferAlloc->getHostPtr(), 0, static_cast<size_t>(pixelDataSize));
553 		flushAlloc(vk, vkDevice, *bufferAlloc);
554 	}
555 
556 	beginCommandBuffer (vk, cmdBuffer);
557 	copyImageToBuffer(vk, cmdBuffer, image, *buffer, tcu::IVec2(m_extent.width, m_extent.height), 0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, m_extent.depth);
558 	endCommandBuffer(vk, cmdBuffer);
559 	submitCommandsAndWait(vk, vkDevice, m_context.getUniversalQueue(), cmdBuffer);
560 
561 	// Read buffer data
562 	invalidateAlloc(vk, vkDevice, *bufferAlloc);
563 	tcu::copy(dst, tcu::ConstPixelBufferAccess(dst.getFormat(), dst.getSize(), bufferAlloc->getHostPtr()));
564 
565 	if (tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Result", description.c_str(), referenceFrame.getLevel(0), dst, tcu::Vec4(0.05f), tcu::COMPARE_LOG_EVERYTHING))
566 		return true;
567 	return false;
568 }
569 
interpolationFill(tcu::Texture2DArray & referenceFrame)570 void CrossStageTestInstance::interpolationFill (tcu::Texture2DArray& referenceFrame)
571 {
572 	for (deUint32 x = 0u; x < m_extent.width; ++x)
573 	{
574 		float u = static_cast<float>(x)/static_cast<float>(m_extent.width - 1);
575 		const Vec4 resultColor (m_colorRed.x() * (1.0f - u) + m_colorGreen.x() * u,
576 								m_colorRed.y() * (1.0f - u) + m_colorGreen.y() * u,
577 								m_colorRed.z() * (1.0f - u) + m_colorGreen.z() * u,
578 								m_colorRed.w() * (1.0f - u) + m_colorGreen.w() * u);
579 
580 		referenceFrame.getLevel(0).setPixel(resultColor,x,0);
581 	}
582 
583 	for (deUint32 y = 0u; y < m_extent.height; ++y)
584 	{
585 		deMemcpy (referenceFrame.getLevel(0).getPixelPtr(0,y), referenceFrame.getLevel(0).getPixelPtr(0,0), m_extent.width * m_extent.depth* referenceFrame.getFormat().getPixelSize());
586 	}
587 }
588 
perspectiveFill(tcu::Texture2DArray & referenceFrame)589 void CrossStageTestInstance::perspectiveFill (tcu::Texture2DArray& referenceFrame)
590 {
591 	float dynamics = 1.732f;
592 	float dynamicChange = 0.732f / static_cast<float>(m_extent.width);
593 	for (deUint32 x = 0u; x < m_extent.width; ++x)
594 	{
595 		float u = static_cast<float>(x)/static_cast<float>(m_extent.width - 1);
596 		const Vec4 resultColor (m_colorRed.x() * (1.0f - dynamics * u) + m_colorGreen.x() * u* dynamics,
597 								m_colorRed.y() * (1.0f - dynamics * u) + m_colorGreen.y() * u* dynamics,
598 								m_colorRed.z() * (1.0f - dynamics * u) + m_colorGreen.z() * u* dynamics,
599 								m_colorRed.w() * (1.0f - dynamics * u) + m_colorGreen.w() * u* dynamics);
600 		dynamics -= dynamicChange;
601 		if (dynamics < 1.0f)
602 			dynamics = 1.0f;
603 
604 		referenceFrame.getLevel(0).setPixel(resultColor,x,0);
605 	}
606 
607 	for (deUint32 y = 0u; y < m_extent.height; ++y)
608 	{
609 		deMemcpy (referenceFrame.getLevel(0).getPixelPtr(0,y), referenceFrame.getLevel(0).getPixelPtr(0,0), m_extent.width * m_extent.depth* referenceFrame.getFormat().getPixelSize());
610 	}
611 }
612 
redFill(tcu::Texture2DArray & referenceFrame)613 void CrossStageTestInstance::redFill (tcu::Texture2DArray& referenceFrame)
614 {
615 	for (deUint32 x = 0u; x < m_extent.width; ++x)
616 		referenceFrame.getLevel(0).setPixel(m_colorRed,x,0);
617 
618 	for (deUint32 y = 0u; y < m_extent.height; ++y)
619 		deMemcpy (referenceFrame.getLevel(0).getPixelPtr(0,y), referenceFrame.getLevel(0).getPixelPtr(0,0), m_extent.width * m_extent.depth* referenceFrame.getFormat().getPixelSize());
620 }
621 
622 struct Decorations
623 {
Decorationsvkt::SpirVAssembly::__anon9c06815e0111::Decorations624 	Decorations()
625 	{}
Decorationsvkt::SpirVAssembly::__anon9c06815e0111::Decorations626 	Decorations(const string& f, const string& v, const string& o)
627 		: fragment	(f)
628 		, vertex	(v)
629 		, others	(o)
630 	{}
631 	string fragment;
632 	string vertex;
633 	string others;
634 };
635 
636 class CrossStageBasicTestsCase : public vkt::TestCase
637 {
638 public:
CrossStageBasicTestsCase(tcu::TestContext & context,const char * name,const char * description,const TestParameters & parameters)639 	CrossStageBasicTestsCase (tcu::TestContext &context, const char *name, const char *description, const TestParameters& parameters)
640 		: TestCase			(context, name, description)
641 		, m_parameters		(parameters)
642 	{
643 	}
644 private:
645 	vkt::TestInstance*	createInstance		(vkt::Context& context) const;
646 	void				initPrograms		(SourceCollections& programCollection) const;
647 
648 	const TestParameters	m_parameters;
649 
650 };
651 
createInstance(vkt::Context & context) const652 vkt::TestInstance* CrossStageBasicTestsCase::createInstance (vkt::Context& context) const
653 {
654 	return new CrossStageTestInstance(context, m_parameters);
655 }
656 
initPrograms(SourceCollections & programCollection) const657 void CrossStageBasicTestsCase::initPrograms (SourceCollections& programCollection) const
658 {
659 	vector<Decorations> decorations;
660 	string epsilon = "3e-7";
661 	switch(m_parameters.qualifier)
662 	{
663 	case TEST_TYPE_FLAT:
664 		decorations.push_back(Decorations("",
665 								//Vertex
666 								"OpDecorate %color_out Flat\n"
667 								"OpDecorate %r_float_out Flat\n"
668 								"OpDecorate %rg_float_out Flat\n"
669 								"OpDecorate %rgb_float_out Flat\n"
670 								"OpDecorate %rgba_float_out Flat\n",
671 								""));
672 		decorations.push_back(Decorations(//Fragment
673 								"OpDecorate %color_in Flat\n"
674 								"OpDecorate %r_float_in Flat\n"
675 								"OpDecorate %rg_float_in Flat\n"
676 								"OpDecorate %rgb_float_in Flat\n"
677 								"OpDecorate %rgba_float_in Flat\n",
678 								"",
679 								""));
680 
681 		decorations.push_back(Decorations(//Fragment
682 								"OpDecorate %color_in Flat\n"
683 								"OpDecorate %r_float_in Flat\n"
684 								"OpDecorate %rg_float_in Flat\n"
685 								"OpDecorate %rgb_float_in Flat\n"
686 								"OpDecorate %rgba_float_in Flat\n",
687 								//Vertex
688 								"OpDecorate %color_out Flat\n"
689 								"OpDecorate %r_float_out Flat\n"
690 								"OpDecorate %rg_float_out Flat\n"
691 								"OpDecorate %rgb_float_out Flat\n"
692 								"OpDecorate %rgba_float_out Flat\n",
693 								""));
694 		epsilon = "0.0";
695 		break;
696 	case TEST_TYPE_NOPERSPECTIVE:
697 		decorations.push_back(Decorations("",
698 								//Vertex
699 								"OpDecorate %color_out NoPerspective\n"
700 								"OpDecorate %r_float_out NoPerspective\n"
701 								"OpDecorate %rg_float_out NoPerspective\n"
702 								"OpDecorate %rgb_float_out NoPerspective\n"
703 								"OpDecorate %rgba_float_out NoPerspective\n",
704 								""));
705 
706 		decorations.push_back(Decorations(//Fragment
707 								"OpDecorate %color_in NoPerspective\n"
708 								"OpDecorate %r_float_in NoPerspective\n"
709 								"OpDecorate %rg_float_in NoPerspective\n"
710 								"OpDecorate %rgb_float_in NoPerspective\n"
711 								"OpDecorate %rgba_float_in NoPerspective\n",
712 								"",
713 								""));
714 
715 		decorations.push_back(Decorations(//Fragment
716 								"OpDecorate %color_in NoPerspective\n"
717 								"OpDecorate %r_float_in NoPerspective\n"
718 								"OpDecorate %rg_float_in NoPerspective\n"
719 								"OpDecorate %rgb_float_in NoPerspective\n"
720 								"OpDecorate %rgba_float_in NoPerspective\n",
721 								//Vertex
722 								"OpDecorate %color_out NoPerspective\n"
723 								"OpDecorate %r_float_out NoPerspective\n"
724 								"OpDecorate %rg_float_out NoPerspective\n"
725 								"OpDecorate %rgb_float_out NoPerspective\n"
726 								"OpDecorate %rgba_float_out NoPerspective\n",
727 								//Others
728 								""));
729 		break;
730 	case TEST_TYPE_RELAXEDPRECISION:
731 		decorations.push_back(Decorations(//Fragment
732 								"OpDecorate %color_out RelaxedPrecision\n"
733 								"OpDecorate %color_in RelaxedPrecision\n"
734 								"OpDecorate %r_float_in RelaxedPrecision\n"
735 								"OpDecorate %rg_float_in RelaxedPrecision\n"
736 								"OpDecorate %rgb_float_in RelaxedPrecision\n"
737 								"OpDecorate %rgba_float_in RelaxedPrecision\n",
738 								//Vertex
739 								"OpDecorate %color_out RelaxedPrecision\n"
740 								"OpDecorate %color_in RelaxedPrecision\n"
741 								"OpDecorate %r_float_out RelaxedPrecision\n"
742 								"OpDecorate %rg_float_out RelaxedPrecision\n"
743 								"OpDecorate %rgb_float_out RelaxedPrecision\n"
744 								"OpDecorate %rgba_float_out RelaxedPrecision\n",
745 								//Others
746 								"OpDecorate %color_out RelaxedPrecision\n"
747 								"OpDecorate %color_in RelaxedPrecision\n"
748 								"OpDecorate %r_float_out RelaxedPrecision\n"
749 								"OpDecorate %rg_float_out RelaxedPrecision\n"
750 								"OpDecorate %rgb_float_out RelaxedPrecision\n"
751 								"OpDecorate %rgba_float_out RelaxedPrecision\n"
752 								"OpDecorate %r_float_in RelaxedPrecision\n"
753 								"OpDecorate %rg_float_in RelaxedPrecision\n"
754 								"OpDecorate %rgb_float_in RelaxedPrecision\n"
755 								"OpDecorate %rgba_float_in RelaxedPrecision\n"));
756 		epsilon = "2e-3";
757 		break;
758 	default:
759 		DE_ASSERT(0);
760 	}
761 
762 	//Spir-v spec: decoration flat can be used only in Shader (fragment or vertex)
763 	for (deUint32 ndx = 0; ndx < decorations.size(); ++ndx)
764 	{
765 
766 		/*#version 450
767 		layout(location = 0) in highp vec4 in_position;
768 		layout(location = 1) in vec4 in_color;
769 		layout(location = 0) out vec4 out_color;
770 		layout(location = 1) out float		r_float_out;
771 		layout(location = 2) out vec2		rg_float_out;
772 		layout(location = 3) out vec3		rgb_float_out;
773 		layout(location = 4) out vec4		rgba_float_out;
774 		void main (void)
775 		{
776 			gl_Position = in_position;
777 			out_color = in_color;
778 			r_float_out = in_color.r;
779 			rg_float_out = vec2(in_color.r, in_color.g);
780 			rgb_float_out = vec3(in_color.r, in_color.g,in_color.b);
781 			rgba_float_out = vec4(in_color.r, in_color.g, in_color.b, in_color.a);
782 		}
783 		*/
784 		const string vertexShaderSource =
785 		"; SPIR-V\n"
786 		"; Version: 1.3\n"
787 		"; Generator: Khronos Glslang Reference Front End; 2\n"
788 		"; Bound: 60\n"
789 		"; Schema: 0\n"
790 		"OpCapability Shader\n"
791 		"%1 = OpExtInstImport \"GLSL.std.450\"\n"
792 		"OpMemoryModel Logical GLSL450\n"
793 		"OpEntryPoint Vertex %4 \"main\" %13 %17 %color_out %color_in %r_float_out %rg_float_out %rgb_float_out %rgba_float_out\n"
794 		"OpMemberDecorate %11 0 BuiltIn Position\n"
795 		"OpMemberDecorate %11 1 BuiltIn PointSize\n"
796 		"OpMemberDecorate %11 2 BuiltIn ClipDistance\n"
797 		"OpMemberDecorate %11 3 BuiltIn CullDistance\n"
798 		"OpDecorate %11 Block\n"
799 		"OpDecorate %17 Location 0\n"
800 		"OpDecorate %color_out Location 0\n"
801 		"OpDecorate %color_in Location 1\n"
802 		"OpDecorate %r_float_out Location 1\n"
803 		"OpDecorate %rg_float_out Location 2\n"
804 		"OpDecorate %rgb_float_out Location 3\n"
805 		"OpDecorate %rgba_float_out Location 4\n"
806 		+decorations[ndx].vertex+
807 		"%2 = OpTypeVoid\n"
808 		"%3 = OpTypeFunction %2\n"
809 		"%6 = OpTypeFloat 32\n"
810 		"%7 = OpTypeVector %6 4\n"
811 		"%8 = OpTypeInt 32 0\n"
812 		"%9 = OpConstant %8 1\n"
813 		"%10 = OpTypeArray %6 %9\n"
814 		"%11 = OpTypeStruct %7 %6 %10 %10\n"
815 		"%12 = OpTypePointer Output %11\n"
816 		"%13 = OpVariable %12 Output\n"
817 		"%14 = OpTypeInt 32 1\n"
818 		"%15 = OpConstant %14 0\n"
819 		"%16 = OpTypePointer Input %7\n"
820 		"%17 = OpVariable %16 Input\n"
821 		"%19 = OpTypePointer Output %7\n"
822 		"%color_out = OpVariable %19 Output\n"
823 		"%color_in = OpVariable %16 Input\n"
824 		"%24 = OpTypePointer Output %6\n"
825 		"%r_float_out = OpVariable %24 Output\n"
826 		"%26 = OpConstant %8 0\n"
827 		"%27 = OpTypePointer Input %6\n"
828 		"%30 = OpTypeVector %6 2\n"
829 		"%31 = OpTypePointer Output %30\n"
830 		"%rg_float_out = OpVariable %31 Output\n"
831 		"%38 = OpTypeVector %6 3\n"
832 		"%39 = OpTypePointer Output %38\n"
833 		"%rgb_float_out = OpVariable %39 Output\n"
834 		"%45 = OpConstant %8 2\n"
835 		"%rgba_float_out = OpVariable %19 Output\n"
836 		"%56 = OpConstant %8 3\n"
837 		"%4 = OpFunction %2 None %3\n"
838 		"%5 = OpLabel\n"
839 		"%18 = OpLoad %7 %17\n"
840 		"%20 = OpAccessChain %19 %13 %15\n"
841 		"OpStore %20 %18\n"
842 		"%23 = OpLoad %7 %color_in\n"
843 		"OpStore %color_out %23\n"
844 		"%28 = OpAccessChain %27 %color_in %26\n"
845 		"%29 = OpLoad %6 %28\n"
846 		"OpStore %r_float_out %29\n"
847 		"%33 = OpAccessChain %27 %color_in %26\n"
848 		"%34 = OpLoad %6 %33\n"
849 		"%35 = OpAccessChain %27 %color_in %9\n"
850 		"%36 = OpLoad %6 %35\n"
851 		"%37 = OpCompositeConstruct %30 %34 %36\n"
852 		"OpStore %rg_float_out %37\n"
853 		"%41 = OpAccessChain %27 %color_in %26\n"
854 		"%42 = OpLoad %6 %41\n"
855 		"%43 = OpAccessChain %27 %color_in %9\n"
856 		"%44 = OpLoad %6 %43\n"
857 		"%46 = OpAccessChain %27 %color_in %45\n"
858 		"%47 = OpLoad %6 %46\n"
859 		"%48 = OpCompositeConstruct %38 %42 %44 %47\n"
860 		"OpStore %rgb_float_out %48\n"
861 		"%50 = OpAccessChain %27 %color_in %26\n"
862 		"%51 = OpLoad %6 %50\n"
863 		"%52 = OpAccessChain %27 %color_in %9\n"
864 		"%53 = OpLoad %6 %52\n"
865 		"%54 = OpAccessChain %27 %color_in %45\n"
866 		"%55 = OpLoad %6 %54\n"
867 		"%57 = OpAccessChain %27 %color_in %56\n"
868 		"%58 = OpLoad %6 %57\n"
869 		"%59 = OpCompositeConstruct %7 %51 %53 %55 %58\n"
870 		"OpStore %rgba_float_out %59\n"
871 		"OpReturn\n"
872 		"OpFunctionEnd\n";
873 
874 		/* #version 450
875 		layout(location = 0) out vec4  color_out;
876 		layout(location = 0) in vec4   color_in;
877 		layout(location = 1) in float  r_float_in;
878 		layout(location = 2) in vec2   rg_float_in;
879 		layout(location = 3) in vec3   rgb_float_in;
880 		layout(location = 4) in vec4   rgba_float_in;
881 		void main()
882 		{
883 			float epsilon = 3e-7; // or 0.0 for flat, or 2e-3 for RelaxedPrecision (mediump)
884 			color_out = color_in;
885 			float epsilon_float = max(abs(r_float_in), abs(color_in.r)) * epsilon;
886 			if(abs(r_float_in - color_in.r) > epsilon_float)
887 				color_out.r = 1.0f;
888 			vec2 epsilon_vec2 = max(abs(rg_float_in), abs(color_in.rg)) * epsilon;
889 			if(any(greaterThan(abs(rg_float_in - color_in.rg), epsilon_vec2)))
890 				color_out.rg = vec2(1.0f);
891 			vec3 epsilon_vec3 = max(abs(rgb_float_in), abs(color_in.rgb)) * epsilon;
892 			if(any(greaterThan(abs(rgb_float_in - color_in.rgb), epsilon_vec3)))
893 				color_out.rgb = vec3(1.0f);
894 			vec4 epsilon_vec4 = max(abs(rgba_float_in), abs(color_in.rgba)) * epsilon;
895 			if(any(greaterThan(abs(rgba_float_in - color_in.rgba), epsilon_vec4)))
896 				color_out.rgba = vec4(1.0f);
897 		}
898 		*/
899 
900 		const string fragmentShaderSource =
901 		"; SPIR-V\n"
902 		"; Version: 1.3\n"
903 		"; Generator: Khronos Glslang Reference Front End; 2\n"
904 		"; Bound: 64\n"
905 		"; Schema: 0\n"
906 		"OpCapability Shader\n"
907 		"%1 = OpExtInstImport \"GLSL.std.450\"\n"
908 		"OpMemoryModel Logical GLSL450\n"
909 		"OpEntryPoint Fragment %4 \"main\" %color_out %color_in %r_float_in %rg_float_in %rgb_float_in %rgba_float_in\n"
910 		"OpExecutionMode %4 OriginUpperLeft\n"
911 		"OpDecorate %color_out Location 0\n"
912 		"OpDecorate %color_in Location 0\n"
913 		"OpDecorate %r_float_in Location 1\n"
914 		"OpDecorate %rg_float_in Location 2\n"
915 		"OpDecorate %rgb_float_in Location 3\n"
916 		"OpDecorate %rgba_float_in Location 4\n"
917 		+decorations[ndx].fragment+
918 		"%2 = OpTypeVoid\n"
919 		"%3 = OpTypeFunction %2\n"
920 		"%6 = OpTypeFloat 32\n"
921 		"%7 = OpTypeVector %6 4\n"
922 		"%8 = OpTypePointer Output %7\n"
923 		"%color_out = OpVariable %8 Output\n"
924 		"%10 = OpTypePointer Input %7\n"
925 		"%color_in = OpVariable %10 Input\n"
926 		"%13 = OpTypePointer Input %6\n"
927 		"%r_float_in = OpVariable %13 Input\n"
928 		"%16 = OpTypeInt 32 0\n"
929 		"%17 = OpConstant %16 0\n"
930 		"%20 = OpTypeBool\n"
931 		"%ep = OpConstant %6 " + epsilon + "\n"
932 		"%24 = OpConstant %6 1\n"
933 		"%25 = OpTypePointer Output %6\n"
934 		"%27 = OpTypeVector %6 2\n"
935 		"%28 = OpTypePointer Input %27\n"
936 		"%rg_float_in = OpVariable %28 Input\n"
937 		"%ep2 = OpConstantComposite %27 %ep %ep\n"
938 		"%33 = OpTypeVector %20 2\n"
939 		"%38 = OpConstantComposite %27 %24 %24\n"
940 		"%41 = OpTypeVector %6 3\n"
941 		"%42 = OpTypePointer Input %41\n"
942 		"%rgb_float_in = OpVariable %42 Input\n"
943 		"%ep3 = OpConstantComposite %41 %ep %ep %ep\n"
944 		"%47 = OpTypeVector %20 3\n"
945 		"%52 = OpConstantComposite %41 %24 %24 %24\n"
946 		"%rgba_float_in = OpVariable %10 Input\n"
947 		"%ep4 = OpConstantComposite %7 %ep %ep %ep %ep\n"
948 		"%58 = OpTypeVector %20 4\n"
949 		"%63 = OpConstantComposite %7 %24 %24 %24 %24\n"
950 		"%4 = OpFunction %2 None %3\n"
951 		"%5 = OpLabel\n"
952 		"%12 = OpLoad %7 %color_in\n"
953 		"OpStore %color_out %12\n"
954 		"%15 = OpLoad %6 %r_float_in\n"
955 		"%18 = OpAccessChain %13 %color_in %17\n"
956 		"%19 = OpLoad %6 %18\n"
957 		"%sub = OpFSub %6 %15 %19\n"
958 		"%abs = OpExtInst %6 %1 FAbs %sub\n"
959 		"%ep1abs0 = OpExtInst %6 %1 FAbs %15\n"
960 		"%ep1abs1 = OpExtInst %6 %1 FAbs %19\n"
961 		"%ep1gt = OpFOrdGreaterThan %20 %ep1abs0 %ep1abs1\n"
962 		"%ep1max = OpSelect %6 %ep1gt %ep1abs0 %ep1abs1\n"
963 		"%ep1rel = OpFMul %6 %ep1max %ep\n"
964 		"%cmp = OpFOrdGreaterThan %20 %abs %ep1rel\n"
965 		"OpSelectionMerge %23 None\n"
966 		"OpBranchConditional %cmp %22 %23\n"
967 		"%22 = OpLabel\n"
968 		"%26 = OpAccessChain %25 %color_out %17\n"
969 		"OpStore %26 %24\n"
970 		"OpBranch %23\n"
971 		"%23 = OpLabel\n"
972 		"%30 = OpLoad %27 %rg_float_in\n"
973 		"%31 = OpLoad %7 %color_in\n"
974 		"%32 = OpVectorShuffle %27 %31 %31 0 1\n"
975 		"%sub2 = OpFSub %27 %30 %32\n"
976 		"%abs2 = OpExtInst %27 %1 FAbs %sub2\n"
977 		"%ep2abs0 = OpExtInst %27 %1 FAbs %30\n"
978 		"%ep2abs1 = OpExtInst %27 %1 FAbs %32\n"
979 		"%ep2gt = OpFOrdGreaterThan %33 %ep2abs0 %ep2abs1\n"
980 		"%ep2max = OpSelect %27 %ep2gt %ep2abs0 %ep2abs1\n"
981 		"%ep2rel = OpFMul %27 %ep2max %ep2\n"
982 		"%cmp2 = OpFOrdGreaterThan %33 %abs2 %ep2rel\n"
983 		"%35 = OpAny %20 %cmp2\n"
984 		"OpSelectionMerge %37 None\n"
985 		"OpBranchConditional %35 %36 %37\n"
986 		"%36 = OpLabel\n"
987 		"%39 = OpLoad %7 %color_out\n"
988 		"%40 = OpVectorShuffle %7 %39 %38 4 5 2 3\n"
989 		"OpStore %color_out %40\n"
990 		"OpBranch %37\n"
991 		"%37 = OpLabel\n"
992 		"%44 = OpLoad %41 %rgb_float_in\n"
993 		"%45 = OpLoad %7 %color_in\n"
994 		"%46 = OpVectorShuffle %41 %45 %45 0 1 2\n"
995 		"%sub3 = OpFSub %41 %44 %46\n"
996 		"%abs3 = OpExtInst %41 %1 FAbs %sub3\n"
997 		"%ep3abs0 = OpExtInst %41 %1 FAbs %44\n"
998 		"%ep3abs1 = OpExtInst %41 %1 FAbs %46\n"
999 		"%ep3gt = OpFOrdGreaterThan %47 %ep3abs0 %ep3abs1\n"
1000 		"%ep3max = OpSelect %41 %ep3gt %ep3abs0 %ep3abs1\n"
1001 		"%ep3rel = OpFMul %41 %ep3max %ep3\n"
1002 		"%cmp3 = OpFOrdGreaterThan %47 %abs3 %ep3rel\n"
1003 		"%49 = OpAny %20 %cmp3\n"
1004 		"OpSelectionMerge %51 None\n"
1005 		"OpBranchConditional %49 %50 %51\n"
1006 		"%50 = OpLabel\n"
1007 		"%53 = OpLoad %7 %color_out\n"
1008 		"%54 = OpVectorShuffle %7 %53 %52 4 5 6 3\n"
1009 		"OpStore %color_out %54\n"
1010 		"OpBranch %51\n"
1011 		"%51 = OpLabel\n"
1012 		"%56 = OpLoad %7 %rgba_float_in\n"
1013 		"%57 = OpLoad %7 %color_in\n"
1014 		"%sub4 = OpFSub %7 %56 %57\n"
1015 		"%abs4 = OpExtInst %7 %1 FAbs %sub4\n"
1016 		"%ep4abs0 = OpExtInst %7 %1 FAbs %56\n"
1017 		"%ep4abs1 = OpExtInst %7 %1 FAbs %57\n"
1018 		"%ep4gt = OpFOrdGreaterThan %58 %ep4abs0 %ep4abs1\n"
1019 		"%ep4max = OpSelect %7 %ep4gt %ep4abs0 %ep4abs1\n"
1020 		"%ep4rel = OpFMul %7 %ep4max %ep4\n"
1021 		"%cmp4 = OpFOrdGreaterThan %58 %abs4 %ep4rel\n"
1022 		"%60 = OpAny %20 %cmp4\n"
1023 		"OpSelectionMerge %62 None\n"
1024 		"OpBranchConditional %60 %61 %62\n"
1025 		"%61 = OpLabel\n"
1026 		"OpStore %color_out %63\n"
1027 		"OpBranch %62\n"
1028 		"%62 = OpLabel\n"
1029 		"OpReturn\n"
1030 		"OpFunctionEnd\n";
1031 
1032 		std::ostringstream vertex;
1033 		vertex << "vertex" << ndx;
1034 		std::ostringstream fragment;
1035 		fragment << "fragment" << ndx;
1036 
1037 		programCollection.spirvAsmSources.add(vertex.str()) << vertexShaderSource;
1038 		programCollection.spirvAsmSources.add(fragment.str()) << fragmentShaderSource;
1039 	}
1040 	{
1041 		/*#version 450
1042 		#extension GL_EXT_tessellation_shader : require
1043 		layout(vertices = 4) out;
1044 		layout(location = 0) in vec4		in_color[];
1045 		layout(location = 1) in float		r_float_in[];
1046 		layout(location = 2) in vec2		rg_float_in[];
1047 		layout(location = 3) in vec3		rgb_float_in[];
1048 		layout(location = 4) in vec4		rgba_float_in[];
1049 		layout(location = 0) out vec4		out_color[];
1050 		layout(location = 1) out float		r_float_out[];
1051 		layout(location = 2) out vec2		rg_float_out[];
1052 		layout(location = 3) out vec3		rgb_float_out[];
1053 		layout(location = 4) out vec4		rgba_float_out[];
1054 		void main (void)
1055 		{
1056 			if ( gl_InvocationID == 0 )
1057 			{
1058 				gl_TessLevelInner[0] = 4.0f;
1059 				gl_TessLevelInner[1] = 4.0f;
1060 				gl_TessLevelOuter[0] = 4.0f;
1061 				gl_TessLevelOuter[1] = 4.0f;
1062 				gl_TessLevelOuter[2] = 4.0f;
1063 				gl_TessLevelOuter[3] = 4.0f;
1064 			}
1065 			out_color[gl_InvocationID] = in_color[gl_InvocationID];
1066 			r_float_out[gl_InvocationID] = r_float_in[gl_InvocationID];
1067 			rg_float_out[gl_InvocationID] = rg_float_in[gl_InvocationID];
1068 			rgb_float_out[gl_InvocationID] = rgb_float_in[gl_InvocationID];
1069 			rgba_float_out[gl_InvocationID] = rgba_float_in[gl_InvocationID];
1070 			gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
1071 		}*/
1072 
1073 		const string tessellationControlSource =
1074 		"; SPIR-V\n"
1075 		"; Version: 1.3\n"
1076 		"; Generator: Khronos Glslang Reference Front End; 2\n"
1077 		"; Bound: 111\n"
1078 		"; Schema: 0\n"
1079 		"OpCapability Tessellation\n"
1080 		"%1 = OpExtInstImport \"GLSL.std.450\"\n"
1081 		"OpMemoryModel Logical GLSL450\n"
1082 		"OpEntryPoint TessellationControl %4 \"main\" %8 %20 %29 %color_out %color_in %r_float_out %r_float_in %rg_float_out %rg_float_in %rgb_float_out %rgb_float_in %rgba_float_out %rgba_float_in %101 %106\n"
1083 		"OpExecutionMode %4 OutputVertices 4\n"
1084 		"OpDecorate %8 BuiltIn InvocationId\n"
1085 		"OpDecorate %20 Patch\n"
1086 		"OpDecorate %20 BuiltIn TessLevelInner\n"
1087 		"OpDecorate %29 Patch\n"
1088 		"OpDecorate %29 BuiltIn TessLevelOuter\n"
1089 		"OpDecorate %color_out Location 0\n"
1090 		"OpDecorate %color_in Location 0\n"
1091 		"OpDecorate %r_float_out Location 1\n"
1092 		"OpDecorate %r_float_in Location 1\n"
1093 		"OpDecorate %rg_float_out Location 2\n"
1094 		"OpDecorate %rg_float_in Location 2\n"
1095 		"OpDecorate %rgb_float_out Location 3\n"
1096 		"OpDecorate %rgb_float_in Location 3\n"
1097 		"OpDecorate %rgba_float_out Location 4\n"
1098 		"OpDecorate %rgba_float_in Location 4\n"
1099 		+decorations[0].others+
1100 		"OpMemberDecorate %98 0 BuiltIn Position\n"
1101 		"OpMemberDecorate %98 1 BuiltIn PointSize\n"
1102 		"OpMemberDecorate %98 2 BuiltIn ClipDistance\n"
1103 		"OpMemberDecorate %98 3 BuiltIn CullDistance\n"
1104 		"OpDecorate %98 Block\n"
1105 		"OpMemberDecorate %103 0 BuiltIn Position\n"
1106 		"OpMemberDecorate %103 1 BuiltIn PointSize\n"
1107 		"OpMemberDecorate %103 2 BuiltIn ClipDistance\n"
1108 		"OpMemberDecorate %103 3 BuiltIn CullDistance\n"
1109 		"OpDecorate %103 Block\n"
1110 		"%2 = OpTypeVoid\n"
1111 		"%3 = OpTypeFunction %2\n"
1112 		"%6 = OpTypeInt 32 1\n"
1113 		"%7 = OpTypePointer Input %6\n"
1114 		"%8 = OpVariable %7 Input\n"
1115 		"%10 = OpConstant %6 0\n"
1116 		"%11 = OpTypeBool\n"
1117 		"%15 = OpTypeFloat 32\n"
1118 		"%16 = OpTypeInt 32 0\n"
1119 		"%17 = OpConstant %16 2\n"
1120 		"%18 = OpTypeArray %15 %17\n"
1121 		"%19 = OpTypePointer Output %18\n"
1122 		"%20 = OpVariable %19 Output\n"
1123 		"%21 = OpConstant %15 4\n"
1124 		"%22 = OpTypePointer Output %15\n"
1125 		"%24 = OpConstant %6 1\n"
1126 		"%26 = OpConstant %16 4\n"
1127 		"%27 = OpTypeArray %15 %26\n"
1128 		"%28 = OpTypePointer Output %27\n"
1129 		"%29 = OpVariable %28 Output\n"
1130 		"%32 = OpConstant %6 2\n"
1131 		"%34 = OpConstant %6 3\n"
1132 		"%36 = OpTypeVector %15 4\n"
1133 		"%37 = OpTypeArray %36 %26\n"
1134 		"%38 = OpTypePointer Output %37\n"
1135 		"%color_out = OpVariable %38 Output\n"
1136 		"%41 = OpConstant %16 32\n"
1137 		"%42 = OpTypeArray %36 %41\n"
1138 		"%43 = OpTypePointer Input %42\n"
1139 		"%color_in = OpVariable %43 Input\n"
1140 		"%46 = OpTypePointer Input %36\n"
1141 		"%49 = OpTypePointer Output %36\n"
1142 		"%r_float_out = OpVariable %28 Output\n"
1143 		"%53 = OpTypeArray %15 %41\n"
1144 		"%54 = OpTypePointer Input %53\n"
1145 		"%r_float_in = OpVariable %54 Input\n"
1146 		"%57 = OpTypePointer Input %15\n"
1147 		"%61 = OpTypeVector %15 2\n"
1148 		"%62 = OpTypeArray %61 %26\n"
1149 		"%63 = OpTypePointer Output %62\n"
1150 		"%rg_float_out = OpVariable %63 Output\n"
1151 		"%66 = OpTypeArray %61 %41\n"
1152 		"%67 = OpTypePointer Input %66\n"
1153 		"%rg_float_in = OpVariable %67 Input\n"
1154 		"%70 = OpTypePointer Input %61\n"
1155 		"%73 = OpTypePointer Output %61\n"
1156 		"%75 = OpTypeVector %15 3\n"
1157 		"%76 = OpTypeArray %75 %26\n"
1158 		"%77 = OpTypePointer Output %76\n"
1159 		"%rgb_float_out = OpVariable %77 Output\n"
1160 		"%80 = OpTypeArray %75 %41\n"
1161 		"%81 = OpTypePointer Input %80\n"
1162 		"%rgb_float_in = OpVariable %81 Input\n"
1163 		"%84 = OpTypePointer Input %75\n"
1164 		"%87 = OpTypePointer Output %75\n"
1165 		"%rgba_float_out = OpVariable %38 Output\n"
1166 		"%rgba_float_in = OpVariable %43 Input\n"
1167 		"%96 = OpConstant %16 1\n"
1168 		"%97 = OpTypeArray %15 %96\n"
1169 		"%98 = OpTypeStruct %36 %15 %97 %97\n"
1170 		"%99 = OpTypeArray %98 %26\n"
1171 		"%100 = OpTypePointer Output %99\n"
1172 		"%101 = OpVariable %100 Output\n"
1173 		"%103 = OpTypeStruct %36 %15 %97 %97\n"
1174 		"%104 = OpTypeArray %103 %41\n"
1175 		"%105 = OpTypePointer Input %104\n"
1176 		"%106 = OpVariable %105 Input\n"
1177 		"%4 = OpFunction %2 None %3\n"
1178 		"%5 = OpLabel\n"
1179 		"%9 = OpLoad %6 %8\n"
1180 		"%12 = OpIEqual %11 %9 %10\n"
1181 		"OpSelectionMerge %14 None\n"
1182 		"OpBranchConditional %12 %13 %14\n"
1183 		"%13 = OpLabel\n"
1184 		"%23 = OpAccessChain %22 %20 %10\n"
1185 		"OpStore %23 %21\n"
1186 		"%25 = OpAccessChain %22 %20 %24\n"
1187 		"OpStore %25 %21\n"
1188 		"%30 = OpAccessChain %22 %29 %10\n"
1189 		"OpStore %30 %21\n"
1190 		"%31 = OpAccessChain %22 %29 %24\n"
1191 		"OpStore %31 %21\n"
1192 		"%33 = OpAccessChain %22 %29 %32\n"
1193 		"OpStore %33 %21\n"
1194 		"%35 = OpAccessChain %22 %29 %34\n"
1195 		"OpStore %35 %21\n"
1196 		"OpBranch %14\n"
1197 		"%14 = OpLabel\n"
1198 		"%40 = OpLoad %6 %8\n"
1199 		"%45 = OpLoad %6 %8\n"
1200 		"%47 = OpAccessChain %46 %color_in %45\n"
1201 		"%48 = OpLoad %36 %47\n"
1202 		"%50 = OpAccessChain %49 %color_out %40\n"
1203 		"OpStore %50 %48\n"
1204 		"%52 = OpLoad %6 %8\n"
1205 		"%56 = OpLoad %6 %8\n"
1206 		"%58 = OpAccessChain %57 %r_float_in %56\n"
1207 		"%59 = OpLoad %15 %58\n"
1208 		"%60 = OpAccessChain %22 %r_float_out %52\n"
1209 		"OpStore %60 %59\n"
1210 		"%65 = OpLoad %6 %8\n"
1211 		"%69 = OpLoad %6 %8\n"
1212 		"%71 = OpAccessChain %70 %rg_float_in %69\n"
1213 		"%72 = OpLoad %61 %71\n"
1214 		"%74 = OpAccessChain %73 %rg_float_out %65\n"
1215 		"OpStore %74 %72\n"
1216 		"%79 = OpLoad %6 %8\n"
1217 		"%83 = OpLoad %6 %8\n"
1218 		"%85 = OpAccessChain %84 %rgb_float_in %83\n"
1219 		"%86 = OpLoad %75 %85\n"
1220 		"%88 = OpAccessChain %87 %rgb_float_out %79\n"
1221 		"OpStore %88 %86\n"
1222 		"%90 = OpLoad %6 %8\n"
1223 		"%92 = OpLoad %6 %8\n"
1224 		"%93 = OpAccessChain %46 %rgba_float_in %92\n"
1225 		"%94 = OpLoad %36 %93\n"
1226 		"%95 = OpAccessChain %49 %rgba_float_out %90\n"
1227 		"OpStore %95 %94\n"
1228 		"%102 = OpLoad %6 %8\n"
1229 		"%107 = OpLoad %6 %8\n"
1230 		"%108 = OpAccessChain %46 %106 %107 %10\n"
1231 		"%109 = OpLoad %36 %108\n"
1232 		"%110 = OpAccessChain %49 %101 %102 %10\n"
1233 		"OpStore %110 %109\n"
1234 		"OpReturn\n"
1235 		"OpFunctionEnd\n";
1236 
1237 		/*#version 450
1238 		#extension GL_EXT_tessellation_shader : require
1239 		layout( quads, equal_spacing, ccw ) in;
1240 		layout(location = 0) in vec4		in_color[];
1241 		layout(location = 1) in float		r_float_in[];
1242 		layout(location = 2) in vec2		rg_float_in[];
1243 		layout(location = 3) in vec3		rgb_float_in[];
1244 		layout(location = 4) in vec4		rgba_float_in[];
1245 		layout(location = 0) out vec4		out_color;
1246 		layout(location = 1) out float		r_float_out;
1247 		layout(location = 2) out vec2		rg_float_out;
1248 		layout(location = 3) out vec3		rgb_float_out;
1249 		layout(location = 4) out vec4		rgba_float_out;
1250 		void main (void)
1251 		{
1252 			const float u = gl_TessCoord.x;
1253 			const float v = gl_TessCoord.y;
1254 			const float w = gl_TessCoord.z;
1255 			out_color = (1 - u) * (1 - v) * in_color[0] +(1 - u) * v * in_color[1] + u * (1 - v) * in_color[2] + u * v * in_color[3];
1256 			r_float_out = (1 - u) * (1 - v) * r_float_in[0] +(1 - u) * v * r_float_in[1] + u * (1 - v) * r_float_in[2] + u * v * r_float_in[3];
1257 			rg_float_out = (1 - u) * (1 - v) * rg_float_in[0] +(1 - u) * v * rg_float_in[1] + u * (1 - v) * rg_float_in[2] + u * v * rg_float_in[3];
1258 			rgb_float_out = (1 - u) * (1 - v) * rgb_float_in[0] +(1 - u) * v * rgb_float_in[1] + u * (1 - v) * rgb_float_in[2] + u * v * rgb_float_in[3];
1259 			rgba_float_out = (1 - u) * (1 - v) * rgba_float_in[0] +(1 - u) * v * rgba_float_in[1] + u * (1 - v) * rgba_float_in[2] + u * v * rgba_float_in[3];
1260 			gl_Position = (1 - u) * (1 - v) * gl_in[0].gl_Position +(1 - u) * v * gl_in[1].gl_Position + u * (1 - v) * gl_in[2].gl_Position + u * v * gl_in[3].gl_Position;
1261 		}*/
1262 
1263 		const string tessellationEvaluationSource =
1264 		"; SPIR-V\n"
1265 		"; Version: 1.3\n"
1266 		"; Generator: Khronos Glslang Reference Front End; 2\n"
1267 		"; Bound: 253\n"
1268 		"; Schema: 0\n"
1269 		"OpCapability Tessellation\n"
1270 		"%1 = OpExtInstImport \"GLSL.std.450\"\n"
1271 		"OpMemoryModel Logical GLSL450\n"
1272 		"OpEntryPoint TessellationEvaluation %4 \"main\" %11 %color_out %color_in %r_float_out %r_float_in %rg_float_out %rg_float_in %rgb_float_out %rgb_float_in %rgba_float_out %rgba_float_in %216 %225\n"
1273 		"OpExecutionMode %4 Quads\n"
1274 		"OpExecutionMode %4 SpacingEqual\n"
1275 		"OpExecutionMode %4 VertexOrderCcw\n"
1276 		"OpDecorate %11 BuiltIn TessCoord\n"
1277 		"OpDecorate %color_out Location 0\n"
1278 		"OpDecorate %color_in Location 0\n"
1279 		"OpDecorate %r_float_out Location 1\n"
1280 		"OpDecorate %r_float_in Location 1\n"
1281 		"OpDecorate %rg_float_out Location 2\n"
1282 		"OpDecorate %rg_float_in Location 2\n"
1283 		"OpDecorate %rgb_float_out Location 3\n"
1284 		"OpDecorate %rgb_float_in Location 3\n"
1285 		"OpDecorate %rgba_float_out Location 4\n"
1286 		"OpDecorate %rgba_float_in Location 4\n"
1287 		+decorations[0].others+
1288 		"OpMemberDecorate %214 0 BuiltIn Position\n"
1289 		"OpMemberDecorate %214 1 BuiltIn PointSize\n"
1290 		"OpMemberDecorate %214 2 BuiltIn ClipDistance\n"
1291 		"OpMemberDecorate %214 3 BuiltIn CullDistance\n"
1292 		"OpDecorate %214 Block\n"
1293 		"OpMemberDecorate %222 0 BuiltIn Position\n"
1294 		"OpMemberDecorate %222 1 BuiltIn PointSize\n"
1295 		"OpMemberDecorate %222 2 BuiltIn ClipDistance\n"
1296 		"OpMemberDecorate %222 3 BuiltIn CullDistance\n"
1297 		"OpDecorate %222 Block\n"
1298 		"%2 = OpTypeVoid\n"
1299 		"%3 = OpTypeFunction %2\n"
1300 		"%6 = OpTypeFloat 32\n"
1301 		"%7 = OpTypePointer Function %6\n"
1302 		"%9 = OpTypeVector %6 3\n"
1303 		"%10 = OpTypePointer Input %9\n"
1304 		"%11 = OpVariable %10 Input\n"
1305 		"%12 = OpTypeInt 32 0\n"
1306 		"%13 = OpConstant %12 0\n"
1307 		"%14 = OpTypePointer Input %6\n"
1308 		"%18 = OpConstant %12 1\n"
1309 		"%22 = OpConstant %12 2\n"
1310 		"%25 = OpTypeVector %6 4\n"
1311 		"%26 = OpTypePointer Output %25\n"
1312 		"%color_out = OpVariable %26 Output\n"
1313 		"%28 = OpConstant %6 1\n"
1314 		"%34 = OpConstant %12 32\n"
1315 		"%35 = OpTypeArray %25 %34\n"
1316 		"%36 = OpTypePointer Input %35\n"
1317 		"%color_in = OpVariable %36 Input\n"
1318 		"%38 = OpTypeInt 32 1\n"
1319 		"%39 = OpConstant %38 0\n"
1320 		"%40 = OpTypePointer Input %25\n"
1321 		"%48 = OpConstant %38 1\n"
1322 		"%57 = OpConstant %38 2\n"
1323 		"%65 = OpConstant %38 3\n"
1324 		"%70 = OpTypePointer Output %6\n"
1325 		"%r_float_out = OpVariable %70 Output\n"
1326 		"%77 = OpTypeArray %6 %34\n"
1327 		"%78 = OpTypePointer Input %77\n"
1328 		"%r_float_in = OpVariable %78 Input\n"
1329 		"%106 = OpTypeVector %6 2\n"
1330 		"%107 = OpTypePointer Output %106\n"
1331 		"%rg_float_out = OpVariable %107 Output\n"
1332 		"%114 = OpTypeArray %106 %34\n"
1333 		"%115 = OpTypePointer Input %114\n"
1334 		"%rg_float_in = OpVariable %115 Input\n"
1335 		"%117 = OpTypePointer Input %106\n"
1336 		"%144 = OpTypePointer Output %9\n"
1337 		"%rgb_float_out = OpVariable %144 Output\n"
1338 		"%151 = OpTypeArray %9 %34\n"
1339 		"%152 = OpTypePointer Input %151\n"
1340 		"%rgb_float_in = OpVariable %152 Input\n"
1341 		"%rgba_float_out = OpVariable %26 Output\n"
1342 		"%rgba_float_in = OpVariable %36 Input\n"
1343 		"%213 = OpTypeArray %6 %18\n"
1344 		"%214 = OpTypeStruct %25 %6 %213 %213\n"
1345 		"%215 = OpTypePointer Output %214\n"
1346 		"%216 = OpVariable %215 Output\n"
1347 		"%222 = OpTypeStruct %25 %6 %213 %213\n"
1348 		"%223 = OpTypeArray %222 %34\n"
1349 		"%224 = OpTypePointer Input %223\n"
1350 		"%225 = OpVariable %224 Input\n"
1351 		"%4 = OpFunction %2 None %3\n"
1352 		"%5 = OpLabel\n"
1353 		"%8 = OpVariable %7 Function\n"
1354 		"%17 = OpVariable %7 Function\n"
1355 		"%21 = OpVariable %7 Function\n"
1356 		"%15 = OpAccessChain %14 %11 %13\n"
1357 		"%16 = OpLoad %6 %15\n"
1358 		"OpStore %8 %16\n"
1359 		"%19 = OpAccessChain %14 %11 %18\n"
1360 		"%20 = OpLoad %6 %19\n"
1361 		"OpStore %17 %20\n"
1362 		"%23 = OpAccessChain %14 %11 %22\n"
1363 		"%24 = OpLoad %6 %23\n"
1364 		"OpStore %21 %24\n"
1365 		"%29 = OpLoad %6 %8\n"
1366 		"%30 = OpFSub %6 %28 %29\n"
1367 		"%31 = OpLoad %6 %17\n"
1368 		"%32 = OpFSub %6 %28 %31\n"
1369 		"%33 = OpFMul %6 %30 %32\n"
1370 		"%41 = OpAccessChain %40 %color_in %39\n"
1371 		"%42 = OpLoad %25 %41\n"
1372 		"%43 = OpVectorTimesScalar %25 %42 %33\n"
1373 		"%44 = OpLoad %6 %8\n"
1374 		"%45 = OpFSub %6 %28 %44\n"
1375 		"%46 = OpLoad %6 %17\n"
1376 		"%47 = OpFMul %6 %45 %46\n"
1377 		"%49 = OpAccessChain %40 %color_in %48\n"
1378 		"%50 = OpLoad %25 %49\n"
1379 		"%51 = OpVectorTimesScalar %25 %50 %47\n"
1380 		"%52 = OpFAdd %25 %43 %51\n"
1381 		"%53 = OpLoad %6 %8\n"
1382 		"%54 = OpLoad %6 %17\n"
1383 		"%55 = OpFSub %6 %28 %54\n"
1384 		"%56 = OpFMul %6 %53 %55\n"
1385 		"%58 = OpAccessChain %40 %color_in %57\n"
1386 		"%59 = OpLoad %25 %58\n"
1387 		"%60 = OpVectorTimesScalar %25 %59 %56\n"
1388 		"%61 = OpFAdd %25 %52 %60\n"
1389 		"%62 = OpLoad %6 %8\n"
1390 		"%63 = OpLoad %6 %17\n"
1391 		"%64 = OpFMul %6 %62 %63\n"
1392 		"%66 = OpAccessChain %40 %color_in %65\n"
1393 		"%67 = OpLoad %25 %66\n"
1394 		"%68 = OpVectorTimesScalar %25 %67 %64\n"
1395 		"%69 = OpFAdd %25 %61 %68\n"
1396 		"OpStore %color_out %69\n"
1397 		"%72 = OpLoad %6 %8\n"
1398 		"%73 = OpFSub %6 %28 %72\n"
1399 		"%74 = OpLoad %6 %17\n"
1400 		"%75 = OpFSub %6 %28 %74\n"
1401 		"%76 = OpFMul %6 %73 %75\n"
1402 		"%80 = OpAccessChain %14 %r_float_in %39\n"
1403 		"%81 = OpLoad %6 %80\n"
1404 		"%82 = OpFMul %6 %76 %81\n"
1405 		"%83 = OpLoad %6 %8\n"
1406 		"%84 = OpFSub %6 %28 %83\n"
1407 		"%85 = OpLoad %6 %17\n"
1408 		"%86 = OpFMul %6 %84 %85\n"
1409 		"%87 = OpAccessChain %14 %r_float_in %48\n"
1410 		"%88 = OpLoad %6 %87\n"
1411 		"%89 = OpFMul %6 %86 %88\n"
1412 		"%90 = OpFAdd %6 %82 %89\n"
1413 		"%91 = OpLoad %6 %8\n"
1414 		"%92 = OpLoad %6 %17\n"
1415 		"%93 = OpFSub %6 %28 %92\n"
1416 		"%94 = OpFMul %6 %91 %93\n"
1417 		"%95 = OpAccessChain %14 %r_float_in %57\n"
1418 		"%96 = OpLoad %6 %95\n"
1419 		"%97 = OpFMul %6 %94 %96\n"
1420 		"%98 = OpFAdd %6 %90 %97\n"
1421 		"%99 = OpLoad %6 %8\n"
1422 		"%100 = OpLoad %6 %17\n"
1423 		"%101 = OpFMul %6 %99 %100\n"
1424 		"%102 = OpAccessChain %14 %r_float_in %65\n"
1425 		"%103 = OpLoad %6 %102\n"
1426 		"%104 = OpFMul %6 %101 %103\n"
1427 		"%105 = OpFAdd %6 %98 %104\n"
1428 		"OpStore %r_float_out %105\n"
1429 		"%109 = OpLoad %6 %8\n"
1430 		"%110 = OpFSub %6 %28 %109\n"
1431 		"%111 = OpLoad %6 %17\n"
1432 		"%112 = OpFSub %6 %28 %111\n"
1433 		"%113 = OpFMul %6 %110 %112\n"
1434 		"%118 = OpAccessChain %117 %rg_float_in %39\n"
1435 		"%119 = OpLoad %106 %118\n"
1436 		"%120 = OpVectorTimesScalar %106 %119 %113\n"
1437 		"%121 = OpLoad %6 %8\n"
1438 		"%122 = OpFSub %6 %28 %121\n"
1439 		"%123 = OpLoad %6 %17\n"
1440 		"%124 = OpFMul %6 %122 %123\n"
1441 		"%125 = OpAccessChain %117 %rg_float_in %48\n"
1442 		"%126 = OpLoad %106 %125\n"
1443 		"%127 = OpVectorTimesScalar %106 %126 %124\n"
1444 		"%128 = OpFAdd %106 %120 %127\n"
1445 		"%129 = OpLoad %6 %8\n"
1446 		"%130 = OpLoad %6 %17\n"
1447 		"%131 = OpFSub %6 %28 %130\n"
1448 		"%132 = OpFMul %6 %129 %131\n"
1449 		"%133 = OpAccessChain %117 %rg_float_in %57\n"
1450 		"%134 = OpLoad %106 %133\n"
1451 		"%135 = OpVectorTimesScalar %106 %134 %132\n"
1452 		"%136 = OpFAdd %106 %128 %135\n"
1453 		"%137 = OpLoad %6 %8\n"
1454 		"%138 = OpLoad %6 %17\n"
1455 		"%139 = OpFMul %6 %137 %138\n"
1456 		"%140 = OpAccessChain %117 %rg_float_in %65\n"
1457 		"%141 = OpLoad %106 %140\n"
1458 		"%142 = OpVectorTimesScalar %106 %141 %139\n"
1459 		"%143 = OpFAdd %106 %136 %142\n"
1460 		"OpStore %rg_float_out %143\n"
1461 		"%146 = OpLoad %6 %8\n"
1462 		"%147 = OpFSub %6 %28 %146\n"
1463 		"%148 = OpLoad %6 %17\n"
1464 		"%149 = OpFSub %6 %28 %148\n"
1465 		"%150 = OpFMul %6 %147 %149\n"
1466 		"%154 = OpAccessChain %10 %rgb_float_in %39\n"
1467 		"%155 = OpLoad %9 %154\n"
1468 		"%156 = OpVectorTimesScalar %9 %155 %150\n"
1469 		"%157 = OpLoad %6 %8\n"
1470 		"%158 = OpFSub %6 %28 %157\n"
1471 		"%159 = OpLoad %6 %17\n"
1472 		"%160 = OpFMul %6 %158 %159\n"
1473 		"%161 = OpAccessChain %10 %rgb_float_in %48\n"
1474 		"%162 = OpLoad %9 %161\n"
1475 		"%163 = OpVectorTimesScalar %9 %162 %160\n"
1476 		"%164 = OpFAdd %9 %156 %163\n"
1477 		"%165 = OpLoad %6 %8\n"
1478 		"%166 = OpLoad %6 %17\n"
1479 		"%167 = OpFSub %6 %28 %166\n"
1480 		"%168 = OpFMul %6 %165 %167\n"
1481 		"%169 = OpAccessChain %10 %rgb_float_in %57\n"
1482 		"%170 = OpLoad %9 %169\n"
1483 		"%171 = OpVectorTimesScalar %9 %170 %168\n"
1484 		"%172 = OpFAdd %9 %164 %171\n"
1485 		"%173 = OpLoad %6 %8\n"
1486 		"%174 = OpLoad %6 %17\n"
1487 		"%175 = OpFMul %6 %173 %174\n"
1488 		"%176 = OpAccessChain %10 %rgb_float_in %65\n"
1489 		"%177 = OpLoad %9 %176\n"
1490 		"%178 = OpVectorTimesScalar %9 %177 %175\n"
1491 		"%179 = OpFAdd %9 %172 %178\n"
1492 		"OpStore %rgb_float_out %179\n"
1493 		"%181 = OpLoad %6 %8\n"
1494 		"%182 = OpFSub %6 %28 %181\n"
1495 		"%183 = OpLoad %6 %17\n"
1496 		"%184 = OpFSub %6 %28 %183\n"
1497 		"%185 = OpFMul %6 %182 %184\n"
1498 		"%187 = OpAccessChain %40 %rgba_float_in %39\n"
1499 		"%188 = OpLoad %25 %187\n"
1500 		"%189 = OpVectorTimesScalar %25 %188 %185\n"
1501 		"%190 = OpLoad %6 %8\n"
1502 		"%191 = OpFSub %6 %28 %190\n"
1503 		"%192 = OpLoad %6 %17\n"
1504 		"%193 = OpFMul %6 %191 %192\n"
1505 		"%194 = OpAccessChain %40 %rgba_float_in %48\n"
1506 		"%195 = OpLoad %25 %194\n"
1507 		"%196 = OpVectorTimesScalar %25 %195 %193\n"
1508 		"%197 = OpFAdd %25 %189 %196\n"
1509 		"%198 = OpLoad %6 %8\n"
1510 		"%199 = OpLoad %6 %17\n"
1511 		"%200 = OpFSub %6 %28 %199\n"
1512 		"%201 = OpFMul %6 %198 %200\n"
1513 		"%202 = OpAccessChain %40 %rgba_float_in %57\n"
1514 		"%203 = OpLoad %25 %202\n"
1515 		"%204 = OpVectorTimesScalar %25 %203 %201\n"
1516 		"%205 = OpFAdd %25 %197 %204\n"
1517 		"%206 = OpLoad %6 %8\n"
1518 		"%207 = OpLoad %6 %17\n"
1519 		"%208 = OpFMul %6 %206 %207\n"
1520 		"%209 = OpAccessChain %40 %rgba_float_in %65\n"
1521 		"%210 = OpLoad %25 %209\n"
1522 		"%211 = OpVectorTimesScalar %25 %210 %208\n"
1523 		"%212 = OpFAdd %25 %205 %211\n"
1524 		"OpStore %rgba_float_out %212\n"
1525 		"%217 = OpLoad %6 %8\n"
1526 		"%218 = OpFSub %6 %28 %217\n"
1527 		"%219 = OpLoad %6 %17\n"
1528 		"%220 = OpFSub %6 %28 %219\n"
1529 		"%221 = OpFMul %6 %218 %220\n"
1530 		"%226 = OpAccessChain %40 %225 %39 %39\n"
1531 		"%227 = OpLoad %25 %226\n"
1532 		"%228 = OpVectorTimesScalar %25 %227 %221\n"
1533 		"%229 = OpLoad %6 %8\n"
1534 		"%230 = OpFSub %6 %28 %229\n"
1535 		"%231 = OpLoad %6 %17\n"
1536 		"%232 = OpFMul %6 %230 %231\n"
1537 		"%233 = OpAccessChain %40 %225 %48 %39\n"
1538 		"%234 = OpLoad %25 %233\n"
1539 		"%235 = OpVectorTimesScalar %25 %234 %232\n"
1540 		"%236 = OpFAdd %25 %228 %235\n"
1541 		"%237 = OpLoad %6 %8\n"
1542 		"%238 = OpLoad %6 %17\n"
1543 		"%239 = OpFSub %6 %28 %238\n"
1544 		"%240 = OpFMul %6 %237 %239\n"
1545 		"%241 = OpAccessChain %40 %225 %57 %39\n"
1546 		"%242 = OpLoad %25 %241\n"
1547 		"%243 = OpVectorTimesScalar %25 %242 %240\n"
1548 		"%244 = OpFAdd %25 %236 %243\n"
1549 		"%245 = OpLoad %6 %8\n"
1550 		"%246 = OpLoad %6 %17\n"
1551 		"%247 = OpFMul %6 %245 %246\n"
1552 		"%248 = OpAccessChain %40 %225 %65 %39\n"
1553 		"%249 = OpLoad %25 %248\n"
1554 		"%250 = OpVectorTimesScalar %25 %249 %247\n"
1555 		"%251 = OpFAdd %25 %244 %250\n"
1556 		"%252 = OpAccessChain %26 %216 %39\n"
1557 		"OpStore %252 %251\n"
1558 		"OpReturn\n"
1559 		"OpFunctionEnd\n";
1560 		programCollection.spirvAsmSources.add("tessellation_control") << tessellationControlSource;
1561 		programCollection.spirvAsmSources.add("tessellation_evaluation") << tessellationEvaluationSource;
1562 	}
1563 	{
1564 
1565 		/*#version 450
1566 		layout(triangles) in;
1567 		layout(triangle_strip, max_vertices = 3) out;
1568 		layout(location = 0) in vec4    in_color[];
1569 		layout(location = 1) in float   r_float_in[];
1570 		layout(location = 2) in vec2    rg_float_in[];
1571 		layout(location = 3) in vec3    rgb_float_in[];
1572 		layout(location = 4) in vec4    rgba_float_in[];
1573 		layout(location = 0) out vec4   out_color;
1574 		layout(location = 1) out float  r_float_out;
1575 		layout(location = 2) out vec2   rg_float_out;
1576 		layout(location = 3) out vec3   rgb_float_out;
1577 		layout(location = 4) out vec4   rgba_float_out;
1578 		void main (void)
1579 		{
1580 			out_color = in_color[0];
1581 			r_float_out = r_float_in[0];
1582 			rg_float_out = rg_float_in[0];
1583 			rgb_float_out = rgb_float_in[0];
1584 			rgba_float_out = rgba_float_in[0];
1585 			gl_Position = gl_in[0].gl_Position;
1586 			EmitVertex();
1587 			out_color = in_color[1];
1588 			r_float_out = r_float_in[1];
1589 			rg_float_out = rg_float_in[1];
1590 			rgb_float_out = rgb_float_in[1];
1591 			rgba_float_out = rgba_float_in[1];
1592 			gl_Position = gl_in[1].gl_Position;
1593 			EmitVertex();
1594 			out_color = in_color[2];
1595 			r_float_out = r_float_in[2];
1596 			rg_float_out = rg_float_in[2];
1597 			rgb_float_out = rgb_float_in[2];
1598 			rgba_float_out = rgba_float_in[2];
1599 			gl_Position = gl_in[2].gl_Position;
1600 			EmitVertex();
1601 			EndPrimitive();
1602 		}
1603 		*/
1604 		const string geometrySource =
1605 		"; SPIR-V\n"
1606 		"; Version: 1.3\n"
1607 		"; Generator: Khronos Glslang Reference Front End; 2\n"
1608 		"; Bound: 90\n"
1609 		"; Schema: 0\n"
1610 		"OpCapability Geometry\n"
1611 		"%1 = OpExtInstImport \"GLSL.std.450\"\n"
1612 		"OpMemoryModel Logical GLSL450\n"
1613 		"OpEntryPoint Geometry %4 \"main\" %color_out %color_in %r_float_out %r_float_in %rg_float_out %rg_float_in %rgb_float_out %rgb_float_in %rgba_float_out %rgba_float_in %54 %58\n"
1614 		"OpExecutionMode %4 Triangles\n"
1615 		"OpExecutionMode %4 Invocations 1\n"
1616 		"OpExecutionMode %4 OutputTriangleStrip\n"
1617 		"OpExecutionMode %4 OutputVertices 3\n"
1618 		"OpDecorate %color_out Location 0\n"
1619 		"OpDecorate %color_in Location 0\n"
1620 		"OpDecorate %r_float_out Location 1\n"
1621 		"OpDecorate %r_float_in Location 1\n"
1622 		"OpDecorate %rg_float_out Location 2\n"
1623 		"OpDecorate %rg_float_in Location 2\n"
1624 		"OpDecorate %rgb_float_out Location 3\n"
1625 		"OpDecorate %rgb_float_in Location 3\n"
1626 		"OpDecorate %rgba_float_out Location 4\n"
1627 		"OpDecorate %rgba_float_in Location 4\n"
1628 		+decorations[0].others+
1629 		"OpMemberDecorate %52 0 BuiltIn Position\n"
1630 		"OpMemberDecorate %52 1 BuiltIn PointSize\n"
1631 		"OpMemberDecorate %52 2 BuiltIn ClipDistance\n"
1632 		"OpMemberDecorate %52 3 BuiltIn CullDistance\n"
1633 		"OpDecorate %52 Block\n"
1634 		"OpMemberDecorate %55 0 BuiltIn Position\n"
1635 		"OpMemberDecorate %55 1 BuiltIn PointSize\n"
1636 		"OpMemberDecorate %55 2 BuiltIn ClipDistance\n"
1637 		"OpMemberDecorate %55 3 BuiltIn CullDistance\n"
1638 		"OpDecorate %55 Block\n"
1639 		"%2 = OpTypeVoid\n"
1640 		"%3 = OpTypeFunction %2\n"
1641 		"%6 = OpTypeFloat 32\n"
1642 		"%7 = OpTypeVector %6 4\n"
1643 		"%8 = OpTypePointer Output %7\n"
1644 		"%color_out = OpVariable %8 Output\n"
1645 		"%10 = OpTypeInt 32 0\n"
1646 		"%11 = OpConstant %10 3\n"
1647 		"%12 = OpTypeArray %7 %11\n"
1648 		"%13 = OpTypePointer Input %12\n"
1649 		"%color_in = OpVariable %13 Input\n"
1650 		"%15 = OpTypeInt 32 1\n"
1651 		"%16 = OpConstant %15 0\n"
1652 		"%17 = OpTypePointer Input %7\n"
1653 		"%20 = OpTypePointer Output %6\n"
1654 		"%r_float_out = OpVariable %20 Output\n"
1655 		"%22 = OpTypeArray %6 %11\n"
1656 		"%23 = OpTypePointer Input %22\n"
1657 		"%r_float_in = OpVariable %23 Input\n"
1658 		"%25 = OpTypePointer Input %6\n"
1659 		"%28 = OpTypeVector %6 2\n"
1660 		"%29 = OpTypePointer Output %28\n"
1661 		"%rg_float_out = OpVariable %29 Output\n"
1662 		"%31 = OpTypeArray %28 %11\n"
1663 		"%32 = OpTypePointer Input %31\n"
1664 		"%rg_float_in = OpVariable %32 Input\n"
1665 		"%34 = OpTypePointer Input %28\n"
1666 		"%37 = OpTypeVector %6 3\n"
1667 		"%38 = OpTypePointer Output %37\n"
1668 		"%rgb_float_out = OpVariable %38 Output\n"
1669 		"%40 = OpTypeArray %37 %11\n"
1670 		"%41 = OpTypePointer Input %40\n"
1671 		"%rgb_float_in = OpVariable %41 Input\n"
1672 		"%43 = OpTypePointer Input %37\n"
1673 		"%rgba_float_out = OpVariable %8 Output\n"
1674 		"%rgba_float_in = OpVariable %13 Input\n"
1675 		"%50 = OpConstant %10 1\n"
1676 		"%51 = OpTypeArray %6 %50\n"
1677 		"%52 = OpTypeStruct %7 %6 %51 %51\n"
1678 		"%53 = OpTypePointer Output %52\n"
1679 		"%54 = OpVariable %53 Output\n"
1680 		"%55 = OpTypeStruct %7 %6 %51 %51\n"
1681 		"%56 = OpTypeArray %55 %11\n"
1682 		"%57 = OpTypePointer Input %56\n"
1683 		"%58 = OpVariable %57 Input\n"
1684 		"%62 = OpConstant %15 1\n"
1685 		"%76 = OpConstant %15 2\n"
1686 		"%4 = OpFunction %2 None %3\n"
1687 		"%5 = OpLabel\n"
1688 		"%18 = OpAccessChain %17 %color_in %16\n"
1689 		"%19 = OpLoad %7 %18\n"
1690 		"OpStore %color_out %19\n"
1691 		"%26 = OpAccessChain %25 %r_float_in %16\n"
1692 		"%27 = OpLoad %6 %26\n"
1693 		"OpStore %r_float_out %27\n"
1694 		"%35 = OpAccessChain %34 %rg_float_in %16\n"
1695 		"%36 = OpLoad %28 %35\n"
1696 		"OpStore %rg_float_out %36\n"
1697 		"%44 = OpAccessChain %43 %rgb_float_in %16\n"
1698 		"%45 = OpLoad %37 %44\n"
1699 		"OpStore %rgb_float_out %45\n"
1700 		"%48 = OpAccessChain %17 %rgba_float_in %16\n"
1701 		"%49 = OpLoad %7 %48\n"
1702 		"OpStore %rgba_float_out %49\n"
1703 		"%59 = OpAccessChain %17 %58 %16 %16\n"
1704 		"%60 = OpLoad %7 %59\n"
1705 		"%61 = OpAccessChain %8 %54 %16\n"
1706 		"OpStore %61 %60\n"
1707 		"OpEmitVertex\n"
1708 		"%63 = OpAccessChain %17 %color_in %62\n"
1709 		"%64 = OpLoad %7 %63\n"
1710 		"OpStore %color_out %64\n"
1711 		"%65 = OpAccessChain %25 %r_float_in %62\n"
1712 		"%66 = OpLoad %6 %65\n"
1713 		"OpStore %r_float_out %66\n"
1714 		"%67 = OpAccessChain %34 %rg_float_in %62\n"
1715 		"%68 = OpLoad %28 %67\n"
1716 		"OpStore %rg_float_out %68\n"
1717 		"%69 = OpAccessChain %43 %rgb_float_in %62\n"
1718 		"%70 = OpLoad %37 %69\n"
1719 		"OpStore %rgb_float_out %70\n"
1720 		"%71 = OpAccessChain %17 %rgba_float_in %62\n"
1721 		"%72 = OpLoad %7 %71\n"
1722 		"OpStore %rgba_float_out %72\n"
1723 		"%73 = OpAccessChain %17 %58 %62 %16\n"
1724 		"%74 = OpLoad %7 %73\n"
1725 		"%75 = OpAccessChain %8 %54 %16\n"
1726 		"OpStore %75 %74\n"
1727 		"OpEmitVertex\n"
1728 		"%77 = OpAccessChain %17 %color_in %76\n"
1729 		"%78 = OpLoad %7 %77\n"
1730 		"OpStore %color_out %78\n"
1731 		"%79 = OpAccessChain %25 %r_float_in %76\n"
1732 		"%80 = OpLoad %6 %79\n"
1733 		"OpStore %r_float_out %80\n"
1734 		"%81 = OpAccessChain %34 %rg_float_in %76\n"
1735 		"%82 = OpLoad %28 %81\n"
1736 		"OpStore %rg_float_out %82\n"
1737 		"%83 = OpAccessChain %43 %rgb_float_in %76\n"
1738 		"%84 = OpLoad %37 %83\n"
1739 		"OpStore %rgb_float_out %84\n"
1740 		"%85 = OpAccessChain %17 %rgba_float_in %76\n"
1741 		"%86 = OpLoad %7 %85\n"
1742 		"OpStore %rgba_float_out %86\n"
1743 		"%87 = OpAccessChain %17 %58 %76 %16\n"
1744 		"%88 = OpLoad %7 %87\n"
1745 		"%89 = OpAccessChain %8 %54 %16\n"
1746 		"OpStore %89 %88\n"
1747 		"OpEmitVertex\n"
1748 		"OpEndPrimitive\n"
1749 		"OpReturn\n"
1750 		"OpFunctionEnd\n";
1751 		programCollection.spirvAsmSources.add("geometry") << geometrySource;
1752 	}
1753 }
1754 
1755 class CrossStageInterfaceTestsCase : public vkt::TestCase
1756 {
1757 public:
CrossStageInterfaceTestsCase(tcu::TestContext & context,const char * name,const char * description,const TestParameters & parameters)1758 	CrossStageInterfaceTestsCase (tcu::TestContext &context, const char *name, const char *description, const TestParameters& parameters)
1759 		: TestCase			(context, name, description)
1760 		, m_parameters		(parameters)
1761 	{
1762 	}
1763 private:
1764 	vkt::TestInstance*	createInstance		(vkt::Context& context) const;
1765 	void				initPrograms		(SourceCollections& programCollection) const;
1766 
1767 	const TestParameters	m_parameters;
1768 
1769 };
1770 
createInstance(vkt::Context & context) const1771 vkt::TestInstance* CrossStageInterfaceTestsCase::createInstance (vkt::Context& context) const
1772 {
1773 	return new CrossStageTestInstance(context, m_parameters);
1774 }
1775 
initPrograms(SourceCollections & programCollection) const1776 void CrossStageInterfaceTestsCase::initPrograms (SourceCollections& programCollection) const
1777 {
1778 	vector<Decorations> decorations;
1779 	string epsilon = "3e-7";
1780 	switch(m_parameters.qualifier)
1781 	{
1782 	case TEST_TYPE_FLAT:
1783 		decorations.push_back(Decorations("",
1784 								//Vertex
1785 								"OpDecorate %color_out Flat\n"
1786 								"OpMemberDecorate %block_out 0 Flat\n"
1787 								"OpMemberDecorate %block_out 1 Flat\n",
1788 								""));
1789 		decorations.push_back(Decorations(//Fragment
1790 								"OpDecorate %color_in Flat\n"
1791 								"OpMemberDecorate %block_in 0 Flat\n"
1792 								"OpMemberDecorate %block_in 1 Flat\n",
1793 								"",
1794 								""));
1795 
1796 		decorations.push_back(Decorations(//Fragment
1797 								"OpDecorate %color_in Flat\n"
1798 								"OpMemberDecorate %block_in 0 Flat\n"
1799 								"OpMemberDecorate %block_in 1 Flat\n",
1800 								//Vertex
1801 								"OpDecorate %color_out Flat\n"
1802 								"OpMemberDecorate %block_out 0 Flat\n"
1803 								"OpMemberDecorate %block_out 1 Flat\n",
1804 								""));
1805 		epsilon = "0.0";
1806 		break;
1807 	case TEST_TYPE_NOPERSPECTIVE:
1808 		decorations.push_back(Decorations("",
1809 								//Vertex
1810 								"OpDecorate %color_out NoPerspective\n"
1811 								"OpMemberDecorate %block_out 0 NoPerspective\n"
1812 								"OpMemberDecorate %block_out 1 NoPerspective\n",
1813 								""));
1814 
1815 		decorations.push_back(Decorations(//Fragment
1816 								"OpDecorate %color_in NoPerspective\n"
1817 								"OpMemberDecorate %block_in 0 NoPerspective\n"
1818 								"OpMemberDecorate %block_in 1 NoPerspective\n",
1819 								"",
1820 								""));
1821 
1822 		decorations.push_back(Decorations(//Fragment
1823 								"OpDecorate %color_in NoPerspective\n"
1824 								"OpMemberDecorate %block_in 0 NoPerspective\n"
1825 								"OpMemberDecorate %block_in 1 NoPerspective\n",
1826 								//Vertex
1827 								"OpDecorate %color_out NoPerspective\n"
1828 								"OpMemberDecorate %block_out 0 NoPerspective\n"
1829 								"OpMemberDecorate %block_out 1 NoPerspective\n",
1830 								""));
1831 		break;
1832 	case TEST_TYPE_RELAXEDPRECISION:
1833 		decorations.push_back(Decorations(//Fragment
1834 								"OpDecorate %color_in RelaxedPrecision\n"
1835 								"OpDecorate %color_out RelaxedPrecision\n"
1836 								"OpMemberDecorate %block_in 0 RelaxedPrecision\n"
1837 								"OpMemberDecorate %block_in 1 RelaxedPrecision\n",
1838 								//Vertex
1839 								"OpDecorate %color_out RelaxedPrecision\n"
1840 								"OpDecorate %color_in RelaxedPrecision\n"
1841 								"OpMemberDecorate %block_out 0 RelaxedPrecision\n"
1842 								"OpMemberDecorate %block_out 1 RelaxedPrecision\n",
1843 								//Others
1844 								"OpDecorate %color_out RelaxedPrecision\n"
1845 								"OpDecorate %color_in RelaxedPrecision\n"
1846 								"OpMemberDecorate %block_out 0 RelaxedPrecision\n"
1847 								"OpMemberDecorate %block_out 1 RelaxedPrecision\n"
1848 								"OpMemberDecorate %block_in 0 RelaxedPrecision\n"
1849 								"OpMemberDecorate %block_in 1 RelaxedPrecision\n"));
1850 		epsilon = "2e-3";
1851 		break;
1852 	default:
1853 		DE_ASSERT(0);
1854 	}
1855 
1856 	//Spir-v spec: decoration flat can be used only in Shader (fragment or vertex)
1857 	for (deUint32 ndx = 0; ndx < decorations.size(); ++ndx)
1858 	{
1859 
1860 		/*#version 450
1861 		layout(location = 0) in highp vec4 in_position;
1862 		layout(location = 1) in vec4 in_color;
1863 		layout(location = 0) out vec4 out_color;
1864 		layout(location = 1) out ColorData
1865 		{
1866 		  vec4 colorVec;
1867 		  mat2 colorMat;
1868 		} outData;
1869 		void main (void)
1870 		{
1871 		  gl_Position = in_position;
1872 		  out_color = in_color;
1873 		  outData.colorVec = in_color;
1874 		  outData.colorMat = mat2(in_color.r, in_color.g, in_color.b, in_color.a);
1875 		}
1876 		*/
1877 		const string vertexShaderSource =
1878 		"; SPIR-V\n"
1879 		"; Version: 1.3\n"
1880 		"; Generator: Khronos Glslang Reference Front End; 2\n"
1881 		"; Bound: 51\n"
1882 		"; Schema: 0\n"
1883 		"OpCapability Shader\n"
1884 		"%1 = OpExtInstImport \"GLSL.std.450\"\n"
1885 		"OpMemoryModel Logical GLSL450\n"
1886 		"OpEntryPoint Vertex %4 \"main\" %13 %17 %color_out %color_in %28\n"
1887 		"OpMemberDecorate %11 0 BuiltIn Position\n"
1888 		"OpMemberDecorate %11 1 BuiltIn PointSize\n"
1889 		"OpMemberDecorate %11 2 BuiltIn ClipDistance\n"
1890 		"OpMemberDecorate %11 3 BuiltIn CullDistance\n"
1891 		"OpDecorate %11 Block\n"
1892 		"OpDecorate %17 Location 0\n"
1893 		"OpDecorate %color_out Location 0\n"
1894 		"OpDecorate %color_in Location 1\n"
1895 		"OpDecorate %block_out Block\n"
1896 		"OpDecorate %28 Location 1\n"
1897 		+decorations[ndx].vertex+
1898 		"%2 = OpTypeVoid\n"
1899 		"%3 = OpTypeFunction %2\n"
1900 		"%6 = OpTypeFloat 32\n"
1901 		"%7 = OpTypeVector %6 4\n"
1902 		"%8 = OpTypeInt 32 0\n"
1903 		"%9 = OpConstant %8 1\n"
1904 		"%10 = OpTypeArray %6 %9\n"
1905 		"%11 = OpTypeStruct %7 %6 %10 %10\n"
1906 		"%12 = OpTypePointer Output %11\n"
1907 		"%13 = OpVariable %12 Output\n"
1908 		"%14 = OpTypeInt 32 1\n"
1909 		"%15 = OpConstant %14 0\n"
1910 		"%16 = OpTypePointer Input %7\n"
1911 		"%17 = OpVariable %16 Input\n"
1912 		"%19 = OpTypePointer Output %7\n"
1913 		"%color_out = OpVariable %19 Output\n"
1914 		"%color_in = OpVariable %16 Input\n"
1915 		"%24 = OpTypeVector %6 2\n"
1916 		"%25 = OpTypeMatrix %24 2\n"
1917 		"%block_out = OpTypeStruct %7 %25\n"
1918 		"%27 = OpTypePointer Output %block_out\n"
1919 		"%28 = OpVariable %27 Output\n"
1920 		"%31 = OpConstant %14 1\n"
1921 		"%32 = OpConstant %8 0\n"
1922 		"%33 = OpTypePointer Input %6\n"
1923 		"%38 = OpConstant %8 2\n"
1924 		"%41 = OpConstant %8 3\n"
1925 		"%44 = OpConstant %6 1\n"
1926 		"%45 = OpConstant %6 0\n"
1927 		"%49 = OpTypePointer Output %25\n"
1928 		"%4 = OpFunction %2 None %3\n"
1929 		"%5 = OpLabel\n"
1930 		"%18 = OpLoad %7 %17\n"
1931 		"%20 = OpAccessChain %19 %13 %15\n"
1932 		"OpStore %20 %18\n"
1933 		"%23 = OpLoad %7 %color_in\n"
1934 		"OpStore %color_out %23\n"
1935 		"%29 = OpLoad %7 %color_in\n"
1936 		"%30 = OpAccessChain %19 %28 %15\n"
1937 		"OpStore %30 %29\n"
1938 		"%34 = OpAccessChain %33 %color_in %32\n"
1939 		"%35 = OpLoad %6 %34\n"
1940 		"%36 = OpAccessChain %33 %color_in %9\n"
1941 		"%37 = OpLoad %6 %36\n"
1942 		"%39 = OpAccessChain %33 %color_in %38\n"
1943 		"%40 = OpLoad %6 %39\n"
1944 		"%42 = OpAccessChain %33 %color_in %41\n"
1945 		"%43 = OpLoad %6 %42\n"
1946 		"%46 = OpCompositeConstruct %24 %35 %37\n"
1947 		"%47 = OpCompositeConstruct %24 %40 %43\n"
1948 		"%48 = OpCompositeConstruct %25 %46 %47\n"
1949 		"%50 = OpAccessChain %49 %28 %31\n"
1950 		"OpStore %50 %48\n"
1951 		"OpReturn\n"
1952 		"OpFunctionEnd\n";
1953 
1954 		/* #version 450
1955 		layout(location = 0) in vec4 in_color;
1956 		layout(location = 0) out vec4 out_color;
1957 		layout(location = 1) in ColorData
1958 		{
1959 		  vec4 colorVec;
1960 		  mat2 colorMat;
1961 		} inData;
1962 		void main()
1963 		{
1964 		  float epsilon = 3e-7; // or 0.0 for flat, or 2e-3 for RelaxedPrecision (mediump)
1965 		  out_color = in_color;
1966 		  vec4 epsilon_vec4 = max(abs(inData.colorVec), abs(in_color)) * epsilon;
1967 		  if(any(greaterThan(abs(inData.colorVec - in_color), epsilon_vec4)))
1968 		    out_color.rgba = vec4(1.0f);
1969 		  epsilon_vec4.r = max(abs(inData.colorMat[0][0]), abs(in_color.r)) * epsilon;
1970 		  if(abs(inData.colorMat[0][0] - in_color.r) > epsilon_vec4.r)
1971 		    out_color.rgba = vec4(1.0f);
1972 		  epsilon_vec4.a = max(abs(inData.colorMat[1][1]), abs(in_color.a)) * epsilon;
1973 		  if(abs(inData.colorMat[1][1] - in_color.a) > epsilon_vec4.a)
1974 		    out_color.rgba = vec4(1.0f);
1975 		}
1976 		*/
1977 		const string fragmentShaderSource =
1978 		"; SPIR-V\n"
1979 		"; Version: 1.3\n"
1980 		"; Generator: Khronos Glslang Reference Front End; 2\n"
1981 		"; Bound: 51\n"
1982 		"; Schema: 0\n"
1983 		"OpCapability Shader\n"
1984 		"%1 = OpExtInstImport \"GLSL.std.450\"\n"
1985 		"OpMemoryModel Logical GLSL450\n"
1986 		"OpEntryPoint Fragment %4 \"main\" %color_out %color_in %17\n"
1987 		"OpExecutionMode %4 OriginUpperLeft\n"
1988 		"OpDecorate %color_out Location 0\n"
1989 		"OpDecorate %color_in Location 0\n"
1990 		"OpDecorate %block_in Block\n"
1991 		"OpDecorate %17 Location 1\n"
1992 		+decorations[ndx].fragment+
1993 		"%2 = OpTypeVoid\n"
1994 		"%3 = OpTypeFunction %2\n"
1995 		"%6 = OpTypeFloat 32\n"
1996 		"%7 = OpTypeVector %6 4\n"
1997 		"%8 = OpTypePointer Output %7\n"
1998 		"%color_out = OpVariable %8 Output\n"
1999 		"%10 = OpTypePointer Input %7\n"
2000 		"%color_in = OpVariable %10 Input\n"
2001 		"%13 = OpTypeVector %6 2\n"
2002 		"%14 = OpTypeMatrix %13 2\n"
2003 		"%block_in = OpTypeStruct %7 %14\n"
2004 		"%16 = OpTypePointer Input %block_in\n"
2005 		"%17 = OpVariable %16 Input\n"
2006 		"%18 = OpTypeInt 32 1\n"
2007 		"%19 = OpConstant %18 0\n"
2008 		"%23 = OpTypeBool\n"
2009 		"%24 = OpTypeVector %23 4\n"
2010 		"%ep = OpConstant %6 " + epsilon + "\n"
2011 		"%ep4 = OpConstantComposite %7 %ep %ep %ep %ep\n"
2012 		"%29 = OpConstant %6 1\n"
2013 		"%30 = OpConstantComposite %7 %29 %29 %29 %29\n"
2014 		"%31 = OpConstant %18 1\n"
2015 		"%32 = OpTypeInt 32 0\n"
2016 		"%33 = OpConstant %32 0\n"
2017 		"%34 = OpTypePointer Input %6\n"
2018 		"%42 = OpConstant %32 1\n"
2019 		"%45 = OpConstant %32 3\n"
2020 		"%4 = OpFunction %2 None %3\n"
2021 		"%5 = OpLabel\n"
2022 		"%12 = OpLoad %7 %color_in\n"
2023 		"OpStore %color_out %12\n"
2024 		"%20 = OpAccessChain %10 %17 %19\n"
2025 		"%21 = OpLoad %7 %20\n"
2026 		"%22 = OpLoad %7 %color_in\n"
2027 		"%sub4 = OpFSub %7 %21 %22\n"
2028 		"%abs4 = OpExtInst %7 %1 FAbs %sub4\n"
2029 		"%ep4abs0 = OpExtInst %7 %1 FAbs %21\n"
2030 		"%ep4abs1 = OpExtInst %7 %1 FAbs %22\n"
2031 		"%ep4gt = OpFOrdGreaterThan %24 %ep4abs0 %ep4abs1\n"
2032 		"%ep4max = OpSelect %7 %ep4gt %ep4abs0 %ep4abs1\n"
2033 		"%ep4rel = OpFMul %7 %ep4max %ep4\n"
2034 		"%cmp4 = OpFOrdGreaterThan %24 %abs4 %ep4rel\n"
2035 		"%26 = OpAny %23 %cmp4\n"
2036 		"OpSelectionMerge %28 None\n"
2037 		"OpBranchConditional %26 %27 %28\n"
2038 		"%27 = OpLabel\n"
2039 		"OpStore %color_out %30\n"
2040 		"OpBranch %28\n"
2041 		"%28 = OpLabel\n"
2042 		"%35 = OpAccessChain %34 %17 %31 %19 %33\n"
2043 		"%36 = OpLoad %6 %35\n"
2044 		"%37 = OpAccessChain %34 %color_in %33\n"
2045 		"%38 = OpLoad %6 %37\n"
2046 		"%subr = OpFSub %6 %36 %38\n"
2047 		"%absr = OpExtInst %6 %1 FAbs %subr\n"
2048 		"%ep1abs0 = OpExtInst %6 %1 FAbs %36\n"
2049 		"%ep1abs1 = OpExtInst %6 %1 FAbs %38\n"
2050 		"%ep1gt = OpFOrdGreaterThan %23 %ep1abs0 %ep1abs1\n"
2051 		"%ep1max = OpSelect %6 %ep1gt %ep1abs0 %ep1abs1\n"
2052 		"%ep1rel = OpFMul %6 %ep1max %ep\n"
2053 		"%cmpr = OpFOrdGreaterThan %23 %absr %ep1rel\n"
2054 		"OpSelectionMerge %41 None\n"
2055 		"OpBranchConditional %cmpr %40 %41\n"
2056 		"%40 = OpLabel\n"
2057 		"OpStore %color_out %30\n"
2058 		"OpBranch %41\n"
2059 		"%41 = OpLabel\n"
2060 		"%43 = OpAccessChain %34 %17 %31 %31 %42\n"
2061 		"%44 = OpLoad %6 %43\n"
2062 		"%46 = OpAccessChain %34 %color_in %45\n"
2063 		"%47 = OpLoad %6 %46\n"
2064 		"%suba = OpFSub %6 %44 %47\n"
2065 		"%absa = OpExtInst %6 %1 FAbs %suba\n"
2066 		"%ep1babs0 = OpExtInst %6 %1 FAbs %44\n"
2067 		"%ep1babs1 = OpExtInst %6 %1 FAbs %47\n"
2068 		"%ep1bgt = OpFOrdGreaterThan %23 %ep1babs0 %ep1babs1\n"
2069 		"%ep1bmax = OpSelect %6 %ep1bgt %ep1babs0 %ep1babs1\n"
2070 		"%ep1brel = OpFMul %6 %ep1bmax %ep\n"
2071 		"%cmpa = OpFOrdGreaterThan %23 %absa %ep1brel\n"
2072 		"OpSelectionMerge %50 None\n"
2073 		"OpBranchConditional %cmpa %49 %50\n"
2074 		"%49 = OpLabel\n"
2075 		"OpStore %color_out %30\n"
2076 		"OpBranch %50\n"
2077 		"%50 = OpLabel\n"
2078 		"OpReturn\n"
2079 		"OpFunctionEnd\n";
2080 
2081 		std::ostringstream vertex;
2082 		vertex << "vertex" << ndx;
2083 		std::ostringstream fragment;
2084 		fragment << "fragment" << ndx;
2085 
2086 		programCollection.spirvAsmSources.add(vertex.str()) << vertexShaderSource;
2087 		programCollection.spirvAsmSources.add(fragment.str()) << fragmentShaderSource;
2088 	}
2089 	{
2090 		/*#version 450
2091 		#extension GL_EXT_tessellation_shader : require
2092 		layout(vertices = 4) out;
2093 		layout(location = 0) in vec4		in_color[];
2094 		layout(location = 1) in ColorData
2095 		{
2096 		  vec4 colorVec;
2097 		  mat2 colorMat;
2098 		} inData[];
2099 		layout(location = 0) out vec4		out_color[];
2100 		layout(location = 1) out ColorData
2101 		{
2102 		  vec4 colorVec;
2103 		  mat2 colorMat;
2104 		} outData[];
2105 		void main (void)
2106 		{
2107 			if ( gl_InvocationID == 0 )
2108 			{
2109 				gl_TessLevelInner[0] = 4.0f;
2110 				gl_TessLevelInner[1] = 4.0f;
2111 				gl_TessLevelOuter[0] = 4.0f;
2112 				gl_TessLevelOuter[1] = 4.0f;
2113 				gl_TessLevelOuter[2] = 4.0f;
2114 				gl_TessLevelOuter[3] = 4.0f;
2115 			}
2116 			out_color[gl_InvocationID] = in_color[gl_InvocationID];
2117 			outData[gl_InvocationID].colorVec = inData[gl_InvocationID].colorVec;
2118 			outData[gl_InvocationID].colorMat = inData[gl_InvocationID].colorMat;
2119 			gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
2120 		}*/
2121 
2122 		const string tessellationControlSource =
2123 		"; SPIR-V\n"
2124 		"; Version: 1.3\n"
2125 		"; Generator: Khronos Glslang Reference Front End; 2\n"
2126 		"; Bound: 88\n"
2127 		"; Schema: 0\n"
2128 		"OpCapability Tessellation\n"
2129 		"%1 = OpExtInstImport \"GLSL.std.450\"\n"
2130 		"OpMemoryModel Logical GLSL450\n"
2131 		"OpEntryPoint TessellationControl %4 \"main\" %8 %20 %29 %color_out %color_in %56 %61 %78 %83\n"
2132 		"OpExecutionMode %4 OutputVertices 4\n"
2133 		"OpDecorate %8 BuiltIn InvocationId\n"
2134 		"OpDecorate %20 Patch\n"
2135 		"OpDecorate %20 BuiltIn TessLevelInner\n"
2136 		"OpDecorate %29 Patch\n"
2137 		"OpDecorate %29 BuiltIn TessLevelOuter\n"
2138 		"OpDecorate %color_out Location 0\n"
2139 		"OpDecorate %color_in Location 0\n"
2140 		"OpDecorate %block_out Block\n"
2141 		"OpDecorate %56 Location 1\n"
2142 		"OpDecorate %block_in Block\n"
2143 		"OpDecorate %61 Location 1\n"
2144 		+decorations[0].others+
2145 		"OpMemberDecorate %75 0 BuiltIn Position\n"
2146 		"OpMemberDecorate %75 1 BuiltIn PointSize\n"
2147 		"OpMemberDecorate %75 2 BuiltIn ClipDistance\n"
2148 		"OpMemberDecorate %75 3 BuiltIn CullDistance\n"
2149 		"OpDecorate %75 Block\n"
2150 		"OpMemberDecorate %80 0 BuiltIn Position\n"
2151 		"OpMemberDecorate %80 1 BuiltIn PointSize\n"
2152 		"OpMemberDecorate %80 2 BuiltIn ClipDistance\n"
2153 		"OpMemberDecorate %80 3 BuiltIn CullDistance\n"
2154 		"OpDecorate %80 Block\n"
2155 		"%2 = OpTypeVoid\n"
2156 		"%3 = OpTypeFunction %2\n"
2157 		"%6 = OpTypeInt 32 1\n"
2158 		"%7 = OpTypePointer Input %6\n"
2159 		"%8 = OpVariable %7 Input\n"
2160 		"%10 = OpConstant %6 0\n"
2161 		"%11 = OpTypeBool\n"
2162 		"%15 = OpTypeFloat 32\n"
2163 		"%16 = OpTypeInt 32 0\n"
2164 		"%17 = OpConstant %16 2\n"
2165 		"%18 = OpTypeArray %15 %17\n"
2166 		"%19 = OpTypePointer Output %18\n"
2167 		"%20 = OpVariable %19 Output\n"
2168 		"%21 = OpConstant %15 4\n"
2169 		"%22 = OpTypePointer Output %15\n"
2170 		"%24 = OpConstant %6 1\n"
2171 		"%26 = OpConstant %16 4\n"
2172 		"%27 = OpTypeArray %15 %26\n"
2173 		"%28 = OpTypePointer Output %27\n"
2174 		"%29 = OpVariable %28 Output\n"
2175 		"%32 = OpConstant %6 2\n"
2176 		"%34 = OpConstant %6 3\n"
2177 		"%36 = OpTypeVector %15 4\n"
2178 		"%37 = OpTypeArray %36 %26\n"
2179 		"%38 = OpTypePointer Output %37\n"
2180 		"%color_out = OpVariable %38 Output\n"
2181 		"%41 = OpConstant %16 32\n"
2182 		"%42 = OpTypeArray %36 %41\n"
2183 		"%43 = OpTypePointer Input %42\n"
2184 		"%color_in = OpVariable %43 Input\n"
2185 		"%46 = OpTypePointer Input %36\n"
2186 		"%49 = OpTypePointer Output %36\n"
2187 		"%51 = OpTypeVector %15 2\n"
2188 		"%52 = OpTypeMatrix %51 2\n"
2189 		"%block_out = OpTypeStruct %36 %52\n"
2190 		"%54 = OpTypeArray %block_out %26\n"
2191 		"%55 = OpTypePointer Output %54\n"
2192 		"%56 = OpVariable %55 Output\n"
2193 		"%block_in = OpTypeStruct %36 %52\n"
2194 		"%59 = OpTypeArray %block_in %41\n"
2195 		"%60 = OpTypePointer Input %59\n"
2196 		"%61 = OpVariable %60 Input\n"
2197 		"%68 = OpTypePointer Input %52\n"
2198 		"%71 = OpTypePointer Output %52\n"
2199 		"%73 = OpConstant %16 1\n"
2200 		"%74 = OpTypeArray %15 %73\n"
2201 		"%75 = OpTypeStruct %36 %15 %74 %74\n"
2202 		"%76 = OpTypeArray %75 %26\n"
2203 		"%77 = OpTypePointer Output %76\n"
2204 		"%78 = OpVariable %77 Output\n"
2205 		"%80 = OpTypeStruct %36 %15 %74 %74\n"
2206 		"%81 = OpTypeArray %80 %41\n"
2207 		"%82 = OpTypePointer Input %81\n"
2208 		"%83 = OpVariable %82 Input\n"
2209 		"%4 = OpFunction %2 None %3\n"
2210 		"%5 = OpLabel\n"
2211 		"%9 = OpLoad %6 %8\n"
2212 		"%12 = OpIEqual %11 %9 %10\n"
2213 		"OpSelectionMerge %14 None\n"
2214 		"OpBranchConditional %12 %13 %14\n"
2215 		"%13 = OpLabel\n"
2216 		"%23 = OpAccessChain %22 %20 %10\n"
2217 		"OpStore %23 %21\n"
2218 		"%25 = OpAccessChain %22 %20 %24\n"
2219 		"OpStore %25 %21\n"
2220 		"%30 = OpAccessChain %22 %29 %10\n"
2221 		"OpStore %30 %21\n"
2222 		"%31 = OpAccessChain %22 %29 %24\n"
2223 		"OpStore %31 %21\n"
2224 		"%33 = OpAccessChain %22 %29 %32\n"
2225 		"OpStore %33 %21\n"
2226 		"%35 = OpAccessChain %22 %29 %34\n"
2227 		"OpStore %35 %21\n"
2228 		"OpBranch %14\n"
2229 		"%14 = OpLabel\n"
2230 		"%40 = OpLoad %6 %8\n"
2231 		"%45 = OpLoad %6 %8\n"
2232 		"%47 = OpAccessChain %46 %color_in %45\n"
2233 		"%48 = OpLoad %36 %47\n"
2234 		"%50 = OpAccessChain %49 %color_out %40\n"
2235 		"OpStore %50 %48\n"
2236 		"%57 = OpLoad %6 %8\n"
2237 		"%62 = OpLoad %6 %8\n"
2238 		"%63 = OpAccessChain %46 %61 %62 %10\n"
2239 		"%64 = OpLoad %36 %63\n"
2240 		"%65 = OpAccessChain %49 %56 %57 %10\n"
2241 		"OpStore %65 %64\n"
2242 		"%66 = OpLoad %6 %8\n"
2243 		"%67 = OpLoad %6 %8\n"
2244 		"%69 = OpAccessChain %68 %61 %67 %24\n"
2245 		"%70 = OpLoad %52 %69\n"
2246 		"%72 = OpAccessChain %71 %56 %66 %24\n"
2247 		"OpStore %72 %70\n"
2248 		"%79 = OpLoad %6 %8\n"
2249 		"%84 = OpLoad %6 %8\n"
2250 		"%85 = OpAccessChain %46 %83 %84 %10\n"
2251 		"%86 = OpLoad %36 %85\n"
2252 		"%87 = OpAccessChain %49 %78 %79 %10\n"
2253 		"OpStore %87 %86\n"
2254 		"OpReturn\n"
2255 		"OpFunctionEnd\n";
2256 
2257 		/*#version 450
2258 		#extension GL_EXT_tessellation_shader : require
2259 		layout( quads, equal_spacing, ccw ) in;
2260 		layout(location = 0) in vec4		in_color[];
2261 		layout(location = 1) in ColorData
2262 		{
2263 		  vec4 colorVec;
2264 		  mat2 colorMat;
2265 		} inData[];
2266 		layout(location = 0) out vec4		out_color;
2267 		layout(location = 1) out ColorData
2268 		{
2269 		  vec4 colorVec;
2270 		  mat2 colorMat;
2271 		} outData;
2272 		void main (void)
2273 		{
2274 			const float u = gl_TessCoord.x;
2275 			const float v = gl_TessCoord.y;
2276 			const float w = gl_TessCoord.z;
2277 			out_color = (1 - u) * (1 - v) * in_color[0] +(1 - u) * v * in_color[1] + u * (1 - v) * in_color[2] + u * v * in_color[3];
2278 			outData.colorVec = (1 - u) * (1 - v) * inData[0].colorVec +(1 - u) * v * inData[1].colorVec + u * (1 - v) * inData[2].colorVec + u * v * inData[3].colorVec;
2279 			outData.colorMat = (1 - u) * (1 - v) * inData[0].colorMat +(1 - u) * v * inData[1].colorMat + u * (1 - v) * inData[2].colorMat + u * v * inData[3].colorMat;
2280 			gl_Position = (1 - u) * (1 - v) * gl_in[0].gl_Position +(1 - u) * v * gl_in[1].gl_Position + u * (1 - v) * gl_in[2].gl_Position + u * v * gl_in[3].gl_Position;
2281 		}*/
2282 
2283 		const string tessellationEvaluationSource =
2284 		"; SPIR-V\n"
2285 		"; Version: 1.3\n"
2286 		"; Generator: Khronos Glslang Reference Front End; 2\n"
2287 		"; Bound: 203\n"
2288 		"; Schema: 0\n"
2289 		"OpCapability Tessellation\n"
2290 		"%1 = OpExtInstImport \"GLSL.std.450\"\n"
2291 		"OpMemoryModel Logical GLSL450\n"
2292 		"OpEntryPoint TessellationEvaluation %4 \"main\" %11 %color_out %color_in %74 %83 %166 %175\n"
2293 		"OpExecutionMode %4 Quads\n"
2294 		"OpExecutionMode %4 SpacingEqual\n"
2295 		"OpExecutionMode %4 VertexOrderCcw\n"
2296 		"OpDecorate %11 BuiltIn TessCoord\n"
2297 		"OpDecorate %color_out Location 0\n"
2298 		"OpDecorate %color_in Location 0\n"
2299 		"OpDecorate %block_out Block\n"
2300 		"OpDecorate %74 Location 1\n"
2301 		"OpDecorate %block_in Block\n"
2302 		"OpDecorate %83 Location 1\n"
2303 		+decorations[0].others+
2304 		"OpMemberDecorate %164 0 BuiltIn Position\n"
2305 		"OpMemberDecorate %164 1 BuiltIn PointSize\n"
2306 		"OpMemberDecorate %164 2 BuiltIn ClipDistance\n"
2307 		"OpMemberDecorate %164 3 BuiltIn CullDistance\n"
2308 		"OpDecorate %164 Block\n"
2309 		"OpMemberDecorate %172 0 BuiltIn Position\n"
2310 		"OpMemberDecorate %172 1 BuiltIn PointSize\n"
2311 		"OpMemberDecorate %172 2 BuiltIn ClipDistance\n"
2312 		"OpMemberDecorate %172 3 BuiltIn CullDistance\n"
2313 		"OpDecorate %172 Block\n"
2314 		"%2 = OpTypeVoid\n"
2315 		"%3 = OpTypeFunction %2\n"
2316 		"%6 = OpTypeFloat 32\n"
2317 		"%7 = OpTypePointer Function %6\n"
2318 		"%9 = OpTypeVector %6 3\n"
2319 		"%10 = OpTypePointer Input %9\n"
2320 		"%11 = OpVariable %10 Input\n"
2321 		"%12 = OpTypeInt 32 0\n"
2322 		"%13 = OpConstant %12 0\n"
2323 		"%14 = OpTypePointer Input %6\n"
2324 		"%18 = OpConstant %12 1\n"
2325 		"%22 = OpConstant %12 2\n"
2326 		"%25 = OpTypeVector %6 4\n"
2327 		"%26 = OpTypePointer Output %25\n"
2328 		"%color_out = OpVariable %26 Output\n"
2329 		"%28 = OpConstant %6 1\n"
2330 		"%34 = OpConstant %12 32\n"
2331 		"%35 = OpTypeArray %25 %34\n"
2332 		"%36 = OpTypePointer Input %35\n"
2333 		"%color_in = OpVariable %36 Input\n"
2334 		"%38 = OpTypeInt 32 1\n"
2335 		"%39 = OpConstant %38 0\n"
2336 		"%40 = OpTypePointer Input %25\n"
2337 		"%48 = OpConstant %38 1\n"
2338 		"%57 = OpConstant %38 2\n"
2339 		"%65 = OpConstant %38 3\n"
2340 		"%70 = OpTypeVector %6 2\n"
2341 		"%71 = OpTypeMatrix %70 2\n"
2342 		"%block_out = OpTypeStruct %25 %71\n"
2343 		"%73 = OpTypePointer Output %block_out\n"
2344 		"%74 = OpVariable %73 Output\n"
2345 		"%block_in = OpTypeStruct %25 %71\n"
2346 		"%81 = OpTypeArray %block_in %34\n"
2347 		"%82 = OpTypePointer Input %81\n"
2348 		"%83 = OpVariable %82 Input\n"
2349 		"%116 = OpTypePointer Input %71\n"
2350 		"%161 = OpTypePointer Output %71\n"
2351 		"%163 = OpTypeArray %6 %18\n"
2352 		"%164 = OpTypeStruct %25 %6 %163 %163\n"
2353 		"%165 = OpTypePointer Output %164\n"
2354 		"%166 = OpVariable %165 Output\n"
2355 		"%172 = OpTypeStruct %25 %6 %163 %163\n"
2356 		"%173 = OpTypeArray %172 %34\n"
2357 		"%174 = OpTypePointer Input %173\n"
2358 		"%175 = OpVariable %174 Input\n"
2359 		"%4 = OpFunction %2 None %3\n"
2360 		"%5 = OpLabel\n"
2361 		"%8 = OpVariable %7 Function\n"
2362 		"%17 = OpVariable %7 Function\n"
2363 		"%21 = OpVariable %7 Function\n"
2364 		"%15 = OpAccessChain %14 %11 %13\n"
2365 		"%16 = OpLoad %6 %15\n"
2366 		"OpStore %8 %16\n"
2367 		"%19 = OpAccessChain %14 %11 %18\n"
2368 		"%20 = OpLoad %6 %19\n"
2369 		"OpStore %17 %20\n"
2370 		"%23 = OpAccessChain %14 %11 %22\n"
2371 		"%24 = OpLoad %6 %23\n"
2372 		"OpStore %21 %24\n"
2373 		"%29 = OpLoad %6 %8\n"
2374 		"%30 = OpFSub %6 %28 %29\n"
2375 		"%31 = OpLoad %6 %17\n"
2376 		"%32 = OpFSub %6 %28 %31\n"
2377 		"%33 = OpFMul %6 %30 %32\n"
2378 		"%41 = OpAccessChain %40 %color_in %39\n"
2379 		"%42 = OpLoad %25 %41\n"
2380 		"%43 = OpVectorTimesScalar %25 %42 %33\n"
2381 		"%44 = OpLoad %6 %8\n"
2382 		"%45 = OpFSub %6 %28 %44\n"
2383 		"%46 = OpLoad %6 %17\n"
2384 		"%47 = OpFMul %6 %45 %46\n"
2385 		"%49 = OpAccessChain %40 %color_in %48\n"
2386 		"%50 = OpLoad %25 %49\n"
2387 		"%51 = OpVectorTimesScalar %25 %50 %47\n"
2388 		"%52 = OpFAdd %25 %43 %51\n"
2389 		"%53 = OpLoad %6 %8\n"
2390 		"%54 = OpLoad %6 %17\n"
2391 		"%55 = OpFSub %6 %28 %54\n"
2392 		"%56 = OpFMul %6 %53 %55\n"
2393 		"%58 = OpAccessChain %40 %color_in %57\n"
2394 		"%59 = OpLoad %25 %58\n"
2395 		"%60 = OpVectorTimesScalar %25 %59 %56\n"
2396 		"%61 = OpFAdd %25 %52 %60\n"
2397 		"%62 = OpLoad %6 %8\n"
2398 		"%63 = OpLoad %6 %17\n"
2399 		"%64 = OpFMul %6 %62 %63\n"
2400 		"%66 = OpAccessChain %40 %color_in %65\n"
2401 		"%67 = OpLoad %25 %66\n"
2402 		"%68 = OpVectorTimesScalar %25 %67 %64\n"
2403 		"%69 = OpFAdd %25 %61 %68\n"
2404 		"OpStore %color_out %69\n"
2405 		"%75 = OpLoad %6 %8\n"
2406 		"%76 = OpFSub %6 %28 %75\n"
2407 		"%77 = OpLoad %6 %17\n"
2408 		"%78 = OpFSub %6 %28 %77\n"
2409 		"%79 = OpFMul %6 %76 %78\n"
2410 		"%84 = OpAccessChain %40 %83 %39 %39\n"
2411 		"%85 = OpLoad %25 %84\n"
2412 		"%86 = OpVectorTimesScalar %25 %85 %79\n"
2413 		"%87 = OpLoad %6 %8\n"
2414 		"%88 = OpFSub %6 %28 %87\n"
2415 		"%89 = OpLoad %6 %17\n"
2416 		"%90 = OpFMul %6 %88 %89\n"
2417 		"%91 = OpAccessChain %40 %83 %48 %39\n"
2418 		"%92 = OpLoad %25 %91\n"
2419 		"%93 = OpVectorTimesScalar %25 %92 %90\n"
2420 		"%94 = OpFAdd %25 %86 %93\n"
2421 		"%95 = OpLoad %6 %8\n"
2422 		"%96 = OpLoad %6 %17\n"
2423 		"%97 = OpFSub %6 %28 %96\n"
2424 		"%98 = OpFMul %6 %95 %97\n"
2425 		"%99 = OpAccessChain %40 %83 %57 %39\n"
2426 		"%100 = OpLoad %25 %99\n"
2427 		"%101 = OpVectorTimesScalar %25 %100 %98\n"
2428 		"%102 = OpFAdd %25 %94 %101\n"
2429 		"%103 = OpLoad %6 %8\n"
2430 		"%104 = OpLoad %6 %17\n"
2431 		"%105 = OpFMul %6 %103 %104\n"
2432 		"%106 = OpAccessChain %40 %83 %65 %39\n"
2433 		"%107 = OpLoad %25 %106\n"
2434 		"%108 = OpVectorTimesScalar %25 %107 %105\n"
2435 		"%109 = OpFAdd %25 %102 %108\n"
2436 		"%110 = OpAccessChain %26 %74 %39\n"
2437 		"OpStore %110 %109\n"
2438 		"%111 = OpLoad %6 %8\n"
2439 		"%112 = OpFSub %6 %28 %111\n"
2440 		"%113 = OpLoad %6 %17\n"
2441 		"%114 = OpFSub %6 %28 %113\n"
2442 		"%115 = OpFMul %6 %112 %114\n"
2443 		"%117 = OpAccessChain %116 %83 %39 %48\n"
2444 		"%118 = OpLoad %71 %117\n"
2445 		"%119 = OpMatrixTimesScalar %71 %118 %115\n"
2446 		"%120 = OpLoad %6 %8\n"
2447 		"%121 = OpFSub %6 %28 %120\n"
2448 		"%122 = OpLoad %6 %17\n"
2449 		"%123 = OpFMul %6 %121 %122\n"
2450 		"%124 = OpAccessChain %116 %83 %48 %48\n"
2451 		"%125 = OpLoad %71 %124\n"
2452 		"%126 = OpMatrixTimesScalar %71 %125 %123\n"
2453 		"%127 = OpCompositeExtract %70 %119 0\n"
2454 		"%128 = OpCompositeExtract %70 %126 0\n"
2455 		"%129 = OpFAdd %70 %127 %128\n"
2456 		"%130 = OpCompositeExtract %70 %119 1\n"
2457 		"%131 = OpCompositeExtract %70 %126 1\n"
2458 		"%132 = OpFAdd %70 %130 %131\n"
2459 		"%133 = OpCompositeConstruct %71 %129 %132\n"
2460 		"%134 = OpLoad %6 %8\n"
2461 		"%135 = OpLoad %6 %17\n"
2462 		"%136 = OpFSub %6 %28 %135\n"
2463 		"%137 = OpFMul %6 %134 %136\n"
2464 		"%138 = OpAccessChain %116 %83 %57 %48\n"
2465 		"%139 = OpLoad %71 %138\n"
2466 		"%140 = OpMatrixTimesScalar %71 %139 %137\n"
2467 		"%141 = OpCompositeExtract %70 %133 0\n"
2468 		"%142 = OpCompositeExtract %70 %140 0\n"
2469 		"%143 = OpFAdd %70 %141 %142\n"
2470 		"%144 = OpCompositeExtract %70 %133 1\n"
2471 		"%145 = OpCompositeExtract %70 %140 1\n"
2472 		"%146 = OpFAdd %70 %144 %145\n"
2473 		"%147 = OpCompositeConstruct %71 %143 %146\n"
2474 		"%148 = OpLoad %6 %8\n"
2475 		"%149 = OpLoad %6 %17\n"
2476 		"%150 = OpFMul %6 %148 %149\n"
2477 		"%151 = OpAccessChain %116 %83 %65 %48\n"
2478 		"%152 = OpLoad %71 %151\n"
2479 		"%153 = OpMatrixTimesScalar %71 %152 %150\n"
2480 		"%154 = OpCompositeExtract %70 %147 0\n"
2481 		"%155 = OpCompositeExtract %70 %153 0\n"
2482 		"%156 = OpFAdd %70 %154 %155\n"
2483 		"%157 = OpCompositeExtract %70 %147 1\n"
2484 		"%158 = OpCompositeExtract %70 %153 1\n"
2485 		"%159 = OpFAdd %70 %157 %158\n"
2486 		"%160 = OpCompositeConstruct %71 %156 %159\n"
2487 		"%162 = OpAccessChain %161 %74 %48\n"
2488 		"OpStore %162 %160\n"
2489 		"%167 = OpLoad %6 %8\n"
2490 		"%168 = OpFSub %6 %28 %167\n"
2491 		"%169 = OpLoad %6 %17\n"
2492 		"%170 = OpFSub %6 %28 %169\n"
2493 		"%171 = OpFMul %6 %168 %170\n"
2494 		"%176 = OpAccessChain %40 %175 %39 %39\n"
2495 		"%177 = OpLoad %25 %176\n"
2496 		"%178 = OpVectorTimesScalar %25 %177 %171\n"
2497 		"%179 = OpLoad %6 %8\n"
2498 		"%180 = OpFSub %6 %28 %179\n"
2499 		"%181 = OpLoad %6 %17\n"
2500 		"%182 = OpFMul %6 %180 %181\n"
2501 		"%183 = OpAccessChain %40 %175 %48 %39\n"
2502 		"%184 = OpLoad %25 %183\n"
2503 		"%185 = OpVectorTimesScalar %25 %184 %182\n"
2504 		"%186 = OpFAdd %25 %178 %185\n"
2505 		"%187 = OpLoad %6 %8\n"
2506 		"%188 = OpLoad %6 %17\n"
2507 		"%189 = OpFSub %6 %28 %188\n"
2508 		"%190 = OpFMul %6 %187 %189\n"
2509 		"%191 = OpAccessChain %40 %175 %57 %39\n"
2510 		"%192 = OpLoad %25 %191\n"
2511 		"%193 = OpVectorTimesScalar %25 %192 %190\n"
2512 		"%194 = OpFAdd %25 %186 %193\n"
2513 		"%195 = OpLoad %6 %8\n"
2514 		"%196 = OpLoad %6 %17\n"
2515 		"%197 = OpFMul %6 %195 %196\n"
2516 		"%198 = OpAccessChain %40 %175 %65 %39\n"
2517 		"%199 = OpLoad %25 %198\n"
2518 		"%200 = OpVectorTimesScalar %25 %199 %197\n"
2519 		"%201 = OpFAdd %25 %194 %200\n"
2520 		"%202 = OpAccessChain %26 %166 %39\n"
2521 		"OpStore %202 %201\n"
2522 		"OpReturn\n"
2523 		"OpFunctionEnd\n";
2524 		programCollection.spirvAsmSources.add("tessellation_control") << tessellationControlSource;
2525 		programCollection.spirvAsmSources.add("tessellation_evaluation") << tessellationEvaluationSource;
2526 	}
2527 	{
2528 
2529 		/*#version 450
2530 		layout(triangles) in;
2531 		layout(triangle_strip, max_vertices = 3) out;
2532 		layout(location = 0) in vec4		in_color[];
2533 		layout(location = 1) in ColorData
2534 		{
2535 		  vec4 colorVec;
2536 		  mat2 colorMat;
2537 		} inData[];
2538 		layout(location = 0) out vec4		out_color;
2539 		layout(location = 1) out ColorData
2540 		{
2541 		  vec4 colorVec;
2542 		  mat2 colorMat;
2543 		} outData;
2544 		void main (void)
2545 		{
2546 			out_color = in_color[0];
2547 			outData.colorVec = inData[0].colorVec;
2548 			outData.colorMat = inData[0].colorMat;
2549 			gl_Position = gl_in[0].gl_Position;
2550 			EmitVertex();
2551 			out_color = in_color[1];
2552 			outData.colorVec = inData[1].colorVec;
2553 			outData.colorMat = inData[1].colorMat;
2554 			gl_Position = gl_in[1].gl_Position;
2555 			EmitVertex();
2556 			out_color = in_color[2];
2557 			outData.colorVec = inData[2].colorVec;
2558 			outData.colorMat = inData[2].colorMat;
2559 			gl_Position = gl_in[2].gl_Position;
2560 			EmitVertex();
2561 			EndPrimitive();
2562 		}*/
2563 		const string geometrySource =
2564 		"; SPIR-V\n"
2565 		"; Version: 1.3\n"
2566 		"; Generator: Khronos Glslang Reference Front End; 2\n"
2567 		"; Bound: 73\n"
2568 		"; Schema: 0\n"
2569 		"OpCapability Geometry\n"
2570 		"%1 = OpExtInstImport \"GLSL.std.450\"\n"
2571 		"OpMemoryModel Logical GLSL450\n"
2572 		"OpEntryPoint Geometry %4 \"main\" %color_out %color_in %24 %28 %42 %46\n"
2573 		"OpExecutionMode %4 Triangles\n"
2574 		"OpExecutionMode %4 Invocations 1\n"
2575 		"OpExecutionMode %4 OutputTriangleStrip\n"
2576 		"OpExecutionMode %4 OutputVertices 3\n"
2577 		"OpDecorate %color_out Location 0\n"
2578 		"OpDecorate %color_in Location 0\n"
2579 		"OpDecorate %block_out Block\n"
2580 		"OpDecorate %24 Location 1\n"
2581 		"OpDecorate %block_in Block\n"
2582 		"OpDecorate %28 Location 1\n"
2583 		+decorations[0].others+
2584 		"OpMemberDecorate %40 0 BuiltIn Position\n"
2585 		"OpMemberDecorate %40 1 BuiltIn PointSize\n"
2586 		"OpMemberDecorate %40 2 BuiltIn ClipDistance\n"
2587 		"OpMemberDecorate %40 3 BuiltIn CullDistance\n"
2588 		"OpDecorate %40 Block\n"
2589 		"OpMemberDecorate %43 0 BuiltIn Position\n"
2590 		"OpMemberDecorate %43 1 BuiltIn PointSize\n"
2591 		"OpMemberDecorate %43 2 BuiltIn ClipDistance\n"
2592 		"OpMemberDecorate %43 3 BuiltIn CullDistance\n"
2593 		"OpDecorate %43 Block\n"
2594 		"%2 = OpTypeVoid\n"
2595 		"%3 = OpTypeFunction %2\n"
2596 		"%6 = OpTypeFloat 32\n"
2597 		"%7 = OpTypeVector %6 4\n"
2598 		"%8 = OpTypePointer Output %7\n"
2599 		"%color_out = OpVariable %8 Output\n"
2600 		"%10 = OpTypeInt 32 0\n"
2601 		"%11 = OpConstant %10 3\n"
2602 		"%12 = OpTypeArray %7 %11\n"
2603 		"%13 = OpTypePointer Input %12\n"
2604 		"%color_in = OpVariable %13 Input\n"
2605 		"%15 = OpTypeInt 32 1\n"
2606 		"%16 = OpConstant %15 0\n"
2607 		"%17 = OpTypePointer Input %7\n"
2608 		"%20 = OpTypeVector %6 2\n"
2609 		"%21 = OpTypeMatrix %20 2\n"
2610 		"%block_out = OpTypeStruct %7 %21\n"
2611 		"%23 = OpTypePointer Output %block_out\n"
2612 		"%24 = OpVariable %23 Output\n"
2613 		"%block_in = OpTypeStruct %7 %21\n"
2614 		"%26 = OpTypeArray %block_in %11\n"
2615 		"%27 = OpTypePointer Input %26\n"
2616 		"%28 = OpVariable %27 Input\n"
2617 		"%32 = OpConstant %15 1\n"
2618 		"%33 = OpTypePointer Input %21\n"
2619 		"%36 = OpTypePointer Output %21\n"
2620 		"%38 = OpConstant %10 1\n"
2621 		"%39 = OpTypeArray %6 %38\n"
2622 		"%40 = OpTypeStruct %7 %6 %39 %39\n"
2623 		"%41 = OpTypePointer Output %40\n"
2624 		"%42 = OpVariable %41 Output\n"
2625 		"%43 = OpTypeStruct %7 %6 %39 %39\n"
2626 		"%44 = OpTypeArray %43 %11\n"
2627 		"%45 = OpTypePointer Input %44\n"
2628 		"%46 = OpVariable %45 Input\n"
2629 		"%61 = OpConstant %15 2\n"
2630 		"%4 = OpFunction %2 None %3\n"
2631 		"%5 = OpLabel\n"
2632 		"%18 = OpAccessChain %17 %color_in %16\n"
2633 		"%19 = OpLoad %7 %18\n"
2634 		"OpStore %color_out %19\n"
2635 		"%29 = OpAccessChain %17 %28 %16 %16\n"
2636 		"%30 = OpLoad %7 %29\n"
2637 		"%31 = OpAccessChain %8 %24 %16\n"
2638 		"OpStore %31 %30\n"
2639 		"%34 = OpAccessChain %33 %28 %16 %32\n"
2640 		"%35 = OpLoad %21 %34\n"
2641 		"%37 = OpAccessChain %36 %24 %32\n"
2642 		"OpStore %37 %35\n"
2643 		"%47 = OpAccessChain %17 %46 %16 %16\n"
2644 		"%48 = OpLoad %7 %47\n"
2645 		"%49 = OpAccessChain %8 %42 %16\n"
2646 		"OpStore %49 %48\n"
2647 		"OpEmitVertex\n"
2648 		"%50 = OpAccessChain %17 %color_in %32\n"
2649 		"%51 = OpLoad %7 %50\n"
2650 		"OpStore %color_out %51\n"
2651 		"%52 = OpAccessChain %17 %28 %32 %16\n"
2652 		"%53 = OpLoad %7 %52\n"
2653 		"%54 = OpAccessChain %8 %24 %16\n"
2654 		"OpStore %54 %53\n"
2655 		"%55 = OpAccessChain %33 %28 %32 %32\n"
2656 		"%56 = OpLoad %21 %55\n"
2657 		"%57 = OpAccessChain %36 %24 %32\n"
2658 		"OpStore %57 %56\n"
2659 		"%58 = OpAccessChain %17 %46 %32 %16\n"
2660 		"%59 = OpLoad %7 %58\n"
2661 		"%60 = OpAccessChain %8 %42 %16\n"
2662 		"OpStore %60 %59\n"
2663 		"OpEmitVertex\n"
2664 		"%62 = OpAccessChain %17 %color_in %61\n"
2665 		"%63 = OpLoad %7 %62\n"
2666 		"OpStore %color_out %63\n"
2667 		"%64 = OpAccessChain %17 %28 %61 %16\n"
2668 		"%65 = OpLoad %7 %64\n"
2669 		"%66 = OpAccessChain %8 %24 %16\n"
2670 		"OpStore %66 %65\n"
2671 		"%67 = OpAccessChain %33 %28 %61 %32\n"
2672 		"%68 = OpLoad %21 %67\n"
2673 		"%69 = OpAccessChain %36 %24 %32\n"
2674 		"OpStore %69 %68\n"
2675 		"%70 = OpAccessChain %17 %46 %61 %16\n"
2676 		"%71 = OpLoad %7 %70\n"
2677 		"%72 = OpAccessChain %8 %42 %16\n"
2678 		"OpStore %72 %71\n"
2679 		"OpEmitVertex\n"
2680 		"OpEndPrimitive\n"
2681 		"OpReturn\n"
2682 		"OpFunctionEnd\n";
2683 		programCollection.spirvAsmSources.add("geometry") << geometrySource;
2684 	}
2685 }
2686 } // anonymous
2687 
createCrossStageInterfaceTests(tcu::TestContext & testCtx)2688 tcu::TestCaseGroup* createCrossStageInterfaceTests (tcu::TestContext& testCtx)
2689 {
2690 	de::MovePtr<tcu::TestCaseGroup>		testGroup(new tcu::TestCaseGroup(testCtx, "cross_stage", ""));
2691 	{
2692 		de::MovePtr<tcu::TestCaseGroup>		basicGroup(new tcu::TestCaseGroup(testCtx, "basic_type", ""));
2693 		de::MovePtr<tcu::TestCaseGroup>		interfaceGroup(new tcu::TestCaseGroup(testCtx, "interface_blocks", ""));
2694 		{
2695 			TestParameters parm(TEST_TYPE_FLAT,3);
2696 			for (int ndx = 0; ndx < CrossStageTestInstance::DECORATION_LAST; ++ndx)
2697 				parm.testOptions[ndx] = ndx;
2698 
2699 			basicGroup->addChild(new CrossStageBasicTestsCase(testCtx, "flat", "", parm));
2700 			interfaceGroup->addChild(new CrossStageInterfaceTestsCase(testCtx, "flat", "", parm));
2701 
2702 			parm.qualifier = TEST_TYPE_NOPERSPECTIVE;
2703 			basicGroup->addChild(new CrossStageBasicTestsCase(testCtx, "no_perspective", "", parm));
2704 			interfaceGroup->addChild(new CrossStageInterfaceTestsCase(testCtx, "no_perspective", "", parm));
2705 		}
2706 
2707 		{
2708 			TestParameters parm(TEST_TYPE_RELAXEDPRECISION,1);
2709 			parm.testOptions[0] = CrossStageTestInstance::DECORATION_IN_ALL_SHADERS;
2710 			basicGroup->addChild(new CrossStageBasicTestsCase(testCtx, "relaxedprecision", "", parm));
2711 			interfaceGroup->addChild(new CrossStageInterfaceTestsCase(testCtx, "relaxedprecision", "", parm));
2712 		}
2713 		testGroup->addChild(basicGroup.release());
2714 		testGroup->addChild(interfaceGroup.release());
2715 	}
2716 
2717 	return testGroup.release();
2718 }
2719 
2720 } // SpirVAssembly
2721 } // vkt
2722